├── .gitignore ├── README.md ├── database ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── jboss │ │ └── fuse │ │ └── examples │ │ └── transactions │ │ └── model │ │ └── Flight.java │ └── resources-filtered │ └── postgresql │ └── META-INF │ └── persistence.xml ├── datasource ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── jboss │ │ └── fuse │ │ └── examples │ │ └── transactions │ │ └── tools │ │ ├── DataSources.java │ │ └── DbInsert.java │ ├── resources-filtered │ └── postgresql │ │ └── datasource.xml │ ├── resources │ ├── jdbc.properties │ └── logback.xml │ └── sql │ └── postgresql │ └── initdb.sql ├── features ├── README.md ├── pom.xml └── src │ └── main │ └── resources │ └── features.xml ├── fuse-license-header.txt ├── pom.xml └── routing ├── README.md ├── pom.xml └── src └── main ├── java └── org │ └── jboss │ └── fuse │ └── examples │ └── transactions │ └── routes │ ├── Airports.java │ └── TransactionalRouteBuilder.java └── resources └── OSGI-INF └── blueprint └── routing.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | 3 | *.i?? 4 | .idea 5 | 6 | .project 7 | .settings 8 | .classpath -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 18 | # ESB Transactions 19 | 20 | ## Overview 21 | This example will show you how to leverage the JTA transaction manager provided by Fuse ESB when working with JMS 22 | or JTA Camel endpoints. We will setup a route that reads messages from a queue and inserts information into a database 23 | using JTA and XA transactions and deploy that onto JBoss Fuse 6.3.0. 24 | 25 | ## What You Will Learn 26 | In studying this example you will learn: 27 | * how to set up an XA-aware DataSource 28 | * how to configure a JPA persistence unit 29 | * how to leverage Fuse ESB's JTA and JPA support in your routes 30 | * how to configure a JMS component to support XA 31 | * how to define a transactional route 32 | * how to configure a ResourceManager that can recover XA transactions after a crash 33 | 34 | # Initial setup 35 | 36 | We will refer to the root directory of `esb-transactions` project as `$PROJECT_HOME`. 37 | 38 | ## Prerequisites 39 | Before building and running this example you need: 40 | 41 | * Maven 3.2.3 or higher 42 | * JDK 1.7 or JDK 1.8 43 | * JBoss Fuse 6.3.0 44 | * Docker-enabled operating system 45 | 46 | ## Files in the Example 47 | * `pom.xml` - the Maven POM file for building the example 48 | * `datasource` - contains the JDBC data source definition 49 | * `database` - contains the persistence unit definition and the JPA entity beans 50 | * `routing` - contains the transactional Camel routes 51 | * `features` - contains the Apache Karaf features definition that allows for easy installation of this example 52 | 53 | For more information about these Maven modules, have a look at the README.md file in every module directory. 54 | 55 | # Setting up docker-based databases 56 | 57 | To perform tests in more realistic environments, we can leverage the power of Docker to run more advanced database servers. 58 | Of course you can use existing database instances. The below examples are just here for completeness. 59 | 60 | ## PostgreSQL database 61 | 62 | We will use the *official* PostgreSQL docker image available at [docker hub](https://registry.hub.docker.com/_/postgres/). 63 | You can use any of the available methods to access PostgreSQL server (e.g., by mapping ports or connecting to containers IP address directly) if you'd prefer. 64 | 65 | 1. Start the PostgreSQL server docker container: 66 | 67 | $ docker run -d --name fuse-postgresql-server -e POSTGRES_USER=fuse -e POSTGRES_PASSWORD=fuse -p 5432:5432 postgres:9.4 68 | 69 | 2. Connect to the docker container and run the psql client to create the `transactions` database from the `fuse-postgresql-server` container: 70 | 71 | $ docker exec -ti fuse-postgresql-server /bin/bash 72 | root@b052efff5a53:/# psql -U fuse -d fuse 73 | psql (9.4.0) 74 | Type "help" for help. 75 | fuse=# create database transactions owner fuse encoding 'utf8'; 76 | CREATE DATABASE 77 | fuse=# \q 78 | 79 | Enter control-D to exit psql and control-D again to disconnect from docker. 80 | 81 | 3. Initialize the `transactions` database by creating the 'transactions' schema and 'flights' table. 82 | 83 | Simply run: 84 | 85 | $ cd $PROJECT_HOME/datasource 86 | $ mvn -Ppostgresql 87 | 88 | This will produce standard Maven output with single information: 89 | 90 | [INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ datasource --- 91 | 10:39:54.826 INFO [o.j.f.e.t.t.DbInsert] : Database postgresql initialized successfully 92 | 93 | 4. Configure PostgreSQL database to allow XA transactions by setting `max_prepared_transactions` to the value equal or greater 94 | than `max_connections` setting (`100` in the case of `postgres:9.4` image). 95 | 96 | root@b052efff5a53:/# sed -i 's/^#max_prepared_transactions = 0/max_prepared_transactions = 200/' /var/lib/postgresql/data/postgresql.conf 97 | 98 | 5. Restart `fuse-postgresql-server` container. Your PostgreSQL database is ready to use. 99 | 100 | docker restart fuse-postgresql-server 101 | 102 | 103 | ## Building the Example 104 | In the $PROJECT_HOME directory, run `mvn clean install` to build the example. 105 | 106 | ## Running the Example 107 | We will refer to the directory that contains your Fuse ESB installation as `$FUSE_HOME`. 108 | 109 | ### Configuring additional users 110 | Before we can start Fuse ESB, we have to make sure we configure a user we can use later on to connect to the embedded 111 | message broker and send messages to a queue. Edit the '$ESB_HOME/etc/users.properties file and add a line that says: 112 | 113 | admin=admin,Administrator 114 | 115 | The syntax for this line is <userid>=<password>,<role>, so we're creating a user called `admin` with a password `admin` 116 | who has the `Administrator` role. 117 | 118 | ### Start JBoss Fuse 119 | Start JBoss Fuse with these commands 120 | 121 | * on Linux/Unix/MacOS: `bin/fuse` 122 | * on Windows: `bin\fuse.bat` 123 | 124 | ### Adding the features repository 125 | To allow for easy installation of the example, we created a features descriptor. On Fuse ESB's console, add the 126 | extra features repository with this command: 127 | 128 | JBossFuse:karaf@root> features:addurl mvn:org.jboss.fuse.examples.transactions/features/6.3.0/xml/features 129 | 130 | ### Install the example using the feature 131 | First, install the feature itself using this command: 132 | 133 | JBossFuse:karaf@root> features:install transactions-demo 134 | 135 | Using `osgi:list` in the console, you should now see this demo's bundles at the bottom of the list. 136 | 137 | ### Use hawtio to send JMS messages 138 | Open the JBoss Fuse Management Console by going to http://localhost:8181/hawtio and login using the username and password you specified in $FUSE_HOME/etc/users.properties 139 | 140 | Click on ActiveMQ at the top of the page 141 | In the left column expand 'Queue' and click on 'Input.flights' 142 | Click on 'Send' at the top of the page 143 | Set the 'Payload format' to 'Plain text' 144 | Send a few messages to the queue. The message content will become the flight ID in the database, so just use your imagination for that one ;) 145 | 146 | The ESB log file will contain logging output similar to : 147 | 2015-05-22 11:25:37,593 | INFO | r[Input.Flights] | route1 | ? ? | 198 - org.apache.camel.camel-core - 2.15.1.redhat-620118 | Received JMS message TXL-1000 148 | 2015-05-22 11:25:37,594 | INFO | r[Input.Flights] | route1 | ? ? | 198 - org.apache.camel.camel-core - 2.15.1.redhat-620118 | Storing [flight TXL-1000 from DEN to LAS] in the database 149 | 150 | ### Using jconsole to send JMS messages 151 | You can also demonstrate this example using jconsole. Open `jconsole` and connect to the running Fuse ESB Enterprise instance. If the instance is running locally, connect to 152 | the process called `org.apache.karaf.main.Main`. 153 | 154 | On the MBeans tab, navigate to `org.apache.activemq` → `Broker` → `amq` → `Queue` → `Input.Flights`. Send a few 155 | messages to the queue using the `sendTextMessage(String body, String user, String password)` operation. For the second 156 | and third parameter, use the username and password you configured earlier. The first parameter will become the flight ID 157 | in the database, so just use your imagination for that one ;) 158 | 159 | The ESB log file will contain logging output similar to : 160 | 2015-05-22 11:25:37,593 | INFO | r[Input.Flights] | route1 | ? ? | 198 - org.apache.camel.camel-core - 2.15.1.redhat-620118 | Received JMS message TXL-1000 161 | 2015-05-22 11:25:37,594 | INFO | r[Input.Flights] | route1 | ? ? | 198 - org.apache.camel.camel-core - 2.15.1.redhat-620118 | Storing [flight TXL-1000 from DEN to LAS] in the database 162 | 163 | 164 | ### Verifying the result 165 | To verify the result of sending message, reconnect to docker and run the 'psql' client 166 | 167 | $ docker exec -ti fuse-postgresql-server /bin/bash 168 | root@895273b0fb36:/# psql -U fuse -d transactions 169 | psql (9.4.1) 170 | Type "help" for help. 171 | 172 | transactions=# select * from transactions.flights; 173 | 174 | You will see new database rows for every message you sent, using the message body as the flight number. 175 | 176 | ## More information 177 | For more information see: 178 | 179 | * JBoss Fuse 6.3.0 - [Transaction Guide](https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Fuse/6.3/html/Transaction_Guide/index.html) 180 | 181 | ## NOTE: 182 | For more verbose logging about the use of XA transactions, this logging 183 | configuration can be applied on the Karaf shell: 184 | 185 | log:set DEBUG org.apache.activemq.transaction 186 | log:set DEBUG org.springframework.transaction 187 | 188 | emacs 189 | log:set DEBUG org.springframework.jms.connection.JmsTransactionManager 190 | log:set DEBUG org.springframework.orm.jpa.JpaTransactionManager 191 | log:set TRACE org.apache.geronimo.transaction.manager.WrapperNamedXAResource 192 | log:set DEBUG org.apache.geronimo.transaction.log 193 | log:set DEBUG org.jencks 194 | 195 | This will log every tx.begin, tx.prepare and tx.commit operation to data/log/fuse.log. 196 | 197 | ## Installation in Fabric mode: 198 | In Routing component(routing.xml) user might have to change activemq port if deployed in a different container than root. 199 | 200 | profile-create --parent feature-camel transactions-demo.profile 201 | profile-edit --repositories mvn:org.jboss.fuse.examples.transactions/features/6.3.0/xml/features transactions-demo.profile 202 | profile-edit --feature activemq-camel --feature jpa --feature transactions-demo transactions-demo.profile 203 | 204 | -------------------------------------------------------------------------------- /database/README.md: -------------------------------------------------------------------------------- 1 | # Database bundle 2 | This bundle defines the JPA entity classes as well as the JPA persistence unit. 3 | 4 | ## Persistence unit 5 | The persistence unit is defined in the `src/main/resources/META-INF/persistence.xml` file. Inside Fuse ESB Enterprise, 6 | Aries JPA is responsible for configuring and activating this persistence unit. In order for it to find out about the 7 | persistence unit, an extra MANIFEST.MF header called `Meta-Persistence` has to be added. 8 | 9 | ## Checking the OSGi Service Registry 10 | Once the persistence unit has been created, Aries JPA will also ensure that the corresponding `javax.persistence.EntityManagerFactory` 11 | is exported into the OSGi Service Registry. We can use the Fuse ESB Enterprise console to verify that this is actually the case. 12 | 13 | First, find the bundle id for the bundle called "Fuse By Example :: Transactions :: Database" by using the `osgi:list` command. 14 | You can use `grep` to filter the list of bundles and quickly find the right one. 15 | 16 | JBossFuse:karaf@root> osgi:list | grep -i transactions 17 | [ 295] [Active ] [Created ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Datasource (6.3.0) 18 | [ 296] [Active ] [ ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Database (6.3.0) 19 | [ 297] [Active ] [Created ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Routing (6.3.0) 20 | 21 | In this example, the bundle id is 296. Using the `osgi:ls` command, you can see the `javax.persistence.EntityManagerFactory` listed as 22 | a service. 23 | 24 | JBossFuse:karaf@root> osgi:ls 296 25 | 26 | JBoss Fuse :: Examples :: Transactions :: Database (296) provides: 27 | ------------------------------------------------------------------ 28 | objectClass = [javax.persistence.EntityManagerFactory] 29 | org.apache.aries.jpa.container.managed = true 30 | org.apache.aries.jpa.default.unit.name = false 31 | osgi.unit.name = transactionsExample 32 | osgi.unit.provider = org.hibernate.ejb.HibernatePersistence 33 | osgi.unit.version = 6.3.0 34 | service.id = 634 35 | -------------------------------------------------------------------------------- /database/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 4.0.0 23 | 24 | 25 | org.jboss.fuse.examples 26 | esb-transactions 27 | 6.3.0 28 | 29 | 30 | org.jboss.fuse.examples.transactions 31 | database 32 | bundle 33 | 34 | JBoss Fuse :: Examples :: Transactions :: Database 35 | 36 | 37 | 38 | META-INF/persistence.xml 39 | 40 | javax.persistence;version="[2.0,2.1)", 41 | javax.persistence.criteria;version="[2.0,2.1)", 42 | javax.sql, 43 | org.hibernate;version="[4.2,4.3)", 44 | org.hibernate.proxy;version="[4.2,4.3)", 45 | javassist.util.proxy, 46 | org.hibernate.ejb;version="[4.2,5)" 47 | org.hibernate.proxy;version="[4.2,4.3)", 48 | 49 | 50 | org.jboss.fuse.examples.transactions.model 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.apache.camel 59 | camel-core 60 | 61 | 62 | 63 | 64 | org.apache.aries 65 | org.apache.aries.util-r42 66 | provided 67 | 68 | 69 | org.apache.aries.blueprint 70 | org.apache.aries.blueprint.core 71 | provided 72 | 73 | 74 | org.apache.aries.transaction 75 | org.apache.aries.transaction.blueprint 76 | provided 77 | 78 | 79 | org.apache.aries.jpa 80 | org.apache.aries.jpa.blueprint.aries 81 | provided 82 | 83 | 84 | org.apache.aries.jpa 85 | org.apache.aries.jpa.container 86 | provided 87 | 88 | 89 | org.apache.aries.jpa 90 | org.apache.aries.jpa.container.context 91 | provided 92 | 93 | 94 | org.osgi 95 | org.osgi.core 96 | provided 97 | 98 | 99 | 100 | 101 | 102 | org.hibernate 103 | hibernate-core 104 | provided 105 | 106 | 107 | org.hibernate 108 | hibernate-osgi 109 | provided 110 | 111 | 112 | org.hibernate 113 | hibernate-envers 114 | provided 115 | 116 | 117 | org.hibernate 118 | hibernate-entitymanager 119 | provided 120 | 121 | 122 | org.hibernate.javax.persistence 123 | hibernate-jpa-2.0-api 124 | provided 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | src/main/resources 133 | 134 | 135 | src/main/resources-filtered/${database} 136 | true 137 | 138 | 139 | 140 | 141 | 146 | 147 | org.apache.felix 148 | maven-bundle-plugin 149 | true 150 | 151 | 152 | ${persistence-file} 153 | ${project.artifactId} 154 | ${osgi-import-pkg} 155 | ${osgi-export-pkg} 156 | ${osgi-private-pkg} 157 | ${osgi-dynamic-pkg} 158 | {maven-resources} 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | postgresql 168 | 169 | true 170 | 171 | 172 | postgresql 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /database/src/main/java/org/jboss/fuse/examples/transactions/model/Flight.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2005-2015 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 5 | * 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | package org.jboss.fuse.examples.transactions.model; 17 | 18 | import java.io.Serializable; 19 | import javax.persistence.*; 20 | 21 | /** 22 | * A very simple entity class for a flight - every flight has: 23 | * - a flight number 24 | * - a departure airport 25 | * - an arrival airport 26 | */ 27 | @Entity 28 | @Access(AccessType.FIELD) 29 | @Table(name = "FLIGHTS") 30 | public class Flight implements Serializable { 31 | 32 | @Id 33 | @Column(length = 12) 34 | private String number; 35 | @Column(length = 3) 36 | private String departure; 37 | @Column(length = 3) 38 | private String arrival; 39 | 40 | public String getNumber() { 41 | return number; 42 | } 43 | 44 | public void setNumber(String number) { 45 | this.number = number; 46 | } 47 | 48 | public String getDeparture() { 49 | return departure; 50 | } 51 | 52 | public void setDeparture(String departure) { 53 | this.departure = departure; 54 | } 55 | 56 | public String getArrival() { 57 | return arrival; 58 | } 59 | 60 | public void setArrival(String arrival) { 61 | this.arrival = arrival; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return String.format("[flight %s from %s to %s]", number, departure, arrival); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /database/src/main/resources-filtered/postgresql/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 25 | 26 | 27 | 28 | 29 | Persistence unit for Fuse ESB Enterprise transactions example 30 | 31 | org.hibernate.ejb.HibernatePersistence 32 | 36 | osgi:service/jdbc/transactionsdbxa 37 | 38 | osgi:service/jdbc/transactionsdb 39 | 40 | org.jboss.fuse.examples.transactions.model.Flight 41 | true 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /datasource/README.md: -------------------------------------------------------------------------------- 1 | # Datasource bundle 2 | This bundle defines the JDBC `DataSource`s that will be used for accessing the 3 | relational database. 4 | 5 | 6 | ## Blueprint 7 | We are using Blueprint to define the data source bean and publish it into the OSGi Service Registry. Have a look at 8 | `src/main/resources/OSGI-INF/blueprint/datasource.xml` for more details about how this done. 9 | 10 | 11 | ## Checking the OSGi Service Registry 12 | After the bundle is started, we can use the Fuse ESB Enterprise console to look at the registered objects in the registry. 13 | 14 | First, find the bundle id for the bundle called "Fuse By Example :: Transactions :: Datasource" by using the `osgi:list` command. 15 | You can use `grep` to filter the list of bundles and quickly find the right one. 16 | 17 | JBossFuse:karaf@root> osgi:list | grep -i transactions 18 | [ 295] [Active ] [Created ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Datasource (6.3.0) 19 | [ 296] [Active ] [ ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Database (6.3.0) 20 | [ 297] [Active ] [Created ] [ ] [ 80] JBoss Fuse :: Examples :: Transactions :: Routing (6.3.0) 21 | 22 | In this example, the bundle id is 295. Using the `osgi:ls` command, we can see that this bundle is publishing 3 services: 23 | 24 | * first, there's the `javax.sql.XADataSource` that we created in our Blueprint XML file 25 | * secondly, Aries JTA has added a corresponding `javax.sql.DataSource` and added the `aries.xa.aware = true` property to it to indicate an XA-aware data source 26 | * finally, the Blueprint extender mechanism also published the Blueprint container (containg our data source bean definitions) it created 27 | 28 | This is what the `osgi:ls` output looks like 29 | 30 | JBossFuse:karaf@root> osgi:ls 295 31 | 32 | JBoss Fuse :: Examples :: Transactions :: Datasource (295) provides: 33 | -------------------------------------------------------------------- 34 | Bundle-SymbolicName = datasource 35 | Bundle-Version = 6.3.0 36 | objectClass = [org.osgi.service.cm.ManagedService] 37 | service.id = 628 38 | service.pid = org.jboss.fuse.examples.persistence2 39 | ---- 40 | aries.xa.exceptionSorter = known 41 | aries.xa.name = transactionsdb 42 | aries.xa.password = fuse 43 | aries.xa.pooling = true 44 | aries.xa.poolMaxSize = 10 45 | aries.xa.poolMinSize = 0 46 | aries.xa.transaction = local 47 | aries.xa.username = fuse 48 | objectClass = [javax.sql.DataSource] 49 | osgi.jndi.service.name = jdbc/transactionsdb 50 | osgi.service.blueprint.compname = dataSource 51 | service.id = 629 52 | ---- 53 | aries.managed = true 54 | aries.xa.exceptionSorter = known 55 | aries.xa.name = transactionsdb 56 | aries.xa.password = fuse 57 | aries.xa.pooling = true 58 | aries.xa.poolMaxSize = 10 59 | aries.xa.poolMinSize = 0 60 | aries.xa.transaction = local 61 | aries.xa.username = fuse 62 | objectClass = [javax.sql.DataSource] 63 | osgi.jndi.service.name = jdbc/transactionsdb 64 | osgi.service.blueprint.compname = dataSource 65 | service.id = 630 66 | service.ranking = 1000 67 | ---- 68 | aries.xa.exceptionSorter = known 69 | aries.xa.name = transactionsdbxa 70 | aries.xa.password = fuse 71 | aries.xa.pooling = true 72 | aries.xa.poolMaxSize = 10 73 | aries.xa.poolMinSize = 0 74 | aries.xa.transaction = xa 75 | aries.xa.username = fuse 76 | objectClass = [javax.sql.XADataSource] 77 | osgi.jndi.service.name = jdbc/transactionsdbxa 78 | osgi.service.blueprint.compname = xaDataSource 79 | service.id = 631 80 | ---- 81 | aries.managed = true 82 | aries.xa.aware = true 83 | aries.xa.exceptionSorter = known 84 | aries.xa.name = transactionsdbxa 85 | aries.xa.password = fuse 86 | aries.xa.pooling = true 87 | aries.xa.poolMaxSize = 10 88 | aries.xa.poolMinSize = 0 89 | aries.xa.transaction = xa 90 | aries.xa.username = fuse 91 | objectClass = [javax.sql.DataSource] 92 | osgi.jndi.service.name = jdbc/transactionsdbxa 93 | osgi.service.blueprint.compname = xaDataSource 94 | service.id = 632 95 | service.ranking = 1000 96 | ---- 97 | objectClass = [org.osgi.service.blueprint.container.BlueprintContainer] 98 | osgi.blueprint.container.symbolicname = datasource 99 | osgi.blueprint.container.version = 6.3.0 100 | service.id = 633 101 | -------------------------------------------------------------------------------- /datasource/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 4.0.0 23 | 24 | 25 | org.jboss.fuse.examples 26 | esb-transactions 27 | 6.3.0 28 | 29 | 30 | org.jboss.fuse.examples.transactions 31 | datasource 32 | bundle 33 | 34 | JBoss Fuse :: Examples :: Transactions :: Datasource 35 | 36 | 37 | 38 | 39 | javax.sql, 40 | org.postgresql, 41 | org.postgresql.ds, 42 | org.postgresql.xa, 43 | org.apache.commons.dbcp2 44 | 45 | 46 | 47 | 48 | 49 | 50 | 60 | 61 | org.apache.commons 62 | commons-dbcp2 63 | ${commons.dbcp2.version} 64 | 65 | 66 | commons-logging 67 | commons-logging 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | org.apache.aries.transaction 76 | org.apache.aries.transaction.jdbc 77 | ${aries.transaction.jdbc.version} 78 | provided 79 | 80 | 81 | org.apache.aries.transaction 82 | org.apache.aries.transaction.manager 83 | 1.1.1 84 | provided 85 | 86 | 87 | org.apache.geronimo.components 88 | geronimo-connector 89 | 3.1.1 90 | provided 91 | 92 | 93 | org.osgi 94 | org.osgi.core 95 | provided 96 | 97 | 98 | 99 | 100 | 101 | org.apache.karaf.jdbc 102 | org.apache.karaf.jdbc.command 103 | 104 | 105 | 106 | 107 | 108 | org.apache.geronimo.specs 109 | geronimo-jta_1.1_spec 110 | 1.1.1 111 | provided 112 | 113 | 114 | org.apache.geronimo.specs 115 | geronimo-j2ee-connector_1.6_spec 116 | 1.0 117 | provided 118 | 119 | 120 | 121 | 122 | 123 | org.slf4j 124 | slf4j-api 125 | 126 | 127 | org.slf4j 128 | jcl-over-slf4j 129 | 130 | 131 | ch.qos.logback 132 | logback-classic 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | src/main/resources 141 | 142 | 143 | src/main/resources-filtered/${database} 144 | OSGI-INF/blueprint 145 | true 146 | 147 | 148 | 149 | src/main/resources/jdbc.properties 150 | 151 | compile exec:java 152 | 153 | 154 | org.codehaus.mojo 155 | exec-maven-plugin 156 | 157 | org.jboss.fuse.examples.transactions.tools.DbInsert 158 | 159 | ${database} 160 | 161 | -1 162 | false 163 | 164 | 165 | 166 | initdb 167 | 168 | java 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | postgresql 179 | 180 | true 181 | 182 | 183 | postgresql 184 | 185 | 186 | 192 | 193 | org.postgresql 194 | postgresql 195 | 9.3-1102-jdbc41 196 | 197 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /datasource/src/main/java/org/jboss/fuse/examples/transactions/tools/DataSources.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2005-2015 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 5 | * 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | package org.jboss.fuse.examples.transactions.tools; 17 | 18 | import java.io.IOException; 19 | import java.util.Properties; 20 | import javax.sql.DataSource; 21 | 22 | public class DataSources { 23 | 24 | private static Properties properties = new Properties(); 25 | 26 | static { 27 | try { 28 | properties.load(DataSources.class.getResourceAsStream("/jdbc.properties")); 29 | } catch (IOException e) { 30 | throw new RuntimeException(e.getMessage(), e); 31 | } 32 | } 33 | 34 | public static DataSource findDataSource(String db) throws Exception { 35 | switch (db) { 36 | case "postgresql": 37 | return postgresql(); 38 | } 39 | return null; 40 | } 41 | 42 | private static DataSource postgresql() throws Exception { 43 | Class dsClass = Class.forName("org.postgresql.ds.PGSimpleDataSource"); 44 | DataSource ds = (DataSource) dsClass.newInstance(); 45 | set(ds, "url", "jdbc.postgresql.url"); 46 | set(ds, "user", "jdbc.postgresql.user"); 47 | set(ds, "password", "jdbc.postgresql.password"); 48 | 49 | return ds; 50 | } 51 | 52 | private static void set(DataSource ds, String property, String key) throws Exception { 53 | String method = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); 54 | ds.getClass().getMethod(method, String.class).invoke(ds, properties.getProperty(key)); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /datasource/src/main/java/org/jboss/fuse/examples/transactions/tools/DbInsert.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2005-2015 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 5 | * 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | package org.jboss.fuse.examples.transactions.tools; 17 | 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | import java.io.IOException; 21 | import java.io.StringWriter; 22 | import java.sql.Connection; 23 | import java.sql.SQLException; 24 | import java.sql.Statement; 25 | import java.util.Arrays; 26 | import java.util.HashSet; 27 | import java.util.LinkedList; 28 | import java.util.List; 29 | import java.util.Set; 30 | import javax.sql.DataSource; 31 | 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | 35 | public class DbInsert { 36 | 37 | public static Logger LOG = LoggerFactory.getLogger(DbInsert.class); 38 | 39 | public static String[] NON_FATAL_SQLSTATES = { 40 | "42Y07", // Derby: Schema 'schema' does not exist (SQLState: 42Y07) 41 | "42Y55", // Derby: 'DROP TABLE' cannot be performed on 'schema.table' because it does not exist. (SQLState: 42Y55) 42 | "42704", // DB2: SQL Error: SQLCODE=-204, SQLSTATE=42704 'name' is an undefined name. 43 | "42000", // Oracle: ORA-00942: table or view does not exist 44 | }; 45 | 46 | public static void main(String[] args) throws Exception { 47 | String db = (args == null || args.length == 0) ? "postgresql" : args[0]; 48 | Set nonFatalSqlStates = new HashSet<>(Arrays.asList(NON_FATAL_SQLSTATES)); 49 | 50 | DataSource ds = DataSources.findDataSource(db); 51 | 52 | if (ds == null) { 53 | LOG.warn("No datasource configuration found for \"" + db + "\" database type"); 54 | return; 55 | } 56 | 57 | try (Connection con = ds.getConnection()) { 58 | try (Statement st = con.createStatement()) { 59 | String[] scripts = readScripts(db, "initdb.sql"); 60 | try { 61 | for (String script : scripts) { 62 | try { 63 | st.execute(script); 64 | } catch (SQLException e) { 65 | // for databases which don't support "IF EXISTS" clause 66 | if (!nonFatalSqlStates.contains(e.getSQLState())) { 67 | throw e; 68 | } 69 | } 70 | } 71 | LOG.info("Database " + db + " initialized successfully"); 72 | } catch (SQLException e) { 73 | LOG.error(e.getMessage() + " (SQLState: " + e.getSQLState() + ")"); 74 | } 75 | } 76 | } 77 | } 78 | 79 | private static String[] readScripts(String db, String script) throws IOException { 80 | File file = new File("src/main/sql/" + db + "/" + script); 81 | byte[] bytes = new byte[(int) file.length()]; 82 | try (FileInputStream fis = new FileInputStream(file)) { 83 | fis.read(bytes); 84 | } 85 | StringWriter sw = new StringWriter(); 86 | List scripts = new LinkedList<>(); 87 | char[] chars = new String(bytes, "UTF-8").toCharArray(); 88 | int pos = 0; 89 | STATE st = STATE.DEFAULT; 90 | while (pos < chars.length) { 91 | char c = chars[pos++]; 92 | switch (st) { 93 | case DEFAULT: { 94 | if (c == '-' && (pos < chars.length && chars[pos] == '-')) { 95 | st = STATE.COMMENT; 96 | } else if (c == '\'') { 97 | sw.append(c); 98 | st = STATE.STRING_LITERAL; 99 | } else if (c == ';') { 100 | scripts.add(sw.toString()); 101 | sw = new StringWriter(); 102 | } else { 103 | sw.append(c); 104 | } 105 | break; 106 | } 107 | case COMMENT: { 108 | if (c == '\n') { 109 | st = STATE.DEFAULT; 110 | } 111 | break; 112 | } 113 | case STRING_LITERAL: { 114 | sw.append(c); 115 | if (c == '\'') { 116 | st = STATE.DEFAULT; 117 | } 118 | break; 119 | } 120 | } 121 | } 122 | return scripts.toArray(new String[scripts.size()]); 123 | } 124 | 125 | private enum STATE { 126 | DEFAULT, COMMENT, STRING_LITERAL 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /datasource/src/main/resources-filtered/postgresql/datasource.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 24 | 25 | 26 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 74 | 75 | 76 | 77 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /datasource/src/main/resources/jdbc.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2005-2015 Red Hat, Inc. 3 | # 4 | # Red Hat licenses this file to you under the Apache License, version 5 | # 2.0 (the "License"); you may not use this file except in compliance 6 | # with the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | # implied. See the License for the specific language governing 14 | # permissions and limitations under the License. 15 | # 16 | 17 | 18 | # PostgreSQL database 19 | 20 | jdbc.postgresql.url = jdbc:postgresql://localhost:5432/transactions 21 | jdbc.postgresql.user = fuse 22 | jdbc.postgresql.password = fuse 23 | -------------------------------------------------------------------------------- /datasource/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | 23 | %d{HH:mm:ss.SSS} %-5level [%logger{1}] : %msg%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /datasource/src/main/sql/postgresql/initdb.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Copyright 2005-2015 Red Hat, Inc. 3 | -- 4 | -- Red Hat licenses this file to you under the Apache License, version 5 | -- 2.0 (the "License"); you may not use this file except in compliance 6 | -- with the License. You may obtain a copy of the License at 7 | -- 8 | -- http://www.apache.org/licenses/LICENSE-2.0 9 | -- 10 | -- Unless required by applicable law or agreed to in writing, software 11 | -- distributed under the License is distributed on an "AS IS" BASIS, 12 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | -- implied. See the License for the specific language governing 14 | -- permissions and limitations under the License. 15 | -- 16 | 17 | -- Initial setup of PostgreSQL database 18 | 19 | DROP SCHEMA IF EXISTS transactions CASCADE; 20 | 21 | CREATE SCHEMA transactions; 22 | 23 | CREATE TABLE transactions.flights ( 24 | number VARCHAR(12) NOT NULL PRIMARY KEY, 25 | departure VARCHAR(3), 26 | arrival VARCHAR(3) 27 | ); 28 | -------------------------------------------------------------------------------- /features/README.md: -------------------------------------------------------------------------------- 1 | # Features 2 | This project creates a features definition that can be used to install the example. 3 | 4 | ## How it works? 5 | Using Maven's resource filtering mechanism, we replace the `${xyz.version}` tokens in the `src/main/resources/features.xml` file. 6 | Afterwards, the resulting file is published as a Maven artifact itself so you can use it from within the Fuse ESB console with 7 | 8 | JBossFuse:karaf@root> features:addurl mvn:org.jboss.fuse.examples.transactions/features/6.3,0/xml/features 9 | 10 | Inside the features file, you'll find a definition for feature called `transactions-demo`. -------------------------------------------------------------------------------- /features/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 4.0.0 23 | 24 | 25 | org.jboss.fuse.examples 26 | esb-transactions 27 | 6.3.0 28 | 29 | 30 | org.jboss.fuse.examples.transactions 31 | features 32 | jar 33 | 34 | JBoss Fuse :: Examples :: Transactions :: Features 35 | 36 | 37 | 38 | 39 | 40 | src/main/resources 41 | true 42 | 43 | **/* 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.codehaus.mojo 52 | build-helper-maven-plugin 53 | 54 | 55 | attach-artifacts 56 | package 57 | 58 | attach-artifact 59 | 60 | 61 | 62 | 63 | target/classes/features.xml 64 | xml 65 | features 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /features/src/main/resources/features.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | jdbc-driver-${database} 23 | jpa 24 | jndi 25 | camel-blueprint 26 | camel-jpa 27 | camel-jms 28 | hibernate 29 | hibernate-envers 30 | hibernate-validator 31 | transaction 32 | connector 33 | 34 | mvn:org.jboss.fuse.examples.transactions/datasource/${project.version} 35 | mvn:org.jboss.fuse.examples.transactions/database/${project.version} 36 | mvn:org.jboss.fuse.examples.transactions/routing/${project.version} 37 | 38 | 39 | 40 | 41 | wrap:mvn:org.postgresql/postgresql/${jdbc.postgresql.version} 42 | 43 | 44 | mvn:org.apache.aries.transaction/org.apache.aries.transaction.jdbc/${aries.transaction.jdbc.version} 45 | mvn:org.apache.commons/commons-pool2/${commons.pool2.version} 46 | mvn:org.apache.commons/commons-dbcp2/${commons.dbcp2.version} 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /fuse-license-header.txt: -------------------------------------------------------------------------------- 1 | Copyright 2005-2015 Red Hat, Inc. 2 | 3 | Red Hat licenses this file to you under the Apache License, version 4 | 2.0 (the "License"); you may not use this file except in compliance 5 | with the License. You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | implied. See the License for the specific language governing 13 | permissions and limitations under the License. 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 4.0.0 23 | 24 | org.jboss.fuse.examples 25 | esb-transactions 26 | 6.3.0 27 | pom 28 | 29 | JBoss Fuse :: Examples :: Transactions 30 | 31 | 32 | datasource 33 | database 34 | routing 35 | features 36 | 37 | 38 | 39 | UTF-8 40 | 41 | 42 | 6.3.0.redhat-187 43 | 1.7.10 44 | 1.1.2 45 | 2.4.0.redhat-630187 46 | 2.17.0.redhat-630187 47 | 5.11.0.redhat-630187 48 | 4.2.19.Final-redhat-1 49 | 2.1.1 50 | 3.2.12.RELEASE 51 | 3.2.12.RELEASE_2 52 | 2.1 53 | 2.0.1 54 | 9.3-1102-jdbc41 55 | 56 | 57 | ${activemq.version} 58 | ${camel.version} 59 | 1.3.0 60 | 3.1.1 61 | 2.3.0 62 | 63 | 64 | 2.6.1 65 | 3.3 66 | 2.8.2 67 | 2.5.2 68 | 2.7 69 | 3.4 70 | 2.18.1 71 | 2.6 72 | 2.5.3 73 | 1.9.1 74 | 1.3.2 75 | 2.1 76 | 2.8 77 | 78 | 79 | 80 | * 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | redhat-ga-repository 90 | https://maven.repository.redhat.com/ga 91 | 92 | true 93 | 94 | 95 | false 96 | 97 | 98 | 99 | 100 | 101 | 102 | redhat-ga-repository 103 | https://maven.repository.redhat.com/ga 104 | 105 | true 106 | 107 | 108 | false 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | org.jboss.fuse.bom 120 | jboss-fuse-parent 121 | ${jboss.fuse.bom.version} 122 | pom 123 | import 124 | 125 | 126 | 127 | 128 | 129 | org.jboss.fuse.examples.transactions 130 | database 131 | 6.3.0 132 | 133 | 134 | 135 | 136 | 137 | org.apache.aries 138 | org.apache.aries.util-r42 139 | 1.1.0 140 | 141 | 142 | org.apache.aries.blueprint 143 | org.apache.aries.blueprint.core 144 | 1.4.4 145 | 146 | 147 | org.apache.aries.transaction 148 | org.apache.aries.transaction.blueprint 149 | 1.0.2 150 | 151 | 152 | org.apache.aries.jpa 153 | org.apache.aries.jpa.blueprint.aries 154 | 1.0.4 155 | provided 156 | 157 | 158 | org.apache.aries.jpa 159 | org.apache.aries.jpa.container 160 | 1.0.2 161 | provided 162 | 163 | 164 | org.apache.aries.jpa 165 | org.apache.aries.jpa.container.context 166 | 1.0.4 167 | provided 168 | 169 | 170 | 171 | 172 | 173 | org.hibernate 174 | hibernate-core 175 | ${hibernate.version} 176 | 177 | 178 | org.hibernate 179 | hibernate-entitymanager 180 | ${hibernate.version} 181 | 182 | 183 | org.hibernate 184 | hibernate-osgi 185 | ${hibernate.version} 186 | 187 | 188 | org.hibernate 189 | hibernate-envers 190 | ${hibernate.version} 191 | 192 | 193 | org.hibernate.javax.persistence 194 | hibernate-jpa-2.0-api 195 | 1.0.1.Final 196 | 197 | 198 | 199 | 200 | 201 | org.apache.karaf.jdbc 202 | org.apache.karaf.jdbc.command 203 | ${karaf.version} 204 | 205 | 206 | 207 | 208 | 209 | org.slf4j 210 | slf4j-api 211 | ${slf4j.version} 212 | 213 | 214 | org.slf4j 215 | jcl-over-slf4j 216 | ${slf4j.version} 217 | 218 | 219 | ch.qos.logback 220 | logback-classic 221 | ${logback.version} 222 | 223 | 224 | 225 | 226 | 227 | org.apache.activemq 228 | activemq-camel 229 | ${activemq.version} 230 | 231 | 232 | 233 | org.apache.camel 234 | camel-core 235 | ${camel.version} 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | maven-clean-plugin 247 | ${maven.clean.plugin.version} 248 | 249 | 250 | maven-compiler-plugin 251 | ${maven.compiler.plugin.version} 252 | 253 | 254 | maven-deploy-plugin 255 | ${maven.deploy.plugin.version} 256 | 257 | 258 | maven-install-plugin 259 | ${maven.install.plugin.version} 260 | 261 | 262 | maven-resources-plugin 263 | ${maven.resources.plugin.version} 264 | 265 | 266 | maven-site-plugin 267 | ${maven.site.plugin.version} 268 | 269 | 270 | maven-surefire-plugin 271 | ${maven.surefire.plugin.version} 272 | 273 | 274 | 275 | maven-jar-plugin 276 | ${maven.jar.plugin.version} 277 | 278 | 279 | 280 | org.apache.felix 281 | maven-bundle-plugin 282 | ${felix.bundle.plugin.version} 283 | 284 | 285 | 286 | org.codehaus.mojo 287 | build-helper-maven-plugin 288 | ${codehaus.buildhelper.plugin.version} 289 | 290 | 291 | org.codehaus.mojo 292 | exec-maven-plugin 293 | ${codehaus.exec.plugin.version} 294 | 295 | 296 | org.codehaus.mojo 297 | versions-maven-plugin 298 | ${codehaus.versions.plugin.version} 299 | 300 | 301 | 302 | com.mycila 303 | license-maven-plugin 304 | ${mycila.license.plugin} 305 | 306 | 307 | 308 | 309 | 310 | 311 | maven-compiler-plugin 312 | 313 | 1.7 314 | 1.7 315 | 316 | 317 | 318 | 319 | org.apache.felix 320 | maven-bundle-plugin 321 | true 322 | ${felix.bundle.plugin.version} 323 | 324 | 325 | ${persistence-file} 326 | ${project.artifactId} 327 | ${osgi-import-pkg} 328 | ${osgi-export-pkg} 329 | ${osgi-private-pkg} 330 | ${osgi-dynamic-pkg} 331 | {maven-resources} 332 | 333 | 334 | 335 | 336 | 337 | org.codehaus.mojo 338 | versions-maven-plugin 339 | 340 | 341 | 342 | 343 | 344 | 345 | postgresql 346 | 347 | true 348 | 349 | 350 | postgresql 351 | 352 | 353 | 354 | 362 | license 363 | 364 | 365 | 366 | com.mycila 367 | license-maven-plugin 368 | 369 |
fuse-license-header.txt
370 | 371 | **/pom.xml 372 | **/*.md 373 | src/**/*.xml 374 | src/**/*.java 375 | src/**/*.sql 376 | src/**/*.properties 377 | 378 | 379 | XML_STYLE 380 | 381 | false 382 |
383 | 384 | 385 | default 386 | 387 | verify 388 | 389 | check 390 | 391 | 392 | 393 |
394 |
395 |
396 |
397 |
398 | 399 |
400 | -------------------------------------------------------------------------------- /routing/README.md: -------------------------------------------------------------------------------- 1 | # Routing bundle 2 | In this bundle, we will bring together the services we set up in all our other bundles inside one Camel route. We will 3 | receive JMS messages, transform them into a `Flight` POJO and then persist those into the database using JPA. 4 | 5 | For coördinating the transactions with the JMS broker and the RDBMS, we will use Fuse ESB Enterprise's built-in JTA support 6 | (based Aries JTA). 7 | 8 | ## Blueprint XML 9 | The Blueprint XML file at `src/main/java/resources/OSGI-INF/blueprint/routing.xml' is where we glue everything together. 10 | 11 | First, we retrieve some of the services available in the OSGi Service Registry: 12 | 13 | * the global transaction manager provided by Fuse ESB Enterprise 14 | * the JPA EntityManagerFactory that we set up ourselves in the `database` module 15 | 16 | Afterwards, we define our two Camel components and link them up with the correct shared services: 17 | 18 | * the JMS component is defined with an XA-aware connection factory and a reference to the global transaction manager 19 | * the JPA component is defined with a reference to the JPA EntityManagerFactory 20 | 21 | The Blueprint XML file will also define the CamelContext itself, the Camel routes themselves are defined in a Java class. 22 | 23 | ## TransactionalRouteBuilder 24 | The `src/main/java/org/jboss/fuse/examples/transactions/routes/TransactionalRouteBuilder.java` class defines the actual 25 | Camel routes. The code looks like a plain route from a JMS endpoint to a JPA endpoint, but there 2 little things to notice here: 26 | 27 | * the class extends SpringRouteBuilder, to allow for seamless integration between the route and Spring's support for transactions 28 | * because the route starts with a transaction-enabled endpoint amq://Input.Flights, a new transaction will _automatically_ be started whenever a message gets pulled from the queue. There is no need to call the `transacted()` DSL method. 29 | -------------------------------------------------------------------------------- /routing/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 21 | 22 | 4.0.0 23 | 24 | 25 | org.jboss.fuse.examples 26 | esb-transactions 27 | 6.3.0 28 | 29 | 30 | org.jboss.fuse.examples.transactions 31 | routing 32 | bundle 33 | 34 | JBoss Fuse :: Examples :: Transactions :: Routing 35 | 36 | 37 | 38 | * 39 | 40 | org.jboss.fuse.examples.transactions.routes 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.jboss.fuse.examples.transactions 48 | database 49 | 50 | 51 | 52 | org.apache.camel 53 | camel-core 54 | 55 | 56 | 57 | org.apache.activemq 58 | activemq-camel 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.apache.felix 70 | maven-bundle-plugin 71 | true 72 | 73 | 74 | ${project.artifactId} 75 | ${osgi-import-pkg} 76 | <_removeheaders>Import-Service 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /routing/src/main/java/org/jboss/fuse/examples/transactions/routes/Airports.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2005-2015 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 5 | * 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | package org.jboss.fuse.examples.transactions.routes; 17 | 18 | import java.util.Random; 19 | 20 | /** 21 | * Helper class to generate random airport codes out of 50 of the busiest airports in the world. 22 | */ 23 | public class Airports { 24 | 25 | private static final String[] AIRPORTS = 26 | new String[] { "ATL", "PEK", "LHR", "ORD", "HND", "LAX", "CDG", "DFW", "FRA", "HKG", 27 | "DEN", "CGK", "DXB", "AMS", "MAD", "BKK", "JFK", "SIN", "CAN", "LAS", 28 | "PVG", "SFO", "PHX", "IAH", "CLT", "MIA", "MUC", "KUL", "FCO", "IST", 29 | "SYD", "MCO", "ICN", "DEL", "BCN", "LGW", "EWR", "YYZ", "SHA", "MSP", 30 | "SEA", "DTW", "PHL", "BOM", "GRU", "MNL", "CTU", "BOS", "SZX", "MEL" }; 31 | 32 | private static final Random RANDOM = new Random(); 33 | 34 | /** 35 | * Generate a random airport code. 36 | */ 37 | public static final String randomAirport() { 38 | return AIRPORTS[RANDOM.nextInt(AIRPORTS.length)]; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /routing/src/main/java/org/jboss/fuse/examples/transactions/routes/TransactionalRouteBuilder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2005-2015 Red Hat, Inc. 3 | * 4 | * Red Hat licenses this file to you under the Apache License, version 5 | * 2.0 (the "License"); you may not use this file except in compliance 6 | * with the License. You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | package org.jboss.fuse.examples.transactions.routes; 17 | 18 | import org.apache.camel.Exchange; 19 | import org.apache.camel.Processor; 20 | import org.apache.camel.spring.SpringRouteBuilder; 21 | import org.jboss.fuse.examples.transactions.model.Flight; 22 | 23 | import static org.jboss.fuse.examples.transactions.routes.Airports.randomAirport; 24 | 25 | /** 26 | * Camel route builder defining our transactional route. Because we want to maximize the level of support Spring offers for transactions, 27 | * we are extending SpringRouteBuilder instead of a plain RouteBuilder. 28 | * 29 | * Transaction demarcation (begin() and commit()) is performed by the transaction-aware 'amq' endpoint. Hence, there is no need to add the transacted() DSL keyword to the route. 30 | */ 31 | public class TransactionalRouteBuilder extends SpringRouteBuilder { 32 | 33 | @Override 34 | public void configure() throws Exception { 35 | from("amq://Input.Flights?username=admin&password=admin") 36 | .log("Received JMS message ${body}") 37 | .process(new ConvertToJpaBeanProcessor()) 38 | .log("Storing ${body} in the database") 39 | .to("jpa://org.jboss.fuse.examples.transactions.model.Flight"); 40 | } 41 | 42 | /* 43 | * Just a simple Camel processor to transform a plain text message into a Flight object. 44 | */ 45 | private class ConvertToJpaBeanProcessor implements Processor { 46 | 47 | public void process(Exchange exchange) throws Exception { 48 | exchange.getOut().copyFrom(exchange.getIn()); 49 | 50 | String number = exchange.getIn().getBody(String.class); 51 | 52 | Flight flight = new Flight(); 53 | flight.setNumber(number); 54 | flight.setDeparture(randomAirport()); 55 | flight.setArrival(randomAirport()); 56 | 57 | exchange.getOut().setBody(flight); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /routing/src/main/resources/OSGI-INF/blueprint/routing.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 106 | 107 | org.jboss.fuse.examples.transactions.routes 108 | 109 | 110 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 124 | 125 | 126 | 127 | 128 | 129 | --------------------------------------------------------------------------------