Skip to content

Commit 8ccf965

Browse files
committed
Provide jpa-javase project that illustrates JPA API usage in standalone scenario
1 parent 42a497e commit 8ccf965

File tree

31 files changed

+2038
-360
lines changed

31 files changed

+2038
-360
lines changed

README.md

+117-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ It covers the different demos made during the talk and is organised like that:
88
* `jdbc-blueprint`: Maven project using camel-jdbc component and Blueprint XML DSL
99
* `sql-spring`: Maven project using camel-sql component and Spring XML DSL
1010
* `sql-blueprint`: Maven project using camel-sql component and Blueprint XML DSL
11+
* `jpa-javase`: Maven project with JUnit tests showing JPA API usage with local and JTA transactions
1112

1213
# Initial setup
1314

@@ -27,22 +28,40 @@ You can use any of available methods to access PostgreSQL server (e.g., by mappi
2728

2829
$ docker run -d --name fuse-postgresql-server -e POSTGRES_USER=fuse -e POSTGRES_PASSWORD=fuse -p 5432:5432 postgres:9.6.4
2930

30-
2. Create `reportdb` database by from the `fuse-postgresql-server` container:
31+
2. Create `reportdb` database from the `fuse-postgresql-server` container:
3132

3233
$ docker exec -ti fuse-postgresql-server /bin/bash
33-
root@3e37b4b579c7:/# psql -U fuse -d fuse
34-
psql (9.4.0)
34+
root@58b0d9de9c5b:/# psql -U fuse -d fuse
35+
psql (9.6.4)
3536
Type "help" for help.
3637
fuse=# create database reportdb owner fuse encoding 'utf8';
3738
CREATE DATABASE
38-
fuse=# \q
39+
fuse=# \c reportdb
40+
You are now connected to database "reportdb" as user "fuse".
41+
reportdb=# create schema report;
42+
CREATE SCHEMA
43+
reportdb=# \q
44+
45+
3. Create `reportdb2` database from the `fuse-postgresql-server` container (for XA purposes):
46+
47+
$ docker exec -ti fuse-postgresql-server /bin/bash
48+
root@58b0d9de9c5b:/# psql -U fuse -d fuse
49+
psql (9.6.4)
50+
Type "help" for help.
51+
fuse=# create database reportdb2 owner fuse encoding 'utf8';
52+
CREATE DATABASE
53+
fuse=# \c reportdb2
54+
You are now connected to database "reportdb2" as user "fuse".
55+
reportdb2=# create schema report;
56+
CREATE SCHEMA
57+
reportdb2=# \q
3958

40-
3. Initialize database `reportdb` by creating schema, table and populating the table with data.
59+
4. Initialize database `reportdb` by creating schema, table and populating the table with data.
4160

4261
$ cd $PROJECT_HOME/database
4362
$ docker cp src/config/postgresql/reportdb-postgresql-script.sql fuse-postgresql-server:/tmp
4463
$ docker exec -ti fuse-postgresql-server /bin/bash
45-
$ root@58b0d9de9c5b:/# psql -U fuse -d reportdb -f /tmp/reportdb-postgresql-script.sql
64+
root@58b0d9de9c5b:/# psql -U fuse -d reportdb -f /tmp/reportdb-postgresql-script.sql
4665
...
4766
DROP SCHEMA
4867
CREATE SCHEMA
@@ -52,6 +71,13 @@ You can use any of available methods to access PostgreSQL server (e.g., by mappi
5271
INSERT 0 1
5372
INSERT 0 1
5473

74+
5. Configure PostgreSQL database to allow XA transactions by setting `max_prepared_transactions` to the value equal
75+
or greater than `max_connections` setting (`100` in the case of `postgres:9.6.4` image).
76+
77+
root@58b0d9de9c5b:/# sed -i 's/^#max_prepared_transactions = 0/max_prepared_transactions = 200/' /var/lib/postgresql/data/postgresql.conf
78+
79+
5. Restart `fuse-postgresql-server` container. Your PostgreSQL database is ready to use.
80+
5581
# Running examples
5682

5783
## `jdbc-spring` and `jdbc-blueprint`
@@ -118,3 +144,88 @@ to be invoked.
118144

119145
$ cd $PROJECT_HOME/sql-blueprint
120146
$ mvn clean package camel:run
147+
148+
## `jpa-javase`
149+
150+
This project should be examined before running `jpa-spring` and `jpa-blueprint` (and supporting `jpa-ds` and `jpa-model`).
151+
`jpa-javase` shows few _canonical_ ways of using JPA API with Hibernate JPA provider.
152+
According to JPA 2.0 specification (JSR 317), JPA can successfully be used outside application server - in pure JavaSE
153+
environment. Using JPA this way is described as _application-managed Entity Manager_.
154+
155+
In this mode, it's the role of application developer to create `EntityManagerFactory` and obtain `EntityManager`. (In
156+
application server, i.e., when using _container-managed Entity Manager_, `EntityManager` instance is injected to application
157+
code using `@javax.persistence.PersistenceContext` annotation).
158+
159+
`jpa-javase` provides 3 unit tests that illustrate few uses cases related to JPA:
160+
161+
* `com.fusesource.examples.persistence.part1.DiscoveryTest.discovery()`: a tiny example of using JPA discover API,
162+
where we can check what is the configured (discovered) `javax.persistence.spi.PersistenceProvider` instance.
163+
* `com.fusesource.examples.persistence.part1.JavaSETest.bootstrapAndUseApplicationManagedResourceLocalEntityManager()`:
164+
Full example using `transaction-type="RESOURCE_LOCAL"` that shows how to:
165+
* create dbcp2 `javax.sql.DataSource`
166+
* use `javax.persistence.Persistence.createEntityManagerFactory()` to _create_ application-managed EMF using provided properties
167+
* use `javax.persistence.EntityManagerFactory.createEntityManager()` to _obtain_ EntityManager
168+
* use `javax.persistence.EntityTransaction` API to manually demarcate JPA transactions according to declared `transaction-type="RESOURCE_LOCAL"`
169+
* use `javax.persistence.EntityManager.persist()` to simply use JPA API
170+
* use plain JDBC code to verify that record was indeed persisted to database
171+
* `com.fusesource.examples.persistence.part1.JavaSETest.bootstrapAndUseApplicationManagedJTAEntityManager()`:
172+
Full example using `transaction-type="JTA"` that shows how to:
173+
* create fully functional `javax.transaction.TransactionManager`/`javax.transaction.UserTransaction` instances using
174+
aries.transaction.manager
175+
* create 2 `org.postgresql.xa.PGXADataSource` instances for XA-aware access to PostgreSQL database
176+
* create 2 `javax.sql.DataSource` instances that are using JCA API to interact with aries.jdbc and provide
177+
XA-aware, JTA-enlisting, pooling data sources
178+
* use `javax.persistence.Persistence.createEntityManagerFactory()` to _create_ application-managed EMF using provided properties
179+
* use `javax.persistence.EntityManagerFactory.createEntityManager()` to _obtain_ EntityManager
180+
* use `javax.transaction.UserTransaction` API to manually demarcate JPA transactions according to declared `transaction-type="JTA"`
181+
* use `javax.persistence.EntityManager.joinTransaction()` to tie JPA to JTA
182+
* use `javax.persistence.EntityManager.persist()` to simply use JPA API
183+
* use plain JDBC to insert row to 2nd database within the same global JTA transaction
184+
* use plain JDBC code to verify that record was indeed persisted to both databases
185+
186+
## `jpa-spring` and `jpa-blueprint` - TODO
187+
188+
install -s mvn:org.postgresql/postgresql/42.1.4
189+
install -s mvn:org.apache.commons/commons-pool2/2.4.2
190+
install -s mvn:org.apache.commons/commons-dbcp2/2.1.1
191+
features:install jndi jpa hibernate camel-jpa
192+
features:install camel-jpa
193+
features:install transaction connector
194+
install -s mvn:com.fusesource.examples.camel-persistence-part1/jpa-ds/1.0
195+
196+
JBossFuse:karaf@root> ls 317
197+
198+
FuseSource :: Examples :: Camel Persistence :: JPA Data Source (317) provides:
199+
------------------------------------------------------------------------------
200+
Bundle-SymbolicName = com.fusesource.examples.camel-persistence-part1.jpa-ds
201+
Bundle-Version = 1.0.0
202+
objectClass = [javax.sql.DataSource]
203+
org.springframework.osgi.bean.name = reportdb
204+
osgi.jndi.service.name = jdbc/reportdb
205+
service.id = 659
206+
----
207+
Bundle-SymbolicName = com.fusesource.examples.camel-persistence-part1.jpa-ds
208+
Bundle-Version = 1.0.0
209+
objectClass = [org.springframework.osgi.context.DelegatedExecutionOsgiBundleApplicationContext, org.springframework.osgi.context.ConfigurableOsgiBundleApplicationContext, org.springframework.context.ConfigurableApplicationContext, org.springframework.context.ApplicationContext, org.springframework.context.Lifecycle, java.io.Closeable, org.springframework.beans.factory.ListableBeanFactory, org.springframework.beans.factory.HierarchicalBeanFactory, org.springframework.context.MessageSource, org.springframework.context.ApplicationEventPublisher, org.springframework.core.io.support.ResourcePatternResolver, org.springframework.beans.factory.BeanFactory, org.springframework.core.io.ResourceLoader, java.lang.AutoCloseable, org.springframework.beans.factory.DisposableBean]
210+
org.springframework.context.service.name = com.fusesource.examples.camel-persistence-part1.jpa-ds
211+
service.id = 660
212+
213+
### Aries JPA internals
214+
215+
org.apache.aries.jpa.container bundle:
216+
217+
* `org.apache.aries.jpa.container.parsing.PersistenceDescriptorParser` service implemented by
218+
`org.apache.aries.jpa.container.parsing.impl.PersistenceDescriptorParserImpl` - parses `META-INF/persistence.xml`
219+
descriptors into `org.apache.aries.jpa.container.parsing.impl.PersistenceUnitImpl` objects using
220+
`org.apache.aries.jpa.container.parsing.impl.JPAHandler`
221+
* `org.apache.aries.jpa.container.impl.PersistenceBundleManager` - locates, parses and manages persistence units
222+
defined in OSGi bundles. Contains `Map<Bundle, EntityManagerFactoryManager>`
223+
224+
Parsed `org.apache.aries.jpa.container.parsing.impl.PersistenceUnitImpl` is changed into
225+
`org.apache.aries.jpa.container.unit.impl.ManagedPersistenceUnitInfoImpl` and `getPersistenceUnitInfo()` is called
226+
to get `javax.persistence.spi.PersistenceUnitInfo` instance which is then finally used as argument to
227+
`javax.persistence.spi.PersistenceProvider.createContainerEntityManagerFactory()`.
228+
229+
org.apache.aries.jpa.container.context bundle:
230+
231+
* provides contextual (proxied, thread-local) access to context-related `javax.persistence.EntityManager` instance.

jdbc-blueprint/pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@
7676
<artifactId>postgresql</artifactId>
7777
</dependency>
7878

79+
<dependency>
80+
<groupId>org.apache.aries.blueprint</groupId>
81+
<artifactId>org.apache.aries.blueprint.core</artifactId>
82+
</dependency>
83+
7984
</dependencies>
8085

8186
<build>

jpa-ds/pom.xml

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2005-2017 Red Hat, Inc.
5+
6+
Red Hat licenses this file to you under the Apache License, version
7+
2.0 (the "License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15+
implied. See the License for the specific language governing
16+
permissions and limitations under the License.
17+
18+
-->
19+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
22+
<modelVersion>4.0.0</modelVersion>
23+
24+
<parent>
25+
<groupId>com.fusesource.examples</groupId>
26+
<artifactId>camel-persistence-part1</artifactId>
27+
<version>1.0</version>
28+
<relativePath>../pom.xml</relativePath>
29+
</parent>
30+
31+
<groupId>com.fusesource.examples.camel-persistence-part1</groupId>
32+
<artifactId>jpa-ds</artifactId>
33+
<packaging>bundle</packaging>
34+
<name>FuseSource :: Examples :: Camel Persistence :: JPA Data Source</name>
35+
36+
<dependencies>
37+
38+
<!-- OSGi -->
39+
40+
<dependency>
41+
<groupId>org.osgi</groupId>
42+
<artifactId>osgi.enterprise</artifactId>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.osgi</groupId>
46+
<artifactId>osgi.core</artifactId>
47+
</dependency>
48+
49+
<!-- Spring -->
50+
51+
<dependency>
52+
<groupId>org.springframework</groupId>
53+
<artifactId>spring-jdbc</artifactId>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.springframework.osgi</groupId>
57+
<artifactId>spring-osgi-core</artifactId>
58+
</dependency>
59+
<dependency>
60+
<groupId>org.springframework.osgi</groupId>
61+
<artifactId>spring-osgi-extender</artifactId>
62+
</dependency>
63+
64+
<!-- Commons -->
65+
66+
<dependency>
67+
<groupId>org.apache.commons</groupId>
68+
<artifactId>commons-dbcp2</artifactId>
69+
</dependency>
70+
71+
<!-- Database drivers -->
72+
73+
<dependency>
74+
<groupId>org.postgresql</groupId>
75+
<artifactId>postgresql</artifactId>
76+
</dependency>
77+
78+
</dependencies>
79+
80+
<build>
81+
<plugins>
82+
<plugin>
83+
<groupId>org.apache.felix</groupId>
84+
<artifactId>maven-bundle-plugin</artifactId>
85+
<extensions>true</extensions>
86+
<configuration>
87+
<instructions>
88+
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
89+
<Import-Package>
90+
*,
91+
org.postgresql
92+
</Import-Package>
93+
</instructions>
94+
</configuration>
95+
</plugin>
96+
</plugins>
97+
</build>
98+
99+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2005-2017 Red Hat, Inc.
5+
6+
Red Hat licenses this file to you under the Apache License, version
7+
2.0 (the "License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15+
implied. See the License for the specific language governing
16+
permissions and limitations under the License.
17+
18+
-->
19+
<beans xmlns="http://www.springframework.org/schema/beans"
20+
xmlns:osgi="http://www.springframework.org/schema/osgi"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="
23+
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
24+
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd">
25+
26+
<!-- PostgreSQL DB -->
27+
<bean id="reportdb" class="org.apache.commons.dbcp2.BasicDataSource">
28+
<property name="driverClassName" value="org.postgresql.Driver" />
29+
<property name="url" value="jdbc:postgresql://localhost:5432/reportdb" />
30+
<property name="username" value="fuse" />
31+
<property name="password" value="fuse" />
32+
<property name="defaultAutoCommit" value="false" />
33+
</bean>
34+
35+
<osgi:service ref="reportdb" interface="javax.sql.DataSource">
36+
<osgi:service-properties>
37+
<entry key="osgi.jndi.service.name" value="jdbc/reportdb" />
38+
</osgi:service-properties>
39+
</osgi:service>
40+
41+
</beans>

0 commit comments

Comments
 (0)