0

The event is getting stored in the event store but not getting persisted in the Entity table.

My Controller method

    @PostMapping("/saveProduct")
    public ResponseEntity<Void> productCreator(@RequestBody CreateProductModel createProductModel){
        
        CreateProductCommand createProductCommand = CreateProductCommand.builder().
                productId(UUID.randomUUID().toString()).
                title(createProductModel.getTitle()).
                description(createProductModel.getDescription()).
                price(createProductModel.getPrice()).
                discountPercentage(createProductModel.getDiscountPercentage()).
                available(createProductModel.isAvailable()).build();
        try {
            commandGateway.sendAndWait(createProductCommand);
        }catch(Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

Aggregate Class

@Aggregate
public class ProductAggregate {
    
    @AggregateIdentifier
    private String productId;
    private String title;
    private String description;
    private int price;
    private short discountPercentage;
    private boolean available;
    
    public ProductAggregate() {
        //leave it blank always
    }
    
    @CommandHandler
    public ProductAggregate(CreateProductCommand createProductCommand) {
        ProductCreatedEvent productCreatedEvent = new ProductCreatedEvent();
        BeanUtils.copyProperties(createProductCommand, productCreatedEvent);
        AggregateLifecycle.apply(productCreatedEvent);
    }
    
    @EventSourcingHandler
    public void on(ProductCreatedEvent productCreatedEvent) {
        this.productId = productCreatedEvent.getProductId();
        this.title =  productCreatedEvent.getTitle();
        this.description = productCreatedEvent.getDescription();
        this.price = productCreatedEvent.getPrice();
        this.discountPercentage = productCreatedEvent.getDiscountPercentage();
        this.available = productCreatedEvent.isAvailable();
    }
}

But this below class's method public void on(ProductCreatedEvent productCreatedEvent) is not getting called because of which the events are getting stored in event store but not getting persisted. Can someone help why this is happening?

@Service
public class ProductEventsHandler {

    private final ProductRepo productRepo;
    
    public ProductEventsHandler(ProductRepo productRepo) {
        this.productRepo = productRepo;
    }
    
    @EventHandler
    public void on(ProductCreatedEvent productCreatedEvent) {
        //1. Create object of entity
        Product product = new Product();
        //2. Copy from productCreatedEvent(event) to entity 
        BeanUtils.copyProperties(productCreatedEvent, product);
        //3. repository.save(entity);
        productRepo.save(product);
    }   
    
}

Also, I am getting an exception while running the application as below :

2021-11-07 00:19:20.677  INFO 6668 --- [           main] com.netflix.discovery.DiscoveryClient    : Initializing Eureka in region us-east-1
2021-11-07 00:19:20.719  INFO 6668 --- [           main] c.n.d.s.r.aws.ConfigClusterResolver      : Resolving eureka endpoints via configuration
2021-11-07 00:19:20.782  WARN 6668 --- [s.CQRS.query]-0] o.a.e.TrackingEventProcessor             : Error occurred. Starting retry mode.
com.thoughtworks.xstream.security.ForbiddenClassException: com.solinvictus.Products.CQRS.events.ProductCreatedEvent
    at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26) ~[xstream-1.4.18.jar:1.4.18]
    at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:74) ~[xstream-1.4.18.jar:1.4.18]
    at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) ~[xstream-1.4.18.jar:1.4.18]
    at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47) ~[xstream-1.4.18.jar:1.4.18]
    at org.axonframework.serialization.AbstractXStreamSerializer.classForType(AbstractXStreamSerializer.java:159) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.serialization.LazyDeserializingObject.<init>(LazyDeserializingObject.java:83) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.EventUtils.lambda$upcastAndDeserializeTrackedEvents$1(EventUtils.java:99) ~[axon-messaging-4.2.jar:4.2]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_202]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_202]
    at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine$EventStreamSpliterator.tryAdvance(BatchingEventStorageEngine.java:242) ~[axon-eventsourcing-4.2.jar:4.2]
    at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294) ~[na:1.8.0_202]
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206) ~[na:1.8.0_202]
    at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161) ~[na:1.8.0_202]
    at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300) ~[na:1.8.0_202]
    at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) ~[na:1.8.0_202]
    at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peekPrivateStream(EmbeddedEventStore.java:397) ~[axon-eventsourcing-4.2.jar:4.2]
    at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peek(EmbeddedEventStore.java:356) ~[axon-eventsourcing-4.2.jar:4.2]
    at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.hasNextAvailable(EmbeddedEventStore.java:333) ~[axon-eventsourcing-4.2.jar:4.2]
    at org.axonframework.common.stream.BlockingStream.hasNextAvailable(BlockingStream.java:40) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.TrackingEventProcessor.checkSegmentCaughtUp(TrackingEventProcessor.java:464) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.TrackingEventProcessor.processBatch(TrackingEventProcessor.java:351) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.TrackingEventProcessor.processingLoop(TrackingEventProcessor.java:275) ~[axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.TrackingEventProcessor$TrackingSegmentWorker.run(TrackingEventProcessor.java:1071) [axon-messaging-4.2.jar:4.2]
    at org.axonframework.eventhandling.TrackingEventProcessor$WorkerLauncher.run(TrackingEventProcessor.java:1183) [axon-messaging-4.2.jar:4.2]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_202]
Aayush Sahu
  • 126
  • 1
  • 1
  • 10
  • To make it easy next time, always state which versions you are using.. specially AxonFramework in this case! Since you already found the problem, I am not going to write a full answer but just a comment stating that there is a lot going on with XStream at the moment and because of that, you should provide your own instance with the given security context you allow. That will be automatically done for you in the following versions of AF but as it is at the moment, you need to provide it yourself. – Lucas Campos Nov 23 '21 at 09:54

2 Answers2

1

You've encountered a failure in Axon's upcaster because of a ForbiddenClassException thrown by XStream.

2021-11-07 00:19:20.782  WARN 6668 --- [s.CQRS.query]-0] o.a.e.TrackingEventProcessor             : Error occurred. Starting retry mode.
com.thoughtworks.xstream.security.ForbiddenClassException: com.solinvictus.Products.CQRS.events.ProductCreatedEvent

To solve this you should allow XStream for your event classes to be serialized as stated in this answer

  • Thanks for the help. Tried all the approaches mentioned but none of them seems to work in my case. Still getting the same exception. – Aayush Sahu Nov 14 '21 at 10:26
1

There were two issues that I found in my code :

  1. The issue was with XStream so I excluded the Xstream dependency from the axon framework and added the XStream dependency myself ().
         <dependency>
            <groupId>org.axonframework</groupId>
            <artifactId>axon-spring-boot-starter</artifactId>
            <version>4.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.axonframework</groupId>
                    <artifactId>axon-server-connector</artifactId>
                </exclusion>

                <exclusion>
                    <groupId>com.thoughtworks.xstream</groupId>
                    <artifactId>xstream</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.17</version>
        </dependency>
  1. The silly one: I had annotated the "id" field of the entity class with @GeneratedValue and since I was populating the value using UUID that was causing the error. It was causing the error. I didn't notice this issue until I did the 1st fix(mentioned above)
Aayush Sahu
  • 126
  • 1
  • 1
  • 10