Package a runnable JPA jar putting persistence.xml outside - java

I want to export my jpa/swing project to a runnable jar. But I want the persistence.xml to be outside the jar not packaged inside, so I can change it without the need to export the jar again after each config.

According to JPA specifications, persistence.xml file cannot be detected outside the JAR file where the persistence unit is defined. By convention, it should be placed inside META-INF directory.
Read JSR-317, paragraph 8.2.1 for more details (http://download.oracle.com/otndocs/jcp/persistence-2.0-fr-eval-oth-JSpec/).
Nevertheless, you can try the hint proposed by this guy here and deploy your archives in exploded form.

I had the same problem, but I only needed to change Server, database, user and password. So this did it for me:
In JBoss AS, you can even have the property value as a placeholder, for example:
<property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://${DbServer}:1234;databaseName=${DbName}" />
<property name="javax.persistence.jdbc.user" value="${DbUser}" />
<property name="javax.persistence.jdbc.password" value="${DbPassword}" />
and then pass the "DbServer", "DbName", "DbUser" and "DbPassword" value as a Java system property:
-DDbServer=sql99 -DDbName=db_Name -DDbUser=USER -DDbPassword=pw
In Eclipse:

Related

Hibernate Config in Properties outside of the WAR without Spring

I have this structure in my Jboss 6.4, and I need to access outside of the war to another folder to take the configuration for Hibernate:
/usr/webapps/MYAPP/deployments/MYAPP.war
/usr/webapps/MYAPP/appconfig/hibernate.properties
I have to use this pattern, and I'm using Hibernate 4.2, in my case I need to take the content of the properties file to use it in my hibernate.cfg.xml like here:
<property name="connection.driver_class">${db.driver}</property>
<property name="hibernate.dialect">${db.dialect}</property>
<property name="hibernate.connection.url">${db.url}</property>
<property name="hibernate.connection.username">${db.username}</property>
<property name="hibernate.connection.password">${db.password}</property>
hibernate.properties:
db.username=usernameTest
db.password=passwordTest
db.driver=driverTest
db.url=urlTest
db.dialect=dialectTest
What should be the best practice to do this, I was watching some cases with Spring here, but in my case it's only with JEE

org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider provider class was not found

Below is the c3p0 configuration m using.
<property name="hibernate.c3p0.timeout">500</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="c3p0.min_size">20</property>
<property name="c3p0.max_size">100</property>
<property name="testConnectionOnCheckin">true</property>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property>
<property name="hibernate.c3p0.unreturnedConnectionTimeout">60</property>
I checked in my log and found
"c3p0 properties were encountered, but the org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider provider class was not found on the classpath; these properties are going to be ignored."
I used 2 lib. c3p0-0.9.1.jar & hibernate-c3p0-4.1.4.final-sources.jar
Please Help...
org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider provider class was not found on the classpath
Because you using hibernate-c3p0-4.1.4.final-sources.jar and this jar only contains Java source-code (.java) files not the compiled Java code (.class). So even If you are expecting "C3P0ConnectionProvider" class is in your classpath, but in reality it is not.
Solution
Use "hibernate-c3p0-4.1.10.Final.jar". This jar contains C3P0ConnectionProvider.class file.
Hopefully this will resolve your issue.

No Persistence Provider for EntityManager named foo

Yes I've already searched here for this question but I have this problem after the researches.
So, I'm making a simple standalone project, containing only Entities and DAOs.
I'm using IntelliJ.
EDIT: My DB connection informations are good, I'm sure. And I've got another project (GWT) and I'm using the same method -> it works
My META-INF folder is in the root src folder, so this is my persistence.xml:
`<persistence-unit name="jpa">
<!--<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>-->
<class>ejbpersistance.entities.User</class>
<class>ejbpersistance.entities.Comment</class>
<class>ejbpersistance.entities.Article</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/ejb"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>`
and this is my code:
public EntityManagerFactory getEntityManagerFactory() {
if(emf == null)
emf = Persistence.createEntityManagerFactory("jpa");
return emf;
}
I tried with Hibernate provider, Eclipse provider but always this problem.
Can someone help me ? And if I missed something in another topic concerning this issue, I apologize for the time loss.
The location of the persistence unit is the issue here.
check if persistence.xml is in your classpath:
If it is non-Java EE application(j2SE)
The jar file or directory whose META-INF directory contains the persistence.xml
file is termed the root of the persistence unit.please check classpath location in your IDE, Eclipse: Project Properties -> Java Build Path -> ****.
check if hibernate provider is in your classpath
once you can try to uncomment the provider line in your P.xml file
org.eclipse.persistence.jpa.PersistenceProvider</provider>-->
Thanks
Make sure persistence.xml is in the META-INF directory and the class path includes the META-INF parent directory.
You also didn't show the complete persistence.xml. The surrounding <persistence> tag must include the proper namespace, e.g.
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence">
...
</persistence>

Elegant ways to separate configuration from WAR in Tomcat

I am trying to find the best way to pass complex configurations in a Spring webapp running in Tomcat. Currently I use JNDI to pass data sources and strings from the Tomcat context into the webapp, and this works well.
But, lets say I need to select the implementation of a notification service. There is no way that Spring can conditionally select which bean to instantiate (although in the past I have used a JNDI string to import a predefined configuration of beans by setting contextConfigLocation).
I've also seen many webapps which supply a configuration tool which will create a custom WAR file. In my opinion this is bad form, if for no other reason than it prevents the redeployment of WARs from upstream without many checks to ensure all the configuration has been re-applied.
Ideally I would be able to supply a Spring XML file which existed on the filesystem, outside of the webapp. But, the spring import directive does not seem to resolve ${} variables, making it impossible to supply customisations.
Are there any techniques I can employ here to properly separate complex configuration from the webapp?
If I have a specific set of beans that I'd like to configure, and this configuration must be separated from the WAR file, I usually do the following:
In applicationContext.xml:
<!-- here you have a configurer based on a *.properties file -->
<bean id="configurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file://${configDir}/configuration.properties"/>
<property name="ignoreResourceNotFound" value="false" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="searchSystemEnvironment" value="false" />
</bean>
<!-- this is how you can use configuration properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${smtp.host}"/>
</bean>
In configuration.properties:
smtp.host=smtp.your-isp.com
You also need to start Tomcat with -DconfigDir=/path/to/configuration/directory
If you are using Spring 3, you can take advantage of the Spring Expression Language. Let's say you have two applications app1.war and app2.war and they require a properties file named config.properties. The applications will be deployed with context paths /app1 and /app2.
Create two directories app1 and app2 in a common directory, eg. C:\myConfig\app1 and C:\myConfig\app2.
Put config.properties inside app1 and another config.properties inside app2.
Then create a file ${CATALINA_HOME}/conf/[enginename]/[hostname]/context.xml.default with the contents:
context.xml.default:
<Context>
<Parameter name="myConfigDirectory" value="C:/myConfig" override="false"/>
</Context>
The parameter myConfigDirectory will be available to all the applications on the host. It is better to create this parameter in context.xml.default rather than in server.xml, because the file can be changed later without restarting tomcat.
In the applicationContext.xml inside war you can access config.properties using the SpEL expression: "#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties", so for example you can write:
applicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties" />
</bean>
The expression will get expanded to C:/myConfig/app1 for application with contextPath /app1, and C:/myConfig/app2 for application with contextPath /app2. This will make the applications access the config.properties file based on their contextPath.
If you want to be fully portable between web containers you cannot rely on anything outside your WAR-file. In Tomcat the SecurityManager allows you to discover the physical location on disk where your code is deployed, and you can then use that knowledge to navigate the disk to a location where your configuration file is placed.
See e.g. Determine location of a java class loaded by Matlab

Ant: Referencing dynamic properties

I want to use the same ant script to do a build in either my local windows environment or on our redhat build server.
I have a variable 'buildDirectory' in two files (build_unix.properties & build_windows). I want to set variables depending on the environment.
<osfamily property="os.family"/>
<property file="./build_${os.family}.properties" />
<property name="tmp-base.folder" value="${buildDirectory}/tmp/"/>
I also tried
<if>
<os family="unix"/>
<then>
<property file="./build_unix.properties" />
</then>
<else>
<property file="./build_windows.properties" />
</else>
</if>
Any ideas?
Are you asking how you can automatically set the os.family property in the first place?
If so, here's one approach:
<available file="C:\\" property="os.family" value="windows" />
<available file="/usr/bin/" property="os.family" value="unix" />
Ah! Edited question makes it more clear what you are asking (not this), and I see that you're using the "osfamily" task from ant-contrib to determine the OS family. But I'll leave this answer up for anyone who is just using ant without ant-contrib.
I would expect your if...then...else version to work. As it apparently isn't I would add some extra echo's to make sure your build is doing what you think it is doing.
An echo inside the then and the else would let you know for certain what path is being executed.
Add a prefix to the properties (e.g. <property file="..." prefix="test" />) and then add an <echoproperties prefix="test" /> to ensure the properties you think are being loaded are.
you can have two files : build-unix.properties and build-windows.properites and in your init target, you simply do a copy:
<copy file="build-${os.family}.properties" tofile="build.properties">
your main build.xml could simply reference the build.properties file.
This could be quite tricky to make it work properly so what I would do is to keep all properties of the build server in the build.properties file and allow local override (for your Windows box) in a build-local.properties. You can also move properties to a build-common.properties so that your build file would include the properties files in the following order
<property file="build-local.properties"/>
<property file="build-common.properties"/>
<property file="build.properties"/>

Categories