Good morning, I have been trying to implement XA transactions for one of my rest endpoints (persist to db and send JMS message). As I can see from the logs while debugging db (Postgresql) is using arjuna as it is supposed to, but when it comes to publishing message to activeMQ by using camel I am getting exception:
javax.jms.JMSException: Session's XAResource has not been enlisted in a distributed transaction.
at org.apache.activemq.ActiveMQXASession.doStartTransaction(ActiveMQXASession.java:101)
at org.apache.activemq.ActiveMQSession.send(ActiveMQSession.java:1916)
at org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:288)
at org.apache.activemq.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:223)
at org.apache.activemq.ActiveMQMessageProducerSupport.send(ActiveMQMessageProducerSupport.java:241)
Is Narayana compatible with spring boot 2.4.5 at all? If so what could be the problem behind this exception?
Here is my controller code
@ResponseBody
@Transactional
public ResponseEntity<ReceiptDetailResource> createReceiptDetail(
@RequestHeader("X-TenantId") String tenantId,
@RequestHeader("X-CompanyId") Long companyId,
@RequestHeader("X-CashMachineId") Long cashMachineId,
@Valid @RequestBody ReceiptDetailResource receiptDetailDto) throws SystemException, NotSupportedException, HeuristicRollbackException, HeuristicMixedException, RollbackException {
log.info("Creating Receipt Detail");
ReceiptDetailResource receiptDetailResource = new ReceiptDetailResource();
try {
ReceiptDetail receiptDetail = EnrichReceiptDetail(receiptDetailResourceTransformService.fromDto(receiptDetailDto), cashMachineId);
if (tenantId == null || companyId == null || cashMachineId == null) {
log.error("Headers are not set !!!");
throw new IllegalArgumentException();
}
Optional<ReceiptHeader> receiptHeaderOptional = receiptHeaderQueryService.getRepository().findById(receiptDetailDto.getReceiptHeaderId());
if (receiptHeaderOptional.isPresent()) {
receiptDetail.setReceiptHeader(receiptHeaderOptional.get());
} else {
// If ReceiptHeader is null - create new ReceiptHeader using context.
RequestContext.getRequestContext("x-organizationid");
RequestContext.getRequestContext("x-companyid");
RequestContext.getRequestContext("x-cashmachineid");
Optional<CashRegister> cashRegister = cashRegisterQueryService.findById(Long.parseLong((String) RequestContext.getRequestContext("x-cashmachineid")));
// TODO Get client:
ReceiptHeader receiptHeader = new ReceiptHeader();
receiptHeader.setReceiptDate(ZonedDateTime.now());
receiptHeader.setCashRegister(cashRegister.get());
receiptHeader = receiptHeaderQueryService.getRepository().save(receiptHeader);
receiptDetail.setReceiptHeader(receiptHeader);
}
receiptDetail = receiptDetailQueryService.getRepository().save(receiptDetail);
ReceiptDetailDiscount receiptDetailDiscount = new ReceiptDetailDiscount();
receiptDetailResource = new ReceiptDetailResource(receiptDetail);
priceBean.applyDiscountForReceiptDetail(receiptDetailResource, receiptDetailDiscount);
receiptDetailResource.setId(receiptDetail.getId());
if(receiptDetail.getDiscountPrice() != null || receiptDetail.getDiscountPercentage() != null) {
priceBean.updateReceiptDetailDiscount(receiptDetailDiscount, receiptDetail.getId());
}
// TODO Send event:
String updatedBy = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
updatedBy = ((UserDetails) authentication.getPrincipal()).getUsername();
}
BasePosEvent receiptDetailCreatedEvent = new BasePosEvent(updatedBy, tenantId, companyId, null, cashMachineId,
PosSalesEventTypes.receiptDetailCreatedEvent, receiptDetailResource);
camelPublisher.publish(receiptQueue, receiptDetailCreatedEvent, PosSalesEventTypes.receiptDetailCreatedEvent.name());
log.info("Receipt Detail created: " + receiptDetailResource.getId());
return ResponseEntity.ok(receiptDetailResource);
} catch (EntityNotFoundException e) {
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, e.getLocalizedMessage()
);
} catch (IllegalArgumentException e) {
log.warn("Bad Receipt Detail or context.", e);
throw new ResponseStatusException(
HttpStatus.BAD_REQUEST, "Bad Receipt Detail or context."
);
}
}
exception is thrown at this line:
camelPublisher.publish(receiptQueue, receiptDetailCreatedEvent, PosSalesEventTypes.receiptDetailCreatedEvent.name());
Thank you for your answer