Note: Although at first similar, this is not a duplicate of Using Spring, JPA with Hibernate to access multiple databases/datasources configured in Jboss
Dear Stackoverflow,
I had a spring-jpa with hibernate application running on jboss-4.2.1.GA and using a single database.
I now have a second spring-hibernate project bundled up in the same ear file with the project described above but it needs to use a second database. This second hibernate/spring project is set up with the database.properties and hibernate.cfg.xml files.
The two databases details are stored on jboss oracle-ds.xml file:
<datasources>
<local-tx-datasource>
<jndi-name>DefaultDS</jndi-name>
...
</local-tx-datasource>
<local-tx-datasource>
<jndi-name>SecondDS</jndi-name>
...
</local-tx-datasource>
</datasources>
My question is, in the second project, with objects for the second database and not the first one, how can I call sessionFactory for the second database whose details are stored on the oracle-ds.xml instead of using database.properties files?
I have seen an example calling
#Resource(mappedName = "java:SecondDS")
private DataSource secondDS;
...
java.sql.Connection conn = secondDS.getConnection();
If it is that easy to obtain a connection, that is only useful for prepared statements, how can I in get hold of the sessionFactory? Is there a similar approach?
All examples I have seen refer to database.properties and not the jboss ds.xml file.
Thanks in advance
There is several solution, depending on how you bind the data source to a presistance context, Spring way, JPA way or Hibernate way....
Spring
To link spring/hibernate application to JNDI data source, you will need to use JndiObjectFactoryBean
<bean id="serverDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/blah"/>
<property name="proxyInterface" value="javax.sql.DataSource"></property>
</bean>
This way you have a spring bean representing the JNDI data source. You will need to create 2 of them (one for each of you data source). They you need to inject the data source in your spring defined SessionFactory. The same can be use if you use Spring managed JPA entity manager.
JPA
If you are using JPA (session factory is hibernate not jpa...) you can also defined a jndi data source name in the corresponding persistance.xml file.
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
...
</persistence-unit>
You need to use unitName parameter when injecting the entityManager:
#PersistenceContext(unitName="sample")
Hibernate
For hibernate.cfg.xml file you can specify the JNDI data source with this property
<property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
The database.property should be removed to be sure the jndi data source is used.
These are only example, the final result will depend on how you made your plumbing.
Related
Recently I started a maven project to build an application for integrating
Spring, JPA, JSF
But in the automatically generated folder structure I can see one file named as
db.properties
and also I have one
persistence.xml
Now my question is that Database connection can be defined in either of these files, Can anybody tell me
1. Which way is better and why ?
2. Why there is db.properties file automatically generated while I already have persistence.xml ?
db.properties file is like messages.properties which is used to define key value pair. And after that we will use keys in expression language. So configurations will only be done in
persistence.xml or dataSource.xml
whichever is preferred choice but the values we will take from db.properties in the form of expression language eg.
driverClassName=com.mysql.jdbc.Driver
this is an entry in your db.properties. and you will use it in persistence.xml as follows.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}" />
I assume, from the fact that you mention JSF, that you are building a web application for deployment to an application server. I also caveat this question in that I don't know about db.properties or where it comes from.
When deploying to an application server, it is always best to configure your database connections in the container and expose them to the application via JNDI. This allows the container to manage connection pooling and credentials and keeps this information out of your WAR/EAR files. It also ensures that your WAR/EAR files are agnostic to the particular database instance, so can be deployed to a container in any environment without modification.
Therefore, I recommend against configuring your datasource in persistence.xml.
See also Difference between configuring data source in persistence.xml and in spring configuration files which is a similar question- the accepted answer there expresses the solution in more detail.
We have to rename persistence.xml to fool WebSphere 7 not to use its built-in OpenJPA.
It is pretty easy to do when you use Spring, you just instruct its entity manager factory to use another location for persistence.xml:
<property name="persistenceXmlLocation" value="META-INF/persistence-xxx.xml"/>
But now we want to use plain Hibernate/JPA without Spring, and couldn't find any way to specify the alternate persistence.xml location.
JPA2 spec doesn't say anything about it...
Any clues? Is it possible to instruct Hibernate to use a renamed persistence.xml?
======
It appears that it is NOT POSSIBLE to make Hibernate read a renamed persistence.xml file.
And not necessary in my case.
As far as I know, it's not possible to change the location of the persistence.xml file.
Also take a look at this document: Alternate JPA Providers in WebSphere Application Server, it seems like you should be able to use Hibernate as JPA provider by specifying it in the persistence.xml file, and embedding the required jars in your application.
Make sure your persistence.xml is specifying Hibernate as JPA provider:
<persistence>
<persistence-unit name="myapp">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
You should also be able to achieve this by creating a shared library and using it to configure WebSphere to use an alternative persistence provider.
Here you can find how to do it: Configuring the Java Persistence API (JPA) default persistence provider
EDIT
Given the information in the comments in this answer, it seems the problem can be solved by adding these properties in persistence.xml, as indicated in this post Websphere EntityManagerFactory creation problem:
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup" />
<property name="hibernate.transaction.factory_class"
value="org.hibernate.transaction.CMTTransactionFactory" />
This same information is also provided in the Alternate JPA Providers in WebSphere Application Server document.
the persistence.xml should exist in a META-INF directory, usually packaged alongside a jar file that contains your entity classes. What I do is I have the entity clases in a seperate project under eclipse, with a META-INF directory that contains the persistence.xml, package this a jar file, and include it in the applications project dependencies (ie. WEB-INF/lib), or, deploy it straight to the app server.
I'm using Spring and Hibernate and want to do some intergration testing with DBUnit. In my application-context.xml I currently specify a datasource via jndi-lookup which reads the jndi-name from a properties file:
<jee:jndi-lookup id="dataSource"
jndi-name="${datasource.myapp.jndi}"
cache="true"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
I'd like to swap this out to an in memory database (hsqldb, h2 etc) for integration testing by just supplying a new properties file, is this possible? Or should I just use a different application-context.xml for the integration testing?
You can either have separate application contexts for prod and test or specify a default data source for the JNDI data source that should be used if the lookup fails. Then don't have a JNDI data source configured on your integration test environment. Spring will automatically fail over to the in-memory source when the lookup fails.
This is why Spring 3.1 introduced profiles: http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
Upgrade application to 3.1 or use different configs for integrations tests.
Move the datasource bean definition to a separate config file (infrastructure-config.xml), create another version of it called test-infrastructure-config.xml in which you can define a datasource either using the jdbc:embedded-database tag
<jdbc:embedded-database type="hsql">
<!-- in case you want to populate database, list the sql script files here -->
<jdbc:script location=".."/>
<jdbc:script location=".."/>
</jdbc:embedded-database>
Once you do this you specify the main application-context.xml and test-infrastructure-config.xml for out of conatiner testing and with the infrastructure-config.xml for deployment.
Use a #Bean to define your datasource. In that method you can use conditional logic to determine the environment and either do the JNDI lookup or connect to your in-memory DB.
I have some JDO objects that I want to spring to configure with info from a property file.
But since spring isn't used to create (i.e these objects are not listed as beans in the xml. Should they, how would it look?) these objects how can I get it to configure those objects?
Only solution I can come up with is to have the property file info configured into the dao and then have the dao insert that data into the object before it returns it. Or I guess I can do some AOP magic, but that seems heavy handed and I don't think it will work in Google App Engine where this service will be deployed.
Any other advice.
You can put any bean in applicationContext.xml, and configure all of its properties there.
The properties file can be loaded via:
<context:property-placeholder location="classpath:application.properties" />
and then, on your bean definition:
<property name="propertyName" value="${valueFromPropertiesFile}" />
Then, in order to have the properly configured bean, you will have to inject it - either in the applicationContext.xml, or via #Resource / #Autowired
But if you can't let spring create, and configure your beans, then simply populate them with your properties manually - load a properties file with java.util.Properties, and fill the data needed.
I have some JDO objects that I want to spring to configure with info from a property file.
I don't get the whole idea. Are these objects persistent or not? If they are, just load them from the datastore. If not, they aren't really JDO objects as pointed out in comments. And in that case, I don't understand the point of the DAO and of the property file. Why don't you just declare them as Spring beans?
I would like to configure a DataSource using JNDI in a Java SE app. What is the best way to do this?
So far, I've come across 2 projects:
Apache Naming. The project page has a specific example for configuring a data source, but it looks like the project is super old and no longer active.
JBossNS. It looks like it's easy to configure a local-only JNDI using LocalOnlyContextFactory, but I haven't found any docs on how to actually configure a data source.
If possible, I would like to also configure the data source with a JTA transaction manager (using JOTM?).
Why are you using JNDI for this? It's not that it's a bad solution if you have a provider but there are alternatives such as dependency injection (IoC: via Spring or Guice).
The Spring JDBC data access is described here. The great thing is that you can use Spring to inject a DataSource into your code:
<bean class="com.my.Persister">
<property name="dataSource" ref="dataSource" />
</bean>
The data source can be defined using a JNDI-lookup:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource" />
In a test environment, you could inject the data source directly:
<bean id="dataSource" class="apache.db.PoolingDataSource">
<!-- config goes here -->
</bean>
These references are pretty old but may help to use jnpserver (JBoss Naming Service provider):
Working With JNDI In A J2SE Application
Standalone JNDI server using jnpserver.jar
A very easy to use solution for stand-alone JNDI is simple-jndi. It works like a charm as long as you only need it within a single JVM, since it's a library no network server.
The Simple-JNDI version, referenced by klenkes74, is not under active development any more. Because I encountered some issues with it I forked it, did some bug fixes and implemented some new features. I already used the old version not only for testing but in production too because I prefer a Service Locator pattern over Dependency Injection although the latter one is more trendy nowadays.
You can easily use Simple-JNDI to define a DataSource or a connection pool declaratively and get it bound to a JNDI Context.
Define a jndi.properties file in your classpath:
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=[absolute_or_relative_path_to_a_property_file]
The property file looks like:
type=javax.sql.DataSource
driver=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost/testdb
user=testuser
password=testing
Now you can access your DataSource from inside your code this way:
InitialContext ctxt = new InitialContext();
DataSource ds = (DataSource) ctxt.lookup("name_of_your_datasource");
For more information see https://github.com/h-thurow/Simple-JNDI