| Title: Aries Transaction Control JPA Provider (Local) |
| Notice: Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| . |
| http://www.apache.org/licenses/LICENSE-2.0 |
| . |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| #Aries Transaction Control JPA Provider (Local) |
| |
| The Aries Local JPA provider implementation is available at the following maven coordinates: |
| |
| <dependency> |
| <groupId>org.apache.aries.tx-control</groupId> |
| <artifactId>tx-control-provider-jpa-local</artifactId> |
| <version>${aries.tx.control.version}</version> |
| </dependency> |
| |
| This module is a prototype implementation of the OSGi Transaction Control JPA resource provider |
| using Local transactions. It supports JPA 2.1, and is tested against Hibernate 5.0.9 and EclipseLink 2.6.0. |
| It also supports JPA 2.0, and is tested against OpenJPA 2.4.1. |
| |
| ##Quick Start |
| |
| A configured <code>JPAEntityManagerProvider</code> can be created quickly using Configuration Admin, |
| the OSGi JPA Service, and the OSGi JDBC Service. |
| |
| 1. Package the persistence unit in a persistence bundle |
| 1. Find and install a JPA provider (for example Hibernate) |
| 1. Find and install a JDBC Service implementation for your chosen database (e.g. the org.h2 bundle for H2) |
| 1. Install a JPA service extender, such as the Apache Aries JPA container |
| 1. Create a factory configuration using the factory pid <code>org.apache.aries.tx.control.jpa.local</code> |
| and add the following properties: |
| * *osgi.jdbc.driver.class* :- The driver class name for your database(e.g. org.h2.Driver) |
| * *url* :- The JDBC URL to use to connect to the database |
| * *osgi.unit.name* :- The name of the persistence unit |
| |
| When the DataSourceFactory for the named <code>osgi.jdbc.driver.class</code> and the |
| <code>EntityManagerFactoryBuilder</code> for the named <code>osgi.unit.name</code> become |
| available the Local JPA Resource Provider will create a JPAEntityManagerProvider and register it in the OSGi |
| service registry. All configuration properties (apart from the database password) will be registered as |
| properties of the JPAEntityManagerProvider service. These properties can be used to select a |
| ResourceProvider if more than one is present in the Service Registry. |
| |
| ## When should I use this module? |
| |
| If you wish to use entirely lightweight, resource-local transactions then it is best to pair this module |
| with the <code>tx-control-service-local</code> bundle. |
| |
| If two-phase commit is needed across multiple resources then the <code>tx-control-service-xa</code> and |
| <code>tx-control-provider-jpa-xa</code> bundles should be used. |
| |
| # Using the JPA Provider bundle |
| |
| This Resource Provider is used in conjunction with a TransactionControl service to provide scoped |
| access to a JPA EntityManager. |
| |
| ## Prerequisites |
| |
| In order to use scoped JPA access the runtime must contain a JPA provider (for example Hibernate), |
| an implementation of the OSGi JPA service (e.g. Aries JPA), and a persistence bundle. |
| |
| ### Suitable Persistence bundles |
| |
| OSGi Persistence bundles contain the persistence descriptor (typically an XML file called |
| META-INF/persistence.xml), all of the JPA Entities, and a Meta-Persistence header |
| pointing at the persistence descriptor. (See the JPA service specification for more details). |
| |
| Unlike "normal" JPA it is usually best not to fully declare the persistence unit in the persistence descriptor. |
| In particular it is a good idea to avoid putting any database configuration in the persistence unit. |
| By not configuring the database inside the bundle the persistence unit remains decoupled, |
| and can be reconfigured for any database at runtime. |
| |
| For example the following persistence unit: |
| |
| <persistence-unit name="test-unit"/> |
| |
| can be reconfigured to use any database and to create/drop tables as appropriate. Configuration |
| for the persistence unit can be provided using Configuration Admin and the EntityManagerFactoryBuilder. |
| |
| |
| ## Creating a resource programmatically |
| |
| Preparing a resource for use is very simple. Create a JPAEntityManagerProvider using the the |
| JPAEntityManagerProviderFactory, then connect the provider to a TransactionControl service. |
| This will return a thread-safe JPA EntityManager that can then be used in any ongoing scoped work. |
| |
| The normal inputs to a JPAEntityManagerProviderFactory are an EntityManagerFactoryBuilder, |
| some JPA properties to connect to the database with, and some properties to control the resource provider. |
| |
| ### Declarative Services Example |
| |
| @Component |
| public class TransactionalJPAComponent { |
| @Reference |
| TransactionControl txControl; |
| |
| @Reference |
| DataSourceFactory dsf; |
| |
| @Reference |
| EntityManagerFactoryBuilder emfb; |
| |
| @Reference |
| JPAEntityManagerProviderFactory providerFactory; |
| |
| EntityManager em; |
| |
| @Activate |
| void start(Config config) { |
| |
| Properties jdbcProps = new Properties(); |
| jdbcProps.put(JDBC_URL, config.url()); |
| jdbcProps.put(JDBC_USER, config.user()); |
| jdbcProps.put(JDBC_PASSWORD, config._password()); |
| |
| Map<String, Object> jpaProps = new HashMap<>(); |
| jpaProps.put("javax.persistence.nonJtaDataSource", |
| dsf.createDataSource(jdbcProps)); |
| |
| em = providerFactory.getProviderFor(emfb, jpaProps, |
| null).getResource(txControl); |
| } |
| |
| public void findUserName(String id) { |
| txControl.required(() -> { |
| // Use the EntityManager in here |
| }); |
| } |
| } |
| |
| If the JPA EntityManagerFactory is already configured then it can be passed into the |
| JPAEntityManagerProviderFactory instead of an EntityManagerFactoryBuilder and JPA configuration. |
| |
| |
| ## Creating a resource using a factory configuration |
| |
| Whilst it is simple to use a EntityManagerFactoryBuilder it does require some lifecycle code to be written. |
| It is therefore possible to directly create JPA resources using factory configurations. When created, |
| the factory service will listen for an applicable EntityManagerFactoryBuilder and potentially also a |
| DataSourceFactory. Once suitable services are available then a JPAEntityManagerProvider service |
| will be published. |
| |
| Configuration properties (except the JPA/JDBC password) are set as service properties for the registered |
| JPAEntityManagerProvider. These properties may therefore be used in filters to select a particular provider. |
| |
| @Component |
| public class TransactionalJDBCComponent { |
| @Reference |
| TransactionControl control; |
| |
| EntityManager em; |
| |
| @Reference(target="(osgi.unit.name=test-unit)") |
| void setProvider(JPAEntityManagerProvider provider) { |
| em = provider.getResource(control); |
| } |
| |
| public void findUserName(String id) { |
| txControl.required(() -> { |
| // Use the connection in here |
| }); |
| } |
| } |
| |
| |
| The factory pid is _org.apache.aries.tx.control.jpa.local_ and it may use the following properties |
| (all optional aside from *osgi.unit.name*): |
| |
| ### Resource Provider properties |
| |
| * *osgi.unit.name* : The name of the persistence unit that this configuration relates to. |
| |
| * *aries.emf.builder.target.filter* : The target filter to use when searching for an EntityManagerFactoryBuilder. If not specified then any builder for the named persistence unit will be used. |
| |
| * *aries.jpa.property.names* : The names of the properties to pass to the EntityManagerFactoryBuilder when creating the EntityManagerFactory. By default all properties are copied. |
| |
| * *aries.dsf.target.filter* : The target filter to use when searching for a DataSourceFactory. If not specified then *osgi.jdbc.driver.class* must be specified. |
| |
| * *aries.jdbc.property.names* : The names of the properties to pass to the DataSourceFactory when creating the JDBC resources. |
| |
| * *osgi.jdbc.driver.class* : Used to locate the DataSourceFactory service if the *aries.dsf.target.filter* is not set. |
| |
| * *osgi.local.enabled* : Defaults to true. If false then resource creation will fail |
| |
| * *osgi.xa.enabled* : Defaults to false. If true then resource creation will fail |
| |
| * *osgi.connection.pooling.enabled* : Defaults to true. If true then the Database connections will be pooled. |
| |
| * *osgi.connection.max* : Defaults to 10. The maximum number of connections that should be kept in the pool |
| |
| * *osgi.connection.min* : Defaults to 10. The minimum number of connections that should be kept in the pool |
| |
| * *osgi.connection.timeout* : Defaults to 30,000 (30 seconds). The maximum time in milliseconds to block when waiting for a database connection |
| |
| * *osgi.idle.timeout* : Defaults to 180,000 (3 minutes). The time in milliseconds before an idle connection is eligible to be closed. |
| |
| * *osgi.connection.timeout* : Defaults to 10,800,000 (3 hours). The maximum time in milliseconds that a connection may remain open before being closed. |
| |
| * *osgi.use.driver* : Defaults to false. If true then use the createDriver method to connect to the database. |
| |
| |
| ### JDBC properties |
| |
| The following properties will automatically be passed to the DataSourceFactory if they are present. The list of properties may be overridden using the *aries.jdbc.property.names* property if necessary. |
| |
| * *databaseName* : The name of the database |
| |
| * *dataSourceName* : The name of the dataSource that will be created |
| |
| * *description* : A description of the dataSource being created |
| |
| * *networkProtocol* : The network protocol to use. |
| |
| * *portNumber* : The port number to use |
| |
| * *roleName* : The name of the JDBC role |
| |
| * *serverName* : The name of the database server |
| |
| * *url* : The JDBC url to use (often used instead of other properties such as *serverName*, *portNumber* and *databaseName*). |
| |
| * *user* : The JDBC user |
| |
| * *password* : The JDBC password |
| |
| |
| ### JPA properties |
| |
| The following properties are potentially useful when configuring JPA: |
| |
| *javax.persistence.schema-generation.database.action* : May be used to automatically create the database tables (see the OSGi spec) |
| |
| * Other provider specific properties, for example configuring second-level caching. |
| |
| |
| [1]: https://github.com/osgi/design/blob/master/rfcs/rfc0221/rfc-0221-TransactionControl.pdf |