Reference a jar file in the persistence.xml within a Spring Boot project [duplicate] - jpa

persistence.xml looks like this:
<persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>jdbc/test</non-jta-data-source>
<jar-file>../../lib/app-services-1.0.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
It is a web project, so the deployment unit is a war file.
The jar file I tried to refer is in WEB-INF/lib/ folder , persistence.xml is in WEB-INF/classes/META-INF folder. When being deployed, it simply tells me
"WARNING: Unable to find file (ignored): file:.../../lib/app-services-1.0.jar".
I also tried every possible path I could think of, i.e. ../lib/app-services-1.0.jar, lib/app-services-1.0.jar.
What is the right path to do this?

Taking a look at jsr always works!
8.2.1.6.3 Jar Files
One or more JAR files may be specified using the jar-file elements instead of, or in addition to the mapping files specified in the mapping-file elements. If specified, these JAR files will >be searched for managed persistence classes, and any mapping metadata annotations found on them will be pro-cessed, or they will be mapped using the mapping annotation defaults defined by this specification.
Such JAR files are specified relative to the directory or jar file that contains the root of the persis-tence unit.
The following examples illustrate the use of the jar-file element to reference additional persistence classes. These examples use the convention that a jar file with a name terminating in “PUnit” contains the persistence.xml file and that a jar file with a name terminating in “Entities” contains additional persistence classes.
Example 1:
app.ear
lib/earEntities.jar
earRootPUnit.jar (with META-INF/persistence.xml )
persistence.xml contains:
<jar-file>lib/earEntities.jar</jar-file>
Example 2:
app.ear
lib/earEntities.jar
lib/earLibPUnit.jar (with META-INF/persistence.xml )
persistence.xml contains:
<jar-file>earEntities.jar</jar-file>
Example 3:
app.ear
lib/earEntities.jar
ejbjar.jar (with META-INF/persistence.xml )
persistence.xml contains:
<jar-file>lib/earEntities.jar</jar-file>
Example 4:
app.ear
war1.war
WEB-INF/lib/warEntities.jar
WEB-INF/lib/warPUnit.jar (with META-INF/persistence.xml )
persistence.xml contains:
<jar-file>warEntities.jar</jar-file>
Example 5:
app.ear
war2.war
WEB-INF/lib/warEntities.jar
WEB-INF/classes/META-INF/persistence.xml
persistence.xml contains:
<jar-file>lib/warEntities.jar</jar-file>
Example 6:
app.ear
lib/earEntities.jar
war2.war
WEB-INF/classes/META-INF/persistence.xml
persistence.xml contains:
<jar-file>../../lib/earEntities.jar</jar-file>
Example 7:
app.ear
lib/earEntities.jar
war1.war
WEB-INF/lib/warPUnit.jar (with META-INF/persistence.xml )
persistence.xml contains:
<jar-file>../../../lib/earEntities.jar</jar-file>
As you see there is no example for war files, all war files in the examples above are inside ear files!
But I tested in war files and it works just when I specify the absolute path of jar files and it is not a good approach for production environment!

