We have an EAR application that contains a WAR, Utility project and a JPA project. The JPA project contains all our entity classes and in the META-INF directory is our persistence.xml which is defined as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="TestJPA">
<description>openjpa</description>
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/TestSource</jta-data-source>
<class>model.TestTable1</class>
<class>model.TestTable2</class>
</persistence-unit>
</persistence>
Our web.xml contains the following for the persistence unit.
<persistence-unit-ref>
<persistence-unit-ref-name>peristence/TestJPA</persistence-unit-ref-name>
<persistence-unit-name>TestJPA</persistence-unit-name>
</persistence-unit-ref>
In our webservice we have the following:
#PersistenceContext(name="peristence/TestJPA", unitName="TestJPA")
private EntityManagerFactory emf;
When the application is deployed emf never gets instantiated. Its always null. We've tried #PersistenceUnit as well, with and without arguments.
We've also tried a different approach by using InitialContext lookup to get an EntityManager. Using this approach an exception gets thrown that it can't find the resource name.
Our last approach we tried was the following:
em = (EntityManager) Persistence.createEntityManagerFactory("TestJPA");
Which produces the following exception
java.lang.ClassCastException: com.ibm.ws.persistence.EntityManagerFactoryImpl incompatible with javax.persistence.EntityManager
I've looked for all sorts of tutorials with regard to OpenJPA deployment with an EAR, but all of them are either for JPA 2 or for OpenJPA 1 with Spring.
Any help would be appreciated.
//try this
#PersistenceContext(name="TestJPA")
private EntityManager em;
I'll suggest to dig into your WAS 7 and use those libraries. WAS is a nightmare if you use non-ibm libraries, even the JDK
In web modules you should use PersistenceUnit instead of PersistneceContext. Try the following injection:
#PersistenceUnit(unitName="TestJPA")
EntityManagerFactory emf;
...
EntityManager em = emf.createEntityManager();
...
em.close();
Also what kind of web service are you using? If you are using third party WS engine, annotation integration might not work.
Related
I have EJB application that is using OpenJPA persistence unit from WebSphere 8.5. The DataSource is configured on the WebSphere with the following settings:
Scope: cells:pxxxxNodexxCell
Name: MYAPP_001
JNDI name: jdbc/MYAPP/DS001
Component-managed authentication alias: MYAPP_001
Mapping-configuration alias: (none)
Container-managed authentication alias: (none)
The persistence unit is configured so:
<?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"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="myapp" transaction-type="JTA">
<jta-data-source>java:comp/env/jdbc/MYAPP/DS001</jta-data-source>
<class>...</class>
<properties>
...
</properties>
</persistence-unit>
</persistence>
Now I'm importing it into EJB:
#PersistenceContext(name = "myapp")
private EntityManager em;
The problem is, that with the following configuration the data source can not be resolved:
Caused by:
org.apache.openjpa.persistence.ArgumentException: The persistence
provider is attempting to use properties in the persistence.xml file
to resolve the data source. A Java Database Connectivity (JDBC) driver
or data source class name must be specified in the
openjpa.ConnectionDriverName or javax.persistence.jdbc.driver
property. The following properties are available in the configuration:
"WsJpaJDBCConfigurationImpl#83f2eb8d: PDQ disabled: AccessIntent
Task=disable". at
org.apache.openjpa.jdbc.schema.DataSourceFactory.newDataSource(DataSourceFactory.java:72)
at
org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.createConnectionFactory(JDBCConfigurationImpl.java:849)
at
org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl.getDBDictionaryInstance(JDBCConfigurationImpl.java:602)
at
org.apache.openjpa.jdbc.meta.MappingRepository.endConfiguration(MappingRepository.java:1518)
at
org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations.java:531)
at
org.apache.openjpa.lib.conf.Configurations.configureInstance(Configurations.java:456)
at
org.apache.openjpa.lib.conf.PluginValue.instantiate(PluginValue.java:121)
at
org.apache.openjpa.conf.MetaDataRepositoryValue.instantiate(MetaDataRepositoryValue.java:68)
at
org.apache.openjpa.lib.conf.ObjectValue.instantiate(ObjectValue.java:83)
at
org.apache.openjpa.conf.OpenJPAConfigurationImpl.newMetaDataRepositoryInstance(OpenJPAConfigurationImpl.java:967)
at
org.apache.openjpa.conf.OpenJPAConfigurationImpl.getMetaDataRepositoryInstance(OpenJPAConfigurationImpl.java:958)
at
org.apache.openjpa.kernel.AbstractBrokerFactory.makeReadOnly(AbstractBrokerFactory.java:644)
at
org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:203)
at
org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
at
org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
at
com.ibm.ws.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:72)
at
com.ibm.ws.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:35)
at
com.ibm.ws.jpa.management.JPAEMPool.getEntityManager(JPAEMPool.java:167)
at
com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:247)
at
com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:179)
at
com.ibm.ws.jpa.management.JPAEntityManager.createQuery(JPAEntityManager.java:299)
What I need, is to provide DataSource resource mapping in any of the EJB's using the EntityManager:
#Resource(name = "java:comp/env/jdbc/MYAPP/DS001", lookup = "jdbc/MYAPP/DS001", shareable = true, authenticationType = Resource.AuthenticationType.CONTAINER)
private DataSource ds;
This is very unelegant solution for me, because:
It's very confusing. It need to be declared only once, in any of the EJB's that are using #PersistenceContext. That DataSource may not be used at all in the Java code, and in my case it is not used. It will be hard to understand what that declaration is doing in that file, and why it is only in one file.
It's duplicating the configuration, that is provided in the other place. I need to specify the name of the resource once again (it was already specified in persistance.xml).
It's storing of the configuration in the source code. Quite a dirty anti-pattern.
Technically, it requires javax.annotation.Resource from Java 7, while my project is using Java 6. But the WebSphere runtime hat altered version of that annotation, so everything is working, but requires compiling with javac from WebSphere runtime, instead of standard JDK.
Is it possible to get rid of that annotation? What do I need to use as alternative?
The java:comp/env/ format represents a resource reference, so somehow you must define it. You have a few options to not define a dummy data source:
1.Define a resource at the class level - this is fully supported in Java 6 - and it correctly defines a resource reference:
#Resource(name="jdbc/dsRef", type=javax.sql.DataSource.class, lookup="jdbc/DS")
public class MyBean implements MyBeanLocal {
One more clarification to this and your code - in name you actually should just give a reference name (without java:comp/env) and then in persistence.xml you put java:comp/env/refName. Lookup defines the actual JNDI name registered on the server. You may skip defining a lookup and bind the reference to a resource during installation or via a binding file.
2.Use deployment descriptor
Create a deployment descriptor (web.xml or ejb-jar.xml) and define a resource reference for each EJB there. You will no longer have to place a DataSource with #Resource in your class.
3.Not use reference at all
Although I'd not recommend it, you can use an actual server JNDI datasource name in persistence.xml. Then you don't need a DataSource in an EJB as no reference is used.
<jta-data-source>jdbc/MYAPP/DS001</jta-data-source>
But in that case, you will not see in the admin console that the application is using a DataSource and you will not be able to change that mapping to a different data source jndi name if needed.
And in clarification of your comment:
Technically, it requires javax.annotation.Resource from Java 7, while
my project is using Java 6. But the WebSphere runtime hat altered
version of that annotation, so everything is working, but requires
compiling with javac from WebSphere runtime, instead of standard JDK
javax.annotation.Resource is a part of Java EE 6, which is implemented by WebSphere. You don't need Java v7, but a fully complaint Java EE 6 application server. You are creating a Java EE app not a Java SE one. That's why you need container classes to resolve that annotation. Its nothing 'altered' by WebSphere, just following the specification.
Supposing I have a jar with the persistence.xml configuration and the jpa entities.
I would like to have the same persistence unit shared among different applications.
For example deploy a war application and have the same persistence unit (that other applications use) injected.
#PersistenceContext(unitName="MySharedPersistence")
private EntityManager entityManager;
I can not consider packaging all the applications in an ear file since I want to have the other applications up and running while I reupload an application (the application reuploaded uses some remote ejbs from the already deployed applications and uses the same persistence unti as described above).
Are there any solutions to this problem?
Thank you in advance.
EDIT: Probably It is not recomended are there any appropriate tryouts with the same result?
You can place your Entity classes and your persistence.xml in a jar, and reuse this jar in all projects. As long as you also include a beans.xml file along with your persistence.xml, it should work just fine. You should then be able to inject the persistence context in any project that uses this jar file.
You need the beans.xml file for autodiscovery by the container. For reference, here's how a beans.xml file would look:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
I need to add geospatial information, "Points" to be specific, to entries of a MySQL database (v5.5.28). I tried to map the created column "location" to the corresponding property of my java EJB entity ServiceInfo, using the simple code:
#Column(name = "location")
private com.vividsolutions.jts.geom.Point location;
However, this causes the following error:
Exception [EclipseLink-66] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Could not deserialize object from byte array.
Internal Exception: java.io.StreamCorruptedException: invalid stream header: 00000000
Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[location-->ServiceInfo.location]
Descriptor: RelationalDescriptor(ies.persistence.entity.ServiceInfo --> [DatabaseTable(ServiceInfo)])
at org.eclipse.persistence.exceptions.DescriptorException.notDeserializable(DescriptorException.java:1218)
at org.eclipse.persistence.mappings.converters.SerializedObjectConverter.convertDataValueToObjectValue(SerializedObjectConverter.java:72)
...
I think the problem is the java mysql connector (v5.1.22) doesn't support geospatial information, which surprises me since the database does. Can someone confirm this is the case, or tell me what I might be doing wrong and point me in the right direction?
I'm working in Netbeans 7.2, using JDK 1.7 and a GlassFish Server 3.1.2
Ok, so I finally fixed my problem by making the following changes to my persistence tier:
I switched from a MySQL database to a PostgeSQL database, using the spatial extension PostGIS. The reason for this is that MySQL only partially implements the OpenGIS specifications.
Next, I had to change the persistence unit of EclipseLink (JPA 2.0)(Default) to Hibernate (JPA 2.0).
Jars to include in the classpath of both my project and glassfish (which seemed to be unable to find them otherwise. I had to copy them to the root of domain1) are:
postgresql-9.2-1002.jdbc4.jar
postgis-jdbc-2.1.0SVN.jar
Hibernate 4.1.8 (all required jars, ehcache for the optional ones and hibernate-entitymanager-4.1.8.Final.jar for JPA... These are all included in the release bundle)
hibernate-spatial-4.0-M1.jar (hibernate-spatial-1.1.1.jar and hibernate-spatial-postgis-1.1.1.jar are NOT compatible with Hibernate 4.x!).
jts-1.8.jar
The resulting persistence.xml file is:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="IES-ejbPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/postgresql_iesdb3</jta-data-source>
<class>ies.persistence.entity.ServiceInfo</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.spatial.dialect.postgis.PostgisDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
The annotations to use for my EJB entitiy are:
#Type(type="org.hibernate.spatial.GeometryType")
#Column(name = "location", columnDefinition="Geometry")
private com.vividsolutions.jts.geom.Geometry location;
We now have a proper mapping using Hibernate + JPA + PostgeSQL/PostGIS.
I am having a hard time when trying to ship inside my EAR my own version of Hibernate (and not the one that JBoss brings by default).
Then I made my deployment "scoped" by including in the EAR a jboss-app.xml file containing the following:
<jboss-app>
<loader-repository>
com.example:archive=unique-archive-name
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</jboss-app>
And, as usual, I declare my persistence provider in the persistence unit to be Hibernate, as follows:
<persistence>
<persistence-unit name="myapp">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
...
But then, the worst happens. On deployment, the server throws a ClassCastException when it tries to cast from org.hibernate.ejb.HibernatePersistence to the JPA interface javax.persistence.spi.PersistenceProvider (which IS implimented by HibernatePersistence).
This is kind of WEIRD, because I am shipping the JPA API also in my EAR, so, given that the classes of the EAR have priority to those of JBoss, it should have no problem when casting from HibernatePersistence to PersistenceProvider, since they "should be" on the same class loader.
If I don't ship my own JPA API, then the deployment fails with a ClassNotFoundException when JBoss tries to find some JPA class.
Any idea on why is this casting failing?
I am using JBoss 5.1.0, and trying to use Hibernate 3.5.6.Final. The JPA API version is the one imported transitively by the menctioned Hibernate version.
You could try turning on class scoping via the ear deployer. For JBoss 5.x edit:
jboss/server/[configuration]/deployers/ear-deployer-jboss-beans.xml
and change:
<bean name="EARClassLoaderDeployer" class="org.jboss.deployment.EarClassLoaderDeployer">
<property name="isolated">false</property>
</bean>
setting isolated to true.
Have you included the hibernate-entitymanager.jar too?
Otherwise you can try replacing the hibernate core jar in the common/lib with the 3.5.6 version.
To solve the class loading issues with hibernate in jboss server you need to add the jboss-classloading.xml inside the WEB-INF folder of your web application. Read more about these configuration settings here.
<classloading xmlns="urn:jboss:classloading:1.0"
domain="pentaho.ear"
export-all="NON_EMPTY"
import-all="true"
parent-first="false">
</classloading>
An application that has been working well for months has stopped picking up the JPA #Entity annotations that have been a part of it for months. As my integration tests run I see dozens of "org.hibernate.MappingException: Unknown entity: com.whatever.OrderSystem" type errors.
It isn't clear to me what's gone wrong here.
I have no hibernate.cfg.xml file because I'm using the Hibernate Entity Manager. Since I'm exclusively using annotations, there are no .hbm.xml files for my entities. My persistence.xml file is minimal, and lives in META-INF as it is supposed to.
I'm obviously missing something but can't put my finger on it.
I'm using hibernate-annotations 3.2.1, hibernate-entitymanager 3.2.1, persistence-api 1.0 and hibernate 3.2.1. hibernate-commons-annotations is also a part of the project's POM but I don't know if that's relevant.
Is there a web.xml entry that has vanished, or a Spring configuration entry that has accidentally been deleted?
verify in your entity classe that you import javax.persistent.Entity and not org.hibernate.annotations.Entity
I seem to recall I had a similar issue at one time.
Its a long shot, but if you're not already doing this, have you explicitly specified the provider you are using?
<persistence ...>
<persistence-unit ...>
<provider>org.hibernate.ejb.HibernatePersistence</provider> <---- explicit setting
....
</persistence-unit>
</persistence>
Otherwise, I'm not sure?
Is this happening for one specific class (few classes) or all the entity classes. The persistence.xml file has a list of class and or jar files that need to be scanned for #Entity mappings. If it was working earlier you can do a quick diff with the version of persistence.xml that was working correctly. Another issue could be that it is picking up a different persistence.xml file - you can verify this by introducing an error (for e.g., make the xml invalid) in the persistence.xml.