db.properties vs persistence.xml which one is better? - java

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.

Related

Passing the JNDI name dynamically

I have a lot of Websphere servers with different JNDI name of my DB connection so I have to build many ears files for each server. I'd like to do something like this:
<bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${SPECIFIC_JNDI_NAME}"/>
</bean>
How can I create this SPECIFIC_JNDI_NAME variable?
The proper Java EE way to do it, is using resource references in your code like: java:comp/env/jdbc/myDSRef, then this resource reference is bind to actual JNDI name during the installation process.
You either define references via #Resource tag, or entry in the deployment descriptor (web.xml or ejb-jar.xml).
You map it to the JNDI name via admin console, wsadmin installation script, or ibm-web-bnd.xml file placed in the WEB-INF folder.
It is possible to use references with Spring.
This is the wrong way to go about it. One advantage of JNDI is that you can bind objects (in this case a datasource) under one JNDI name without a care for where it came from, how it was instantiated, etc. as long as it was there at the time it was first accessed.
You (or whoever configures the JNDI names) are basically trying to take away that advantage by binding different datasources on different JNDI names.
A workaround could be to bind the 'custom' name to a 'standard' JNDI name such that your application can still refer to the 'standard' name and the onus for providing the right bean is on those who configure the JNDI but really, if you go that far you can also just give the datasource the standard name. Also, I'm not sure that is even possible in JNDI, I just know that it used to be possible in Spring's own configuration.

How to load properties using zookeeper as the data source for a spring based web application?

I have a web application which is initialised using spring and built using maven.
The various properties are loaded using properties files which are statically present. Since various environments require different values for the same properties, i use maven profiles to load different properties files depending upon the environment at build time.
Ex:- dev.properties for dev environment and prod.properties for production environment.
Now i want to make the build independent of the properties files,
The value of the properties will be fetched from some datasource(zookeeper) during context initialisation.
How to load the properties before the context is initialised?
Spring Cloud Config Zookeeper offers a way to do that. I posted a brief example of use here
Properties is just one of Java class and that Apache Configuration project exactly provides such an abstraction. I just showed you a sample for JDBC, but there is really many other stuff there. Here is a sample how I load properties from DB StoredProcedure:
<jee:jndi-lookup id="dataSource" jndi-name="DS"/>
<bean id="storedProcedureConfiguration" class="com.my.proj.config.StoredProcedureConfiguration"
p:dataSource-ref="dataSource"
p:sqlQuery="pki_props.getProperties"/>
<bean id="propertiesFromDB" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:staticMethod="org.apache.commons.configuration.ConfigurationConverter.getProperties"
p:arguments-ref="storedProcedureConfiguration"/>
<context:property-placeholder properties-ref="propertiesFromDB"/>
So, you can implement your own AbstractConfiguration to load Properties from Zookeeper and inject it to the <context:property-placeholder>.
In the java constructor, simply set a connection to the Zookeeper server and get the needed data using the zookeeper client methods. You can find examples here: http://zookeeper.apache.org/doc/trunk/javaExample.html
It would look like this (but you would have to elaborate this)
public YourConstructor() {
Zookeeper zk = new ZooKeeper(host,...);
zk.getData(...);
}

Working with properties files outside war with Spring

I am working on a Spring 3.0.5 web application that accesses LDAP and two databases. I have a properties with configuration information for the LDAP server and that databases, in applicationContext-security.xml and dispatcher-servlet.xml, but I would like to make it so each server can have different data properties without changing a file in the WAR. Can I somehow put a file somewhere else on the server and still access it from within my application?
Add this to your context
<context:property-placeholder location="${envfile}"/>
This will load the properties file located at ${envfile}, a variable you can set with Java's startup paramater like this
-Denvfile="file:/var/server/environment.properties"
Or maybe in Tomcat's startup script
CATALINA_OPTS=" -Denvfile=file:/var/server/environment.properties"
Values can be retrieved in your controllers using Springs Value annotation like this:
#Values("${myvalue}")
private String myValue;
Please note that these features require Spring 3.1, more information here
Good luck!
Try
<util:properties id="props" location="file:///path/to/server.properties"/>

configure Hibernate to use a renamed persistence.xml

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.

Out of container JNDI data source

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

Categories

Resources