just in case someone else stumbles upon this: the jar-file-statement is only valid. when the persistence-unit is deployed as part of an Enterprise Archives (.ear) - in every other case (.war), the persistence.xml must reside in /META-INF/ and cannot refrence classes that live outside the persistence-unit (see: http://javahowto.blogspot.com/2007/06/where-to-put-persistencexml-in-web-app.html). So, as far as I know, there is no way to have a persistence.xml living in WEB-INF/classes/META-INF that references classes that do not live in WEB-INF/classes.

war2.war
WEB-INF/lib/warEntities.jar
WEB-INF/classes/META-INF/persistence.xml
persistence.xml contains:
<jar-file>lib/warEntities.jar</jar-file>
this format works for war file. Im using Wildlfy 8.2.0 and JPA 2.1

Not sure this is related to the fact that you are deploying as a WAR, but the path should be simply "app-sevices-1.0.jar" and the jar should be in the lib of the Java EE application. The thing is: I'm not sure if this is available for the simplified "war" Java EE application. I suspect this is available only for the traditional Java EE deployment file (ear). I would test making an EAR, containing a WAR for the webapp, JAR for the PU and your other JAR for app-services, like a traditional Java EE deployment would be.
Another thing to note is that relative paths are not supported, and usage of this in SE environment is not supported by all vendors.

Related

How do I get an EAR to read a properties file from a WAR?

I'm using Wildfly 11 and Java 8. I'm trying to deploy an EAR file that contains multiple WAR files. One of my WAR files contains this in its web.xml ...
<context-param>
<param-name>Owasp.CsrfGuard.Config</param-name>
<param-value>csrfguard.properties</param-value>
</context-param>
The file in question is within one of my WARs at
myapp.war/WEB-INF/classes/csrfguard.properties
When I deploy the WAR by itself, everything deploys fine. However when I deploy the EAR containing the WAR I get an error complaining about not being able to locate the properties file ...
Caused by: java.io.IOException: unable to locate resource - csrfguard.properties
at org.owasp.csrfguard.CsrfGuardServletContextListener.getResourceStream(CsrfGuardServletContextListener.java:85)
at org.owasp.csrfguard.CsrfGuardServletContextListener.contextInitialized(CsrfGuardServletContextListener.java:36)
... 10 more
I sense that there is a class loader issue happening that I'm not figuring out how to work-around. How do I tell my EAR file where to find the properties file in question?
I suspect that the wrong class loader is being used to search the classpath for csrfguard.properties, which would cause getResourceAsStream to fail. In the .ear file, where does the CSRFGuard library get packaged?
You can try using the context.getRealPath fallback by switching to a path relative to the .war file:
<context-param>
<param-name>Owasp.CsrfGuard.Config</param-name>
<param-value>WEB-INF/classes/csrfguard.properties</param-value>
</context-param>
I had the same problem. Fixed it by adding the csrfguard.jar inside the WEB-INF/lib directory of the WAR file and not the lib directory of the EAR. Added the csrfguard.properties file to WEB-INF/classes directory and used the following context param in the web.xml
<context-param>
<param-name>Owasp.CsrfGuard.Config</param-name>
<param-value>csrfguard.properties</param-value>
</context-param>

Glassfish v3: Web application not finding JAR in the same EAR

I created a EAR application in Eclipse to run in Glassfish 3.1. The used projects are: BibliotecaEAR2 (the main EAR. 'Biblioteca' means 'Library'), BibliotecaEJB (with EJBs), BibliotecaModel (with entities and DAOs) and BibliotecaWeb (The Web application). The application.xml has this structure:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>BibliotecaEAR2</display-name>
<module>
<web>
<web-uri>BibliotecaWeb.war</web-uri>
<context-root>biblioteca</context-root>
</web>
</module>
<module>
<ejb>BibliotecaEJB.jar</ejb>
</module>
</application>
In BibliotecaWeb, the META-INF/MANIFEST.MF is written this:
Manifest-Version: 1.0
Class-Path: lib/google/guava-18.0.jar
// other JARs in BibliotecaEAR2 project
BibliotecaEJB.jar
When I start the glassfish I get this warning message:
2014-10-20T14:34:31.691-0200|WARNING: PWC6351: In TLD scanning, the supplied resource file:/C:/dev/glassfish3/glassfish/domains/biblioteca-glass3/eclipseApps/BibliotecaEAR2/BibliotecaEJB.jar does not exist
java.io.FileNotFoundException: C:\dev\glassfish3\glassfish\domains\biblioteca-glass3\eclipseApps\BibliotecaEAR2\BibliotecaEJB.jar (O sistema nao pode encontrar o arquivo especificado)
Although it does not stop me from running the application, I would like to eliminate it.
Googling for PWC6351 warning, I perceived that it happens when a used JAR is not found in the Manifest File. However the request JAR is not simply a external library, but a sub-project in same EAR. Is there any additional configuration that should I do?
Thanks,
Rafael Afonso
From Packaging libraries with EARs:
When packaging applications in an EAR file, the library JARs need to
be placed in the archive lib directory (jars at the archive root level
are not added to the classpath and thus available from other EAR
artifacts.)
The library jars placed in the "/lib" directory of the EAR (the
directory name can be overridden in application.xml) will be visible
to all sub-modules (JARs, WARs, and RARs) with no further
configuration. No need to add Class-Path entries in the EAR manifest.
In fact you don't need to reference the jars in the lib folder, and it looks like it will not work if you reference a jar on the EAR root level, like your BibliotecaEJB.jar.
If you don't have a real dependency from your WAR module classes to your EJB module classes you can just remove all the entries from the MANIFEST.MF and it should work.
If you instead have a real dependency from WAR to EJB, you may have to think about your project structure and if you really need an EAR. You can also package all the stuff into a single WAR.
The right way to use an EAR with WAR and EJB modules requires a little bit of work if your current WAR classes directly depend on classes from the EJB module:
1. Step
You have to create interfaces for all your "service" classes which should be available to classes in the web application (WAR).
Here is a simple example:
public interface FileService {
public void showFileInformation(File file);
}
and
#Stateless
#Local(FileService.class)
#Remote(FileService.class)
public class FileServiceImpl implements FileService {
#Override
public void showFileInformation(File file) {
// here
// is
// the
// real
// stuff
}
}
2. Step
The next step is to package all your new interfaces into a new jar. Your model jar looks similar to this approach. If this can't be used for this purpose, create a simple java application project which gets packaged as jar and put all the interfaces into this project. This jar has to be in the lib folder of the EAR.
BibliotecaEAR2
-- BibliotecaEJB
-- BibliotecaWeb
-- /lib/interfaces.jar
Then you have to add a dependency to this new jar in your WAR and EJB modules, so that they can find the interface classes.
3. Step
The services can be injected into the managed classes of your web applications (and into other service classes) like this:
#RequestScoped
public class FileHandler {
// make sure to use the interface
#EJB
FileService fileService;
}
Maybe you already have something similar to this, but then it should work without any entries in the MANIFEST.MF.
See also:
Maven2: Best practice for Enterprise Project (EAR file)
Java EE - EAR vs separate EJB+WAR
Packaging EJB in JavaEE 6 WAR vs EAR
I had a similar issue and solved by customizing module location, like this
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>BibliotecaEAR2</display-name>
<module>
<web>
<web-uri>BibliotecaWeb.war</web-uri>
<context-root>biblioteca</context-root>
</web>
</module>
<module>
<ejb>BibliotecaEJB.jar</ejb>
<bundleDir>/lib</bundleDir> <!-- ADD THIS OPTION TO THE MODULE -->
</module>
</application>
This solution is taken from the Maven EAR plugin documentation, which uses Maven 3 syntax, but I think you can use it too (or you can migrate to Maven 3).
Hope that helps.

Unable to build EntityManagerFactory Mapping XML JPA

Every time I configure orm.xml in the Persistance.xml I get the following:
E CWWJP0015E: An error occurred in the org.hibernate.ejb.HibernatePersistence persistence provider when it attempted to create the container entity manager factory for the XYZ persistence unit. The following error occurred: PersistenceUnit: XYZ Unable to build EntityManagerFactory
If I remove the entry from Persistance.xml it works fine, but the `Entity Manager is not able to locate the entity class since I am not using JPA annotation.
Rename Persistance.xml to persistence.xml
Note that the p is lower case and that the word 'persistence' does not contain the letter a.
Also, be sure persistence.xml is in an appropriate location:
The following is from the JPA spec:
A persistence.xml file defines a persistence unit. The persistence.xml file is
located in the META-INF directory of the root of the persistence unit.
The root of the persistence unit is the key here.
If you are a non-Java EE app
The jar file or directory whose META-INF directory contains the persistence.xml
file is termed the root of the persistence unit.
If you are in a Java EE app, the following are valid
In Java EE environments, the root of a persistence unit must be one of the following:
• an EJB-JAR file
• the WEB-INF/classes directory of a WAR file[80]
• a jar file in the WEB-INF/lib directory of a WAR file
• a jar file in the EAR library directory
• an application client jar file

Injecting beans into filter packaged in a shared library

I've got an JavaEE6 app with following structure:
app.ear
META-INF
application.xml
lib
commmon-server-lib.jar
webapp1.war
webapp2.war
services-ejb.jar
Both webapps have common-server-lib.jar in Class-Path entry of their MANIFEST.MF (skinny war's).
application.xml:
<application>
<module>
<ejb>services-ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>webapp1.war</web-uri>
<context-root>/webapp1</context-root>
</web>
</module>
<module>
<web>
<web-uri>webapp2.war</web-uri>
<context-root>/webapp2</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
In common-server-lib.jar there is a web filter that should have few EJBs and other CDI managed beans injected. This filter is defined in web.xml's of both webapps.
common-server-lib.jar and war's have beans.xml in appropriate place.
Now the problem is, that when I try to deploy this app to Glassfish I get errors like this:
Class [ Lcom/acme/UserService; ] not found. Error while loading
[ class com.acme.filter.MyFilter ]
UserService service is located in services-ejb.jar
So my question is: what am I doing wrong...? Is there something wrong in defining web components (that use injections for it's dependencies) in a shared library?
Edit:
In section 15.5 of JSR-315 (Servlets 3.0 final spec) one can find:
In a web application, classes using resource injection will have their annotations
processed only if they are located in the WEB-INF/classes directory, or if they are
packaged in a jar file located in WEB-INF/lib.
I've moved common-server-lib.jar to WEB-INF/lib directories of both webapps but I'm still having same issue ;/...
After many hours of struggling with this puzzle I've found a solution:
Add web-fragment.xml to commmon-server-lib.jar with my filter
Remove filter specification from webapps web.xml's
Change maven fonfiguration to remove all jar's from WEB-INF/lib
directory except commmon-server-lib.jar
Remove commmon-server-lib.jar from EAR /lib directory

Where is deployed content for JBoss AS 7

I am new to JBoss AS 7. I have tried to deploy my war file on JBoss AS 7, which seems working fine. My question is where I can see the deployed content.
I would expect it to be like Tomcat, it should have a explored war folder some where to hold the deployed content. Is there such thing for JBoss AS 7.
It should be in JBOSS_HOME/standalone/deployments see there
If you deploy a war file name as 'sample' then you could see this file domain/configuration/domain.xml as
[...]
<deployments>
<deployment name="sample.war"
runtime-name="sample.war">
<content sha1="dda9881fa7811b22f1424b4c5acccb13c71202bd"/>
</deployment>
</deployments>
[...]
<server-groups>
<server-group name="main-server-group" profile="default">
[...]
<deployments>
<deployment name="sample.war" runtime-name="sample.war"/>
</deployments>
</server-group>
</server-groups>
[...]
ls domain/content/
|---/47
|-----95cc29338b5049e238941231b36b3946952991
|---/dd
|-----a9881fa7811b22f1424b4c5acccb13c71202bd
This works for standalone/content as well.
Note that in the standalone.xml file, as referenced above, the sample.war file has a hash. The hash is the key to locating the WAR file. You will not find it by searching for "sample.war" in the 'content' directory though. First 2 characters of hash is parent directory. The rest is the directory containing the WAR file. However the WAR file has been renamed to 'content'
|---/47
|-----95cc29338b5049e238941231b36b3946952991
|---/dd
|-----a9881fa7811b22f1424b4c5acccb13c71202bd
|-------content <-- this is really sample.war file. JBoss renames it. (go figure!)
do a jar -xvf content and you will see all the class, web.xml, etc files for sample.war
Alternative way to deploy: maven-jboss-as-plugin.
You simply run
mvn deploy
And it deploys your war.
you can find your deployed jars here:
$JBOSS_HOME/standalone/tmp/vfs/deployment/