0

I have a question, I have to use Atomikos with Axon framework, in Spring-Boot (without Axon Server). I am using Oracle DB, and I am using multiple threads (10) to send a lot of commands, and before that I am configuring an JtaTransactionManager for myself, but in some threads I get this kind of exception: javax.transaction.xa.XAException, raised -6 or -4 or -3 or ORA-02056: 2PC: k2lcom: bad two-phase command number rdonly from coord:. As I debugged I saw that the CommandGateWay is using JtaTransactionManager too. Is it right? When is this opening a transaction? Is that possible that my JtaTransactionManager and Axon's is in conflict? Did anybody had this kind of exceptions?

Sample code:

@Service
public class CreateEntitiesServiceImpl extends FutureCompleter implements CreateEntitiesService {

    private static Logger logger = LoggerHelper.getDeveloperLogger(CreateEntitiesServiceImpl.class);
    private final CommandGateway commandGateway;
    private final ExecutionUtil executionUtil;
    private final MyEntityRepository myEntityRepository;

    public CreateEntitiesServiceImpl(CommandGateway commandGateway, ExecutionUtil executionUtil, MyEntityRepository myEntityRepository) {
        this.commandGateway = commandGateway;
        this.executionUtil = executionUtil;
        this.myEntityRepository = myEntityRepository;
    }

    @Override
    public void process(Message message) {
        logger.info("Entity addition started!");
        generateEntities();
        logger.info("Entity addition finished!");
    }

    private void generateEntities() {
        ExecutorService executorService = executionUtil.createExecutor(10, "createEntities");

        List<Integer> list = IntStream.rangeClosed(1, 1000).boxed().collect(Collectors.toList());

        CreateEntitiesService proxy = applicationContext.getBean(CreateEntitiesServiceImpl.class);

        List<CompletableFuture<Void>> processingFutures = list.stream().map(
                e -> CompletableFuture.runAsync(proxy::createEntity, executorService).whenComplete((x, y) -> executorService.shutdown()))
                .collect(Collectors.toList());

        processingFutures.stream().map(this::getVoidFuture).collect(Collectors.toList());
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createEntity() {
        try {
            MyEntity myEntity = new MyEntity();
            myEntity.setEntityStringProperty("string");
            myEntity.setEntityTimestampProperty(LocalDateTime.now());

            MyEntity savedEntity = myEntityRepository.save(myEntity);
            CreateAggregateCommand command = new CreateAggregateCommand(savedEntity.getEntityId(), savedEntity.getEntityStringProperty(),
                    savedEntity.getEntityTimestampProperty());
            commandGateway.send(command);
        } catch (Exception e) {
            throw new CreateEntitiesException(e.getMessage(), e);
        }
    }
}

Thanks

polosoft
  • 200
  • 1
  • 14

1 Answers1

0

I do not fully comprehend what you're asking to be honest.

The title states Axon with Atomikos, whilst I don't feel this point ever comes back in the description.

What you are asking in the question description is whether it's correct that the CommandGateway uses a transaction manager.

On that matter I can be clear though: yes it does. Sending a command will very likely end you up within an aggregate instance. As you'd want to guard the consistency boundary within this instance and ensure the events which are published get stored, it's sensible to start the transaction as soon as the command is being handled.

By the way, small note: it's the CommandBus which uses the TransactionManager. Conceptually that doesn't change my description thus far though.

Concluding, I am not entirely sure whether this will help you out, as your question is not completely clear to me. I hope a rewrite of your post will clarify more of what you are actually after.

Steven
  • 6,936
  • 1
  • 16
  • 31