├── .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 |
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 |
--------------------------------------------------------------------------------