You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2022/05/13 08:19:19 UTC
[camel-spring-boot-examples] 01/02: Add Narayana example
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot-examples.git
commit 3aa966e26653c947712fdb90e9f3f622fb5523ab
Author: Federico Valeri <fe...@gmail.com>
AuthorDate: Mon May 9 10:53:20 2022 +0200
Add Narayana example
Signed-off-by: Federico Valeri <fe...@gmail.com>
---
README.adoc | 4 +-
pom.xml | 2 +
spring-boot-jta-jpa/pom.xml | 145 +++++++++++++++++++++
spring-boot-jta-jpa/readme.adoc | 82 ++++++++++++
.../src/main/java/sample/camel/Application.java | 50 +++++++
.../src/main/java/sample/camel/AuditLog.java | 54 ++++++++
.../src/main/java/sample/camel/CamelRoutes.java | 66 ++++++++++
.../src/main/java/sample/camel/RMFactory.java | 27 ++++
.../src/main/resources/application.properties | 27 ++++
.../src/main/resources/jbossts-properties.xml | 45 +++++++
spring-boot-jta-jpa/src/main/resources/logback.xml | 35 +++++
.../src/main/resources/spring-camel.xml | 113 ++++++++++++++++
12 files changed, 649 insertions(+), 1 deletion(-)
diff --git a/README.adoc b/README.adoc
index 975403b..58da1c5 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@ readme's instructions.
=== Examples
// examples: START
-Number of Examples: 55 (0 deprecated)
+Number of Examples: 56 (0 deprecated)
[width="100%",cols="4,2,4",options="header"]
|===
@@ -35,6 +35,8 @@ Number of Examples: 55 (0 deprecated)
| link:health-checks/readme.adoc[Health Checks] (health-checks) | |
+| link:spring-boot-jta-jpa/readme.adoc[Spring Boot Jta Jpa] (spring-boot-jta-jpa) | | An example showing JTA with Spring Boot
+
| link:undertow-spring-security/readme.adoc[Undertow Spring Security] (undertow-spring-security) | Advanced | Example on how to use the Camel Undertow component with spring security and Keycloak
| link:webhook/readme.adoc[Webhook] (webhook) | Advanced | Example on how to use the Camel Webhook component
diff --git a/pom.xml b/pom.xml
index c52d5ad..8e6d9b7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
<modules>
<module>spring-boot</module>
+ <module>spring-boot-jta-jpa</module>
<module>activemq</module>
<module>actuator-http-metrics</module>
<module>amqp</module>
@@ -101,6 +102,7 @@
<reactor-version>3.2.16.RELEASE</reactor-version>
<testcontainers-version>1.16.3</testcontainers-version>
<hapi-structures-v24-version>2.3</hapi-structures-v24-version>
+ <narayana-spring-boot-version>2.6.3</narayana-spring-boot-version>
</properties>
<repositories>
diff --git a/spring-boot-jta-jpa/pom.xml b/spring-boot-jta-jpa/pom.xml
new file mode 100644
index 0000000..768bf33
--- /dev/null
+++ b/spring-boot-jta-jpa/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel.springboot.example</groupId>
+ <artifactId>examples</artifactId>
+ <version>3.17.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>spring-boot-jta-jpa</artifactId>
+ <name>Camel SB Examples :: JTA</name>
+ <description>An example showing JTA with Spring Boot</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <node.identifier>${project.artifactId}-0</node.identifier>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-bom</artifactId>
+ <version>${camel-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-undertow</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>me.snowdrop</groupId>
+ <artifactId>narayana-spring-boot-starter</artifactId>
+ <version>${narayana-spring-boot-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>me.snowdrop</groupId>
+ <artifactId>narayana-spring-boot-recovery-controller</artifactId>
+ <version>${narayana-spring-boot-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-servlet-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-jpa-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-jms-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.messaginghub</groupId>
+ <artifactId>pooled-jms</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>artemis-jms-client</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot-version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/spring-boot-jta-jpa/readme.adoc b/spring-boot-jta-jpa/readme.adoc
new file mode 100644
index 0000000..f9f8a9a
--- /dev/null
+++ b/spring-boot-jta-jpa/readme.adoc
@@ -0,0 +1,82 @@
+== Camel Example Spring Boot JTA
+
+This example demonstrates how to run a Camel Service on Spring Boot that supports JTA transactions on two external transactional resources: a database (MySQL) and a message broker (Artemis).
+
+We use Narayana as standalone JTA Transaction Manager implementation, and Hibernate as JPA Adapter.
+Most of the configuration is in `src/main/resources/spring-camel.xml` with no auto-configuration magic, in order to show all components needed to support distributed transactions without a full blown application server.
+
+=== External systems
+
+Start MySQL:
+
+----
+WORK_DIR="$HOME/.local/mysql"
+docker run --name db-mysql \
+ -e MYSQL_ROOT_PASSWORD=root \
+ -v $WORK_DIR:/var/lib/mysql \
+ -d -p 3306:3306 mysql
+docker exec -it db-mysql mysql -uroot -proot -e \
+ "CREATE DATABASE testdb CHARACTER SET utf8mb4;
+ CREATE USER 'admin'@'%' IDENTIFIED WITH mysql_native_password BY 'admin';
+ GRANT CREATE,SELECT,INSERT,UPDATE,DELETE ON testdb.* TO 'admin'@'%';
+ GRANT XA_RECOVER_ADMIN on *.* to 'admin'@'%';
+ FLUSH PRIVILEGES;"
+docker exec -it db-mysql mysql testdb -uadmin -padmin -e \
+ "CREATE TABLE IF NOT EXISTS audit_log (
+ id SERIAL PRIMARY KEY,
+ message VARCHAR(255) NOT NULL
+ );"
+----
+
+Start Artemis:
+
+----
+ARTEMIS_URL="https://archive.apache.org/dist/activemq/activemq-artemis/2.22.0/apache-artemis-2.22.0-bin.tar.gz"
+ARTEMIS_HOME="/tmp/artemis" && mkdir -p $ARTEMIS_HOME $ARTEMIS_HOME/servers/server0
+curl -sL $ARTEMIS_URL | tar xz -C $ARTEMIS_HOME --strip-components 1
+export PATH="$ARTEMIS_HOME/bin:$ARTEMIS_HOME/servers/server0/bin:$PATH"
+artemis create $ARTEMIS_HOME/servers/server0 --name server0 --user admin --password admin --require-login
+artemis-service start
+----
+
+=== How to run
+
+You can run this example using (every instance must have a unique identifier):
+
+----
+mvn spring-boot:run -Dnode.identifier="server0"
+----
+
+Test the service endpoint from another terminal:
+
+----
+ADDRESS="http://localhost:8080"
+curl -X POST $ADDRESS/api/message/hello
+curl $ADDRESS/api/messages
+----
+
+Test rollback by calling the service with "fail" content:
+
+----
+curl -X POST $ADDRESS/api/message/fail
+----
+
+You should not find any trace of the message in the `audit_log` table.
+
+=== To get health check
+
+To show a summary of spring boot health check:
+
+----
+curl http://localhost:8080/actuator/health
+----
+
+See the `application.properties` to control what information to present in actuator.
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
diff --git a/spring-boot-jta-jpa/src/main/java/sample/camel/Application.java b/spring-boot-jta-jpa/src/main/java/sample/camel/Application.java
new file mode 100644
index 0000000..cde4ccf
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/java/sample/camel/Application.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import me.snowdrop.boot.narayana.autoconfigure.NarayanaConfiguration;
+import org.apache.camel.component.jms.springboot.JmsComponentAutoConfiguration;
+import org.apache.camel.component.jpa.springboot.JpaComponentAutoConfiguration;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
+import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ImportResource;
+
+@SpringBootConfiguration
+@ComponentScan
+@EnableAutoConfiguration(exclude = {
+ NarayanaConfiguration.class,
+ JtaAutoConfiguration.class,
+ DataSourceAutoConfiguration.class,
+ DataSourceTransactionManagerAutoConfiguration.class,
+ HibernateJpaAutoConfiguration.class,
+ JpaComponentAutoConfiguration.class,
+ ArtemisAutoConfiguration.class,
+ JmsComponentAutoConfiguration.class
+})
+@ImportResource("classpath:spring-camel.xml")
+public class Application {
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/spring-boot-jta-jpa/src/main/java/sample/camel/AuditLog.java b/spring-boot-jta-jpa/src/main/java/sample/camel/AuditLog.java
new file mode 100644
index 0000000..a3ebe24
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/java/sample/camel/AuditLog.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "audit_log")
+@NamedQueries({
+ @NamedQuery(name = "getAuditLog", query = "select al from AuditLog al")
+})
+public class AuditLog {
+ @Id
+ @GeneratedValue (strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ private String id;
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public AuditLog createAuditLog(String message) {
+ AuditLog auditLog = new AuditLog();
+ auditLog.message = message;
+ return auditLog;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{message=%s}", message);
+ }
+}
diff --git a/spring-boot-jta-jpa/src/main/java/sample/camel/CamelRoutes.java b/spring-boot-jta-jpa/src/main/java/sample/camel/CamelRoutes.java
new file mode 100644
index 0000000..302eb99
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/java/sample/camel/CamelRoutes.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.rest.RestParamType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CamelRoutes extends RouteBuilder {
+ @Value("${camel.servlet.mapping.context-path}")
+ public String contextPath;
+
+ @Override
+ public void configure() {
+ restConfiguration()
+ .contextPath(contextPath.substring(0, contextPath.length() - 2));
+
+ rest("/messages")
+ .produces("text/plain")
+ .get()
+ .to("direct:messages")
+ .post("/{message}")
+ .param().name("message").type(RestParamType.path).dataType("string").endParam()
+ .to("direct:trans");
+
+ from("direct:messages")
+ .to("jpa:it.fvaleri.integ.AuditLog?namedQuery=getAuditLog")
+ .convertBodyTo(String.class);
+
+ from("direct:trans")
+ .transacted()
+ .setBody(simple("${headers.message}"))
+ .to("bean:auditLog?method=createAuditLog(${body})")
+ .to("jpa:it.fvaleri.integ.AuditLog")
+ .setBody(simple("${headers.message}"))
+ .to("jms:outbound?disableReplyTo=true")
+ .choice()
+ .when(body().startsWith("fail"))
+ .log("Forced exception")
+ .process(x -> {throw new RuntimeException("fail");})
+ .otherwise()
+ .log("Message added: ${body}")
+ .endChoice();
+
+ from("jms:outbound")
+ .log("Message out: ${body}")
+ .to("bean:auditLog?method=createAuditLog(${body}-ok)")
+ .to("jpa:it.fvaleri.integ.AuditLog");
+ }
+}
diff --git a/spring-boot-jta-jpa/src/main/java/sample/camel/RMFactory.java b/spring-boot-jta-jpa/src/main/java/sample/camel/RMFactory.java
new file mode 100644
index 0000000..0b8b5eb
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/java/sample/camel/RMFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import com.arjuna.ats.arjuna.recovery.RecoveryManager;
+
+public class RMFactory {
+ public RecoveryManager createInstance() {
+ RecoveryManager recoveryManager = RecoveryManager.manager(RecoveryManager.INDIRECT_MANAGEMENT);
+ recoveryManager.startRecoveryManagerThread();
+ return recoveryManager;
+ }
+}
diff --git a/spring-boot-jta-jpa/src/main/resources/application.properties b/spring-boot-jta-jpa/src/main/resources/application.properties
new file mode 100644
index 0000000..6ade52a
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/resources/application.properties
@@ -0,0 +1,27 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+server.port = 8080
+server.address = 0.0.0.0
+logging.config = classpath:logback.xml
+spring.main.banner-mode = off
+spring.jmx.enabled = false
+# http://localhost:8080/actuator/health
+management.endpoints.web.exposure.include = health,beans,loggers
+spring.main.allow-bean-definition-overriding = true
+camel.springboot.jmxEnabled = false
+camel.servlet.mapping.context-path = /api/*
diff --git a/spring-boot-jta-jpa/src/main/resources/jbossts-properties.xml b/spring-boot-jta-jpa/src/main/resources/jbossts-properties.xml
new file mode 100644
index 0000000..8fc515f
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/resources/jbossts-properties.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<properties>
+ <!-- must be unique across all instances to ensure TMs can coordinate the same RMs -->
+ <entry key="CoreEnvironmentBean.nodeIdentifier">${node.identifier}</entry>
+
+ <!-- by default the ObjectStore is crated under user.home -->
+ <entry key="ObjectStoreEnvironmentBean.objectStoreDir">target/store/${node.identifier}</entry>
+
+ <!-- transaction timeout in seconds after which it is automatically rolled back -->
+ <entry key="CoordinatorEnvironmentBean.defaultTimeout">120</entry>
+ <entry key="CoordinatorEnvironmentBean.asyncCommit">NO</entry>
+ <entry key="CoordinatorEnvironmentBean.transactionStatusManagerEnable">NO</entry>
+
+ <!-- transaction recovery periods in seconds (modules executed sequentially) -->
+ <entry key="RecoveryEnvironmentBean.periodicRecoveryPeriod">120</entry>
+ <entry key="RecoveryEnvironmentBean.recoveryBackoffPeriod">10</entry>
+ <entry key="RecoveryEnvironmentBean.recoveryListener">NO</entry>
+ <entry key="RecoveryEnvironmentBean.recoveryModuleClassNames">
+ com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule
+ </entry>
+
+ <!-- expiry period in hours for recovery ObjectStore entries (modules executed randomly) -->
+ <entry key="RecoveryEnvironmentBean.expiryScanInterval">12</entry>
+ <entry key="RecoveryEnvironmentBean.expiryScannerClassNames">
+ com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner
+ </entry>
+</properties>
diff --git a/spring-boot-jta-jpa/src/main/resources/logback.xml b/spring-boot-jta-jpa/src/main/resources/logback.xml
new file mode 100644
index 0000000..528b952
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d %highlight(%p) [%t] %c %m%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="INFO">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+ <logger name="sample.camel" level="INFO"/>
+ <logger name="com.arjuna" level="INFO"/>
+ <logger name="org.apache.camel" level="INFO"/>
+ <logger name="org.hibernate" level="INFO"/>
+</configuration>
diff --git a/spring-boot-jta-jpa/src/main/resources/spring-camel.xml b/spring-boot-jta-jpa/src/main/resources/spring-camel.xml
new file mode 100644
index 0000000..8424b3a
--- /dev/null
+++ b/spring-boot-jta-jpa/src/main/resources/spring-camel.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
+ <bean id="auditLog" class="sample.camel.AuditLog"/>
+ <bean id="transactionManagerImple"
+ class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/>
+ <bean id="userTransactionImple" class="com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple"/>
+ <bean id="recoveryManagerFactory" class="sample.camel.RMFactory"/>
+ <bean id="recoveryManager" factory-bean="recoveryManagerFactory" factory-method="createInstance"/>
+ <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
+ <property name="transactionManager" ref="transactionManagerImple"/>
+ <property name="userTransaction" ref="userTransactionImple"/>
+ </bean>
+ <bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
+ <property name="transactionManager" ref="jtaTransactionManager"/>
+ <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
+ </bean>
+
+ <bean id="jtaDataSource" class="com.mysql.cj.jdbc.MysqlXADataSource">
+ <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
+ <property name="user" value="admin"/>
+ <property name="password" value="admin"/>
+ </bean>
+
+ <!-- Pooled JTA aware data source -->
+ <bean id="pooledJtaDataSource" class="org.apache.commons.dbcp2.managed.BasicManagedDataSource">
+ <property name="transactionManager" ref="transactionManagerImple"/>
+ <property name="xaDataSourceInstance" ref="jtaDataSource"/>
+ <property name="initialSize" value="5"/>
+ <property name="maxIdle" value="5"/>
+ </bean>
+
+ <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+ <property name="packagesToScan" value="sample.camel"/>
+ <property name="jtaDataSource" ref="pooledJtaDataSource"/>
+ <property name="persistenceUnitName" value="camel"/>
+ <property name="jpaDialect">
+ <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
+ </property>
+ <property name="jpaVendorAdapter">
+ <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
+ <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
+ </bean>
+ </property>
+ <property name="jpaProperties">
+ <props>
+ <prop key="hibernate.hbm2ddl.auto">none</prop>
+ <prop key="hibernate.id.new_generator_mappings">false</prop>
+ <prop key="hibernate.transaction.coordinator_class">jta</prop>
+ <prop key="hibernate.transaction.jta.platform">
+ org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform
+ </prop>
+ <prop key="hibernate.show_sql">false</prop>
+ <prop key="hibernate.format_sql">true"</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
+ <property name="transactionManager" ref="jtaTransactionManager"/>
+ <property name="entityManagerFactory" ref="entityManagerFactory"/>
+ <property name="joinTransaction" value="true"/>
+ <property name="sharedEntityManager" value="false"/>
+ </bean>
+
+ <bean id="jtaConnectionFactory" class="org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory">
+ <constructor-arg value="tcp://localhost:61616"/>
+ <constructor-arg value="admin"/>
+ <constructor-arg value="admin"/>
+ </bean>
+
+ <!-- Pooled JTA aware connection factory -->
+ <bean id="pooledJtaConnectionFactory" class="org.messaginghub.pooled.jms.JmsPoolXAConnectionFactory">
+ <property name="transactionManager" ref="transactionManagerImple"/>
+ <property name="connectionFactory" ref="jtaConnectionFactory"/>
+ <property name="maxConnections" value="1"/>
+ <property name="maxSessionsPerConnection" value="100"/>
+ <property name="useAnonymousProducers" value="false"/>
+ </bean>
+
+ <bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
+ <property name="configuration">
+ <bean class="org.apache.camel.component.jms.JmsConfiguration">
+ <property name="transactionManager" ref="jtaTransactionManager"/>
+ <property name="connectionFactory" ref="pooledJtaConnectionFactory"/>
+ <!-- disable local transactions as JTA TM will take care of enrolling -->
+ <property name="transacted" value="false"/>
+ <!-- caching does not work with distributed transactions -->
+ <property name="cacheLevelName" value="CACHE_NONE"/>
+ <property name="maxConcurrentConsumers" value="1"/>
+ <property name="testConnectionOnStartup" value="true"/>
+ </bean>
+ </property>
+ </bean>
+</beans>