0
votes

I am learning how to use the axon framework for event sourcing, seems to be going good but I have gotten stuck on the database configuration for event sourcing. From what I understood from docs / other articles, the database table should automatically generate.

I first tried with H2, the database table was generated by itself, everything working fine. I added my own mysql db, and the database table is not being created.. I'm getting the error

'Table 'producttest.domain_event_entry' doesn't exist

I was under the impression that the table will generate itself, I must be doing something wrong here, but I'm unsure what. Could anyone help me please?

My code:

ProductAggregate class

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.eventsourcing.EventSourcingHandler;
import org.axonframework.modelling.command.AggregateIdentifier;
import org.axonframework.spring.stereotype.Aggregate;

import java.util.UUID;

import static org.axonframework.modelling.command.AggregateLifecycle.apply;

@NoArgsConstructor
@Aggregate
@Slf4j
public class ProductAggregate {

    @AggregateIdentifier
    private String productId;

    private String productName;
    private String productDescription;

    @CommandHandler
    public ProductAggregate(ProductCreateCommand command){
        log.info("handling {}", command);
        apply(new ProductCreatedEvent(command.getProductId(),command.getProductName(),command.getProductDescription()));
    }

    @EventSourcingHandler
    public void onProductCreateEvent(ProductCreatedEvent event){
        log.info("applying {}", event);
        this.productId = event.getProductId();
        this.productName = event.getProductName();
        this.productDescription = event.getProductDescription();
    }
}

ProductCreateCommand

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.axonframework.modelling.command.TargetAggregateIdentifier;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductCreateCommand {

    @TargetAggregateIdentifier
    private String productId;
    private String productName;
    private String productDescription;

}

ProductCreatedEvent

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.axonframework.modelling.command.TargetAggregateIdentifier;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductCreatedEvent {

    @TargetAggregateIdentifier
    private String productId;
    private String productName;
    private String productDescription;

}

TestRunner

import lombok.extern.slf4j.Slf4j;

import org.axonframework.commandhandling.gateway.CommandGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
@Slf4j
public class TestRunner implements CommandLineRunner {

    private final CommandGateway commandGateway;

    @Autowired
    public TestRunner(CommandGateway commandGateway) {
        this.commandGateway = commandGateway;
    }

    @Override
    public void run(String... args) throws Exception {

        log.info("sending product create command");
        commandGateway.sendAndWait(new ProductCreateCommand(UUID.randomUUID().toString(), "Oreo", "biscuit"));
        log.info("sending product create command");
        commandGateway.sendAndWait(new ProductCreateCommand(UUID.randomUUID().toString(), "Oreo", "biscuit"));
    }
}

EDIT:

application.properties file

logging.level.root=info
server.port=8090
spring.datasource.url=jdbc:mysql://localhost:3306/producttest
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.use-new-id-generator-mappings= false

logs:

2021-01-06 21:44:51.229  INFO 21236 --- [           main] c.u.e.a.Client.TestRunner                : sending product create command
2021-01-06 21:44:51.257  INFO 21236 --- [           main] c.u.e.a.Aggregate.ProductAggregate       : handling ProductCreateCommand(productId=638643b7-1e4f-45b5-bfa9-1c2fd9360fa3, productName=Oreo, productDescription=biscuit)
2021-01-06 21:44:51.260  INFO 21236 --- [           main] c.u.e.a.Aggregate.ProductAggregate       : applying ProductCreatedEvent(productId=638643b7-1e4f-45b5-bfa9-1c2fd9360fa3, productName=Oreo, productDescription=biscuit)
2021-01-06 21:44:51.321  WARN 21236 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1146, SQLState: 42S02
2021-01-06 21:44:51.321 ERROR 21236 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Table 'producttest.domain_event_entry' doesn't exist
2021-01-06 21:44:51.333  INFO 21236 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-01-06 21:44:51.346 ERROR 21236 --- [           main] o.s.boot.SpringApplication               : Application run failed
1
I would be more interested in your application.properties (or yml). In short, you have to instruct JPA to create it for you or provide scripts (flyway, liquibase, etc) to do it for you. I would recommend the latter approach.Lucas Campos
Hi @LucasCampos I have added the application.properties file to the post. I think I will try to get this to work, and then as you said for when I try to actually implement this into my real application, I guess I can look into what flyway/liquibase are.amasuKAKAROT
seems like I was missing spring.jpa.hibernate.ddl-auto=create , I should go read up more on JPA :). Thanks for the hint though, appreciate it.amasuKAKAROT
Glad to help! I've added it as an answer than you can accept and everyone is aware of it.Lucas Campos

1 Answers

1
votes

In this case, you should instruct your application how to create tables.

You have 2 options:

  1. Tell JPA to do that, adding spring.jpa.hibernate.ddl-auto=create or spring.jpa.hibernate.ddl-auto=update
  2. Use a more robust tool like flyway, liquibase, etc

All the other configs you showed looks fine.