2.6. Sample Configurations
2.6.1. JDBC Data Source
Overview
If you need to access a database, the JDBC data source provides a convenient, general-purpose mechanism for connecting to a database and making SQL based queries and updates. To group multiple updates into a single transaction, you can instantiate a Spring
DataSourceTransactionManager
and create a transaction scope using the transacted()
DSL command.
Sample JDBC configuration
Example 2.2, “Data Source Transaction Manager Configuration” shows how to instantiate a JDBC transaction manager, of
DataSourceTransactionManager
type, which is required if you want to integrate a JDBC connection with Spring transactions. The JDBC transaction manager requires a reference to data source bean (created here with the ID, dataSource
).
Example 2.2. Data Source Transaction Manager Configuration
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> ... <!-- spring transaction manager --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- datasource to the database --> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:mem:camel"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> </beans>
JDBC data source transaction manager bean
In Example 2.2, “Data Source Transaction Manager Configuration”, the
txManager
bean is a local JDBC transaction manager instance, of DataSourceTransactionManager
type. There is just one property you need to provide to the JDBC transaction manager: a reference to a JDBC data source.
JDBC data source bean
In Example 2.2, “Data Source Transaction Manager Configuration”, the
dataSource
bean is an instance of a JDBC data source, of javax.sql.DataSource
type. The JDBC data source is a standard feature of the Java DataBase Connectivity (JDBC) specification and it represents a single JDBC connection, which encapsulating the information required to connect to a specific database.
In Spring, the recommended way to create a data source is to instantiate a
SimpleDriverDataSource
bean (which implements the javax.sql.DataSource
interface). The simple driver data source bean creates a new data source using a JDBC driver class (which is effectively a data source factory). The properties that you supply to the driver manager data source bean are specific to the database you want to connect to. In general, you need to supply the following properties:
- driverClass
- An instance of
java.sql.Driver
, which is the JDBC driver implemented by the database you want to connect to. Consult the third-party database documentation for the name of this driver class (some examples are given in Table 2.6, “Connection Details for Various Databases”). - url
- The JDBC URL that is used to open a connection to the database. Consult the third-party database documentation for details of the URL format (some examples are given in Table 2.6, “Connection Details for Various Databases”).For example, the URL provided to the
dataSource
bean in Example 2.2, “Data Source Transaction Manager Configuration” is in a format prescribed by the HSQLDB database. The URL,jdbc:hsqldb:mem:camel
, can be parsed as follows:- The prefix,
jdbc:hsqldb:
, is common to all HSQLDB JDBC connection URLs; - The prefix,
mem:
, signifies an in-memory (non-persistent) database; - The final identifier,
camel
, is an arbitrary name that identifies the in-memory database instance.
- username
- The username that is used to log on to the database.For example, when a new HSQLDB database instance is created, the
sa
user is created by default (with administrator privileges). - password
- The password that matches the specified username.
Standalone data sources
Spring provides a variety of data source implementations, which are suitable for standalone mode (that is, the application is not deployed inside an OSGi container). These data sources are described in Table 2.3, “Standalone Data Source Classes”.
Data Source Class | Description |
---|---|
SimpleDriverDataSource |
This data source should always be used in standalone mode. You configure this data source by providing it with details of a third-party JDBC driver class. This implementation has the following features:
|
DriverManagerDataSource | (Deprecated) Incompatible with OSGi containers. This class is superseded by the SimpleDriverDataSource . |
SingleConnectionDataSource | A data source that opens only one database connection (that is, every call to getConnection() returns a reference to the same connection instance). It follows that this data source is incompatible with multi-threading and is therefore not recommended for general use. |
J2EE data source adapters
If your application is deployed into a J2EE container, it does not make sense to create a data source directly. Instead, you should let the J2EE container take care of creating data sources and you can then access those data sources by doing a JNDI lookup. For example, the following code fragment shows how you can obtain a data source from the JNDI reference,
java:comp/env/jdbc/myds
, and then wrap the data source with a UserCredentialsDataSourceAdapter
.
<bean id="myTargetDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/myds"/> </bean> <bean id="myDataSource" class="org.springframework.jdbc.datasource.UserCredentialsDataSourceAdapter"> <property name="targetDataSource" ref="myTargetDataSource"/> <property name="username" value="myusername"/> <property name="password" value="mypassword"/> </bean>
The
JndiObjectFactoryBean
exploits the Spring bean factory pattern to look up an object in JNDI. When this bean's ID, myTargetDataSource
, is referenced elsewhere in Spring using the ref
attribute, instead of getting a reference to the JndiObjectFactoryBean
bean, you actually get a reference to the bean that was looked up in JNDI (a javax.sql.DataSource
instance).
The standard
javax.sql.DataSource
interface exposes two methods for creating connections: getConnection()
and getConnection(String username, String password)
. If (as is normally the case) the referenced database requires credentials in order to open a connection, the UserCredentialsDataSourceAdapter
class provides a convenient way of ensuring that these user credentials are available. You can use this adapter class for wrapping JNDI-provided data sources that do not have their own credentials cache.
In addition to
UserCredentialsDataSourceAdapter
, there are a number of other adapter classes that you can use to wrap data sources obtained from JNDI lookups. These J2EE data source adapters are summarized in Table 2.4, “J2EE Data Source Adapters”.
Data Source Adapter | Description |
---|---|
UserCredentialsDataSourceAdapter |
Data source wrapper class that caches username/password credentials, for cases where the wrapped data source does not have its own credentials cache. This class can be used to wrap a data source obtained by JNDI lookup (typically, in a J2EE container).
The username/password credentials are bound to a specific thread. Hence, you can store different connection credentials for different threads.
|
IsolationLevelDataSourceAdapter | Subclass of UserCredentialsDataSourceAdapter which, in addition to caching user credentials, also applies the current Spring transaction's level of isolation to all of the connections it creates. |
WebSphereDataSourceAdapter | Same functionality as IsolationLevelDataSourceAdapter , except that the implementation is customized to work with IBM-specific APIs. |
Data source proxies for special features
You can wrap a data source with a data source proxy in order to add special functionality to a data source. The data source proxies can be applied either to a standalone data source or a data source provided by the container. They are summarized in Table 2.5, “Data Source Proxies”.
Data Source Proxy | Description |
---|---|
LazyConnectionDataSourceProxy |
This proxy uses lazy semantics to avoid unnecessary database operations. That is, a connection will not actually be opened until the application code attempts to write (or read) to the database.
For example, if some application code opens a connection, begins a transaction, and then commits a transaction, but never actually accesses the database, the lazy connection proxy would optimize these database operations away.
|
TransactionAwareDataSourceProxy |
Provides support for legacy database code that is not implemented using the Spring persistence API.
Do not use this proxy for normal transaction support. The other Spring data sources are already compatible with the Spring persistence and transaction APIs. For example, if your application code uses Spring's
JdbcTemplate class to access JDBC resources, do not use this proxy class.
|
Third-party JDBC driver managers
Table 2.6, “Connection Details for Various Databases” shows the JDBC connection details for a variety of different database products.
Database | JDBC Driver Manager Properties |
---|---|
HSQLDB |
The JDBC driver class for HSQLDB is as follows:
org.hsqldb.jdbcDriver
To connect to a HSQLDB database, you can use one of the following JDBC URL formats:
jdbc:hsqldb:hsql[s]://host[:port][/DBName][KeyValuePairs] jdbc:hsqldb:http[s]://host[:port][/DBName][KeyValuePairs] jdbc:hsqldb:mem:DBName[KeyValuePairs]
Where the
hsqls and https protocols use TLS security and the mem protocol references an in-process, transient database instance (useful for testing). For more details, see http://www.hsqldb.org/doc/src/.
|
MySQL |
The JDBC driver class for MySQL is as follows:
com.mysql.jdbc.Driver
To connect to a MySQL database, use the following JDBC URL format:
jdbc:mysql://[host][,failoverhost...][:port]/[DBName][Options]
Where the Options coincidentally have the same format as Camel component options—for example,
?Option1=Value1&Option2=Value2 . For more details, see http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html.
|
Oracle |
Depending on which version of Oracle you are using choose one of the following JDBC driver classes:
oracle.jdbc.OracleDriver (Oracle 9i, 10) oracle.jdbc.driver.OracleDriver (Oracle 8i)
To connect to an Oracle database, use the following JDBC URL format:
jdbc:oracle:thin:[user/password]@[host][:port]:SID
Where the Oracle System ID (SID) identifies an Oracle database instance. For more details, see http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/basic.htm.
|
DB2 |
The JDBC driver class for DB2 is as follows:
com.ibm.db2.jcc.DB2Driver
To connect to a DB2 database, use the following JDBC URL format:
jdbc:db2://host[:port]/DBName |
SQL Server |
The JDBC driver class for SQL Server is as follows:
com.microsoft.jdbc.sqlserver.SQLServerDriver
To connect to a SQL Server database, use the following JDBC URL format:
jdbc:microsoft:sqlserver://host[:port];DatabaseName=DBName |
Sybase |
The JDBC driver class for Sybase is as follows:
com.sybase.jdbc3.jdbc.SybDriver
To connect to a Sybase database, use the following JDBC URL format:
jdbc:sybase:Tds:host:port/DBName |
Informix |
The JDBC driver class for Informix is as follows:
com.informix.jdbc.IfxDriver
To connect to an Informix database, use the following JDBC URL format:
jdbc:informix-sqli://host:port/DBName:informixserver=DBServerName |
PostgreSQL |
The JDBC driver class for PostgreSQL is as follows:
org.postgresql.Driver
To connect to a PostgreSQL database, use the following JDBC URL format:
jdbc:postgresql://host[:port]/DBName |
MaxDB |
The JDBC driver class for the SAP database is as follows:
com.sap.dbtech.jdbc.DriverSapDB
To connect to a MaxDB database, use the following JDBC URL format:
jdbc:sapdb://host[:port]/DBName |
FrontBase |
The JDBC driver class for FrontBase is as follows:
com.frontbase.jdbc.FBJDriver
To connect to a FrontBase database, use the following JDBC URL format:
jdbc:FrontBase://host[:port]/DBName |
2.6.2. Hibernate
Overview
To enable transactions while accessing Hibernate objects, you need to provide an instance of the Hibernate transaction manager, of
HibernateTransactionManager
type, as described here. You can then use the transacted()
DSL command to create a transaction scope in a route.
Sample Hibernate configuration
Example 2.3, “Hibernate Transaction Manager Configuration” shows how to instantiate a Hibernate transaction manager, of
HibernateTransactionManager
type, which is required if you want to integrate Hibernate object-oriented persistence with Spring transactions. The Hibernate transaction manager requires a reference to a Hibernate session factory, and the Hibernate session factory takes a reference to a JDBC data source.
Example 2.3. Hibernate Transaction Manager Configuration
<beans ... > ... <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="mappingResources"> <list> <value>product.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> </property> </bean> <bean id="hibernateTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="mySessionFactory"/> </bean> </beans>
Hibernate transaction manager bean
In Example 2.3, “Hibernate Transaction Manager Configuration”, the
hibernateTxManager
bean is a local Hibernate transaction manager instance, of HibernateTransactionManager
type. There is just one property you need to provide to the Hibernate transaction manager: a reference to a Hibernate session factory.
Hibernate session factory bean
In Example 2.3, “Hibernate Transaction Manager Configuration”, the
mySessionFactory
bean is a Hibernate session factory of org.springframework.orm.hibernate3.LocalSessionFactory
type. This session factory bean is needed by the Hibernate transaction manager.
In general, you need to supply the following properties to a Hibernate
LocalSessionFactory
bean instance:
- dataSource
- An instance of
javax.sql.DataSource
, which is the JDBC data source of the database that Hibernate is layered over. For details of how to configure a JDBC data source, see Section 2.6.1, “JDBC Data Source”. - mappingResources
- Specifies a list of one or more mapping association files on the class path. A Hibernate mapping association defines how Java objects map to database tables.
- hibernateProperties
- Allows you to set any Hibernate property, by supplying a list of property settings. The most commonly needed property is
hibernate.dialect
, which indicates to Hibernate what sort of database it is layered over, enabling Hibernate to optimize its interaction with the underlying database. The dialect is specified as a class name, which can have one of the following values:org.hibernate.dialect.Cache71Dialect
org.hibernate.dialect.DataDirectOracle9Dialect
org.hibernate.dialect.DB2390Dialect
org.hibernate.dialect.DB2400Dialect
org.hibernate.dialect.DB2Dialect
org.hibernate.dialect.DerbyDialect
org.hibernate.dialect.FirebirdDialect
org.hibernate.dialect.FrontBaseDialect
org.hibernate.dialect.H2Dialect
org.hibernate.dialect.HSQLDialect
org.hibernate.dialect.IngresDialect
org.hibernate.dialect.InterbaseDialect
org.hibernate.dialect.JDataStoreDialect
org.hibernate.dialect.MckoiDialect
org.hibernate.dialect.MimerSQLDialect
org.hibernate.dialect.MySQL5Dialect
org.hibernate.dialect.MySQL5InnoDBDialect
org.hibernate.dialect.MySQLDialect
org.hibernate.dialect.MySQLInnoDBDialect
org.hibernate.dialect.MySQLMyISAMDialect
org.hibernate.dialect.Oracle9Dialect
org.hibernate.dialect.OracleDialect
org.hibernate.dialect.PointbaseDialect
org.hibernate.dialect.PostgreSQLDialect
org.hibernate.dialect.ProgressDialect
org.hibernate.dialect.RDMSOS2200Dialect
org.hibernate.dialect.SAPDBDialect
org.hibernate.dialect.SQLServerDialect
org.hibernate.dialect.Sybase11Dialect
org.hibernate.dialect.SybaseAnywhereDialect
org.hibernate.dialect.SybaseDialect
org.hibernate.dialect.TimesTenDialect
2.6.3. JPA
Overview
To enable transactions in a JPA component, you need to provide the JPA component with a reference to a transaction manager, of
JpaTransactionManager
type. The Java Persistence API is a generic wrapper API for object-relational persistence and it can be layered over a variety of different object-relational mapping technologies.
Sample JPA configuration
Example 2.4, “JPA Transaction Manager Configuration” shows how to customize the configuration of a JPA component (creating a component with the bean ID, jpa), so that the JPA component supports Spring transactions. When used with transactions, the JPA component requires a reference to an entity manager factory and a reference to a transaction manager.
Example 2.4. JPA Transaction Manager Configuration
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="transactionManager" ref="jpaTxManager"/> </bean> <bean id="jpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="camel"/> </bean> </beans>
JPA transaction manager bean
In Example 2.4, “JPA Transaction Manager Configuration”, the
jpaTxManager
bean is a local JPA transaction manager instance, of JpaTransactionManager
type. The JPA transaction manager requires a reference to an entity manager factory bean (in this example, the entityManagerFactory
bean).
If you deploy your application into an OSGi container, however, you might want to consider using a
JtaTransactionManager
instead. See Table 2.2, “Global Transaction Managers”.
Entity manager factory bean
The entity manager factory bean encapsulates the JPA runtime functionality. For example, the Spring
LocalEntityManagerFactoryBean
class is just a wrapper around the standard javax.persistence.EntityManagerFactory
class. The entity manager factory is used to create a javax.persistence.EntityManager
instance, where the entity manager is associated with a unique persistence context. A persistence context represents a consistent set of entity objects that are instantiated from the underlying database (analogous to a Hibernate session).
The
LocalEntityManagerFactoryBean
class is a relatively simple JPA wrapper class that is suitable for simple demonstrations and testing purposes. This class reads its required configuration information from the persistence.xml
file, which is found at the standard location, META-INF/persistence.xml
, on the class path (see the section called “Sample persistence.xml file”). The persistenceUnitName
property references a section of the persistence.xml
file.
JPA entity manager factories
As well as instantiating a
LocalEntityManagerFactoryBean
bean, there are other ways of obtaining a JPA entity manager factory, as summarized in Table 2.7, “Obtaining JPA Entity Manager Factory”.
Entity Manager Factory | Description |
---|---|
Obtain from JNDI | If your application is deployed in a J2EE container, the recommended approach is to let the container take care of instantiating the entity manager factory. You can then obtain a reference to the entity manager factory using JNDI. See Obtaining an EntityManagerFactory from JNDI in the Spring documentation. |
LocalEntityManagerFactoryBean | For simple standalone applications and for testing, the simplest option is to create a bean of this type. The JPA runtime is configured using the standard META-INF/persistence.xml file. |
LocalContainerEntityManagerFactoryBean | Use this class, if you need to configure special bootstrap options for the JPA runtime. In spite of the name, this class is not restricted to containers; you can also use it in standalone mode. See LocalContainerEntityManagerFactoryBean in the Spring documentation. |
JPA bootstrap contract
The JPA is a thin abstraction layer that allows you to write code that is independent of a particular object-relational mapping product—for example, it enables you to layer your application over products such as OpenJPA, Hibernate, or TopLink. To match the application code to a specific JPA implementation, JPA defines a bootstrap contract, which is a procedure to locate and configure JPA implementations, as follows:
- To make a JPA implementation available to your application, put the JAR file containing the relevant JPA provider class (of
javax.persistence.spi.PersistenceProvider
type) on your class path. In fact, it is possible to add multiple JPA providers to your class path: you can optionally specify which JPA provider to use in thepersistence.xml
file. - The JPA persistence layer is configured by the standard
persistence.xml
file, which is normally located inMETA-INF/persistence.xml
on the class path.
Sample persistence.xml file
Example 2.5, “Sample persistence.xml File” shows a sample
persistence.xml
file for configuring an OpenJPA JPA provider layered over a Derby database.
Example 2.5. Sample persistence.xml File
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="camel" transaction-type="RESOURCE_LOCAL"> <!-- The default provider can be OpenJPA, or some other product. This element is optional if OpenJPA is the only JPA provider in the current classloading environment, but can be specified in cases where there are multiple JPA implementations available. --> <provider> 1 org.apache.openjpa.persistence.PersistenceProviderImpl </provider> <class>org.apache.camel.examples.MultiSteps</class> 2 <class>org.apache.camel.examples.SendEmail</class> <properties> 3 <property name="openjpa.ConnectionURL" value="jdbc:derby:target/derby;create=true"/> <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.EmbeddedDriver"/> <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/> <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO, SQL=TRACE"/> </properties> </persistence-unit> </persistence>
- 1
- The
provider
element can be used to specify the OpenJPA provider implementation class. If theprovider
element is omitted, the JPA layer simply uses the first JPA provider it can find. Hence, it is recommended to specify theprovider
element, if there are multiple JPA providers on your class path.To make a JPA provider available to an application, simply add the provider's JAR file to the class path and the JPA layer will auto-detect the JPA provider. - 2
- Use the
class
elements to list all of the Java types that you want to persist using the JPA framework. - 3
- Use the
properties
element to configure the underlying JPA provider. In particular, you should at least provide enough information here to configure the connection to the underlying database.
Sample annotated class
The following code example shows how the
org.apache.camel.examples.SendEmail
class referenced in Example 2.5, “Sample persistence.xml File” should be annotated to turn it into a persistent entity bean (so that it is persistible by JPA):
// Java package org.apache.camel.examples; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** * Represents a task which is added to the database, then removed from the database when it is consumed * * @version $Revision$ */ @Entity public class SendEmail { private Long id; private String address; public SendEmail() { } public SendEmail(String address) { setAddress(address); } @Override public String toString() { return "SendEmail[id: " + getId() + " address: " + getAddress() + "]"; } @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
The preceding class has the following JPA annotations:
-
@javax.persistence.Entity
- Specifies that the following class is persistible by the JPA.
-
@javax.persistence.Id
- The following bean property must be used as the primary key (for locating objects of this type in the database).
-
@javax.persistence.GeneratedValue
- Specifies that the primary key values should be automatically generated by the JPA runtime (you can optionally set attributes on this annotation to configure the ID generation algorithm as well).
For the complete list of JPA annotations, see the API for the
javax.persistence
package.