Spring Boot Camel JPA No local transaction to join

1.3k views Asked by At

I am using

Spring Boot 1.5.10.RELEASE
Camel 2.21.1
Java 1.8

My application

@SpringBootApplication
@ImportResource({"classpath:my-webservice.xml", "classpath:my-camel.xml"})
public class CamelCXFApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(CamelCXFApplication.class, args);
    }

    @Bean
    ServletRegistrationBean servletRegistrationBean() {
        ServletRegistrationBean servlet = new ServletRegistrationBean(new CamelHttpTransportServlet(), "/camel-rest-jpa/*");
        servlet.setName("CamelServlet");
        return servlet;
    }
}

My route

@Component
public class RestAPI extends RouteBuilder {

    @Override
    public void configure() {
        restConfiguration().contextPath("/camel-rest-jpa").apiContextPath("/api-doc")
                .apiProperty("api.title", "Camel REST API")
                .apiProperty("api.version", "1.0")
                .apiProperty("cors", "true")
                .apiContextRouteId("doc-api")
                .bindingMode(RestBindingMode.json);


        rest("/books").description("Books REST service")
                .get("/").description("The list of all the books")
                .route().routeId("books-api")
                .bean(Database.class, "findBooks")
                .endRest()
                .get("order/{id}").description("Details of an order by id")
                .route().routeId("order-api")
                .bean(Database.class, "findOrder(${header.id})");


    }
}

My BackendRoute

@Component
public class Backend extends RouteBuilder {

    @Override
    public void configure() {


        // A first route generates some orders and queue them in DB
        from("timer:new-order?delay=1s&period={{example.generateOrderPeriod:2s}}")
                .routeId("generate-order")
                .bean("orderService", "generateOrder")
                .to("jpa:org.apache.jms.example.spring.boot.rest.jpa.Order")
                .log("Inserted new order ${body.id}");

        // A second route polls the DB for new orders and processes them
        from("jpa:org.apache.jms.example.spring.boot.rest.jpa.Order"
                + "?consumer.namedQuery=new-orders"
                + "&consumer.delay={{example.processOrderPeriod:5s}}"
                + "&consumeDelete=false")
                .routeId("process-order")
                .log("Processed order #id ${body.id} with ${body.amount} copies of the «${body.book.description}» book");

    }
}

Maven

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jms-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jms</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-servlet-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.1.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-features-logging</artifactId>
            <version>3.1.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-test-spring</artifactId>
            <version>${camel.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jackson-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jpa-starter</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-csv</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>${camel.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-swagger-java-starter</artifactId>
            <version>${camel.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.hibernate</groupId>
                    <artifactId>hibernate-validator</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-servlet</artifactId>
            <version>${camel.version}</version>
        </dependency>
    </dependencies>

I am getting error

2018-06-25 14:44:47.460  WARN 13696 --- [mer://new-order] o.a.camel.component.timer.TimerConsumer  : Error processing exchange. Exchange[ID-IZeno-NB1048-1529912673553-0-5]. Caused by: [javax.persistence.TransactionRequiredException - No local transaction to join]

javax.persistence.TransactionRequiredException: No local transaction to join
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.doJoinTransaction(ExtendedEntityManagerCreator.java:388) ~[spring-orm-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:330) ~[spring-orm-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at com.sun.proxy.$Proxy121.joinTransaction(Unknown Source) ~[na:na]
    at org.apache.camel.component.jpa.JpaProducer$2.doInTransaction(JpaProducer.java:213) ~[camel-jpa-2.21.1.jar:2.21.1]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.apache.camel.component.jpa.JpaProducer.processEntity(JpaProducer.java:210) ~[camel-jpa-2.21.1.jar:2.21.1]
    at org.apache.camel.component.jpa.JpaProducer.process(JpaProducer.java:162) ~[camel-jpa-2.21.1.jar:2.21.1]
    at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61) ~[camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:148) ~[camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:548) ~[camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:138) ~[camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:101) ~[camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:201) [camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.component.timer.TimerConsumer.sendTimerExchange(TimerConsumer.java:197) [camel-core-2.21.1.jar:2.21.1]
    at org.apache.camel.component.timer.TimerConsumer$1.run(TimerConsumer.java:79) [camel-core-2.21.1.jar:2.21.1]
    at java.util.TimerThread.mainLoop(Timer.java:555) [na:1.8.0_161]
    at java.util.TimerThread.run(Timer.java:505) [na:1.8.0_161]

I am following the sample from https://github.com/apache/camel/tree/master/examples/camel-example-spring-boot-rest-jpa however I am not using Spring Boot 2.0.3, I am using 1.5.10.

UPDATE

I realized I have one JmsTransactionManager

@Bean
    public JmsTransactionManager jmsTransactionManager(final ConnectionFactory connectionFactory) {
        JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
        jmsTransactionManager.setConnectionFactory(connectionFactory);
        return jmsTransactionManager;
    }

Do I need to define additional transactionManager for Jpa ? What else is required ?

1

There are 1 answers

0
burki On BEST ANSWER

To integrate a database and use it transactional, your JmsTransactionManager is not suitable. You would need a DataSourceTransactionManager instead.

I don't see any routes that send or consume to/from JMS. If you don't use JMS at all, you don't need the JmsTransactionManager.