I'm try to use the Sun Java PetStore Demo.
In the CatalogFacade class there is the following annotation:
#PersistenceUnit(unitName="myPetStorePU")
private EntityManagerFactory emf;
In all the methods of the CatalogFacade Sun has:
EntityManager em = emf.createEntityManager();
But I am getting a null pointer exception for emf when trying to createEntityManager. But... if I add the following line above that line as such
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("myPetStorePU");
EntityManager em = emf.createEntityManager();
then emf gets successfully created and the persistence unit myPetStorePU also successfully connects to the database. So it looks like persistence.xml syntax and its location is correct. I'd like to understand why the annotation doesn't work since I think there was a reason for just using the annotation as opposed to adding the createEntityManagerFactory line in every method.
My src/META-INF/persistence.xml file looks like this:
<persistence-unit name="myPetStorePU">
<description>Petstore Persistence Unit</description>
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<class>com.sun.javaee.blueprints.petstore.model.Tag</class>
<class>com.sun.javaee.blueprints.petstore.model.SellerContactInfo</class>
<class>com.sun.javaee.blueprints.petstore.model.Product</class>
<class>com.sun.javaee.blueprints.petstore.model.Item</class>
<class>com.sun.javaee.blueprints.petstore.model.Category</class>
<class>com.sun.javaee.blueprints.petstore.model.Address</class>
<class>com.sun.javaee.blueprints.petstore.model.ZipLocation</class>
<properties>
<property name="toplink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="toplink.jdbc.url" value="jdbc:oracle:thin:##############"/>
<property name="toplink.jdbc.user" value="####"/>
<property name="toplink.jdbc.password" value="#####"/>
<property name="toplink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
Edit:
CatalogFacade is in the petstore.model package and implements the ServletContextListener
<listener>
<listener-class>com.sun.javaee.blueprints.petstore.model.CatalogFacade</listener-class>
</listener>
in the index.jsp Sun has the following:
<%
CatalogFacade cf = (CatalogFacade)config.getServletContext().getAttribute("CatalogFacade");
List<Tag> tags=cf.getTagsInChunk(0, 12);
%>
public List<Tag> getTagsInChunk(int start, int chunkSize) {
//The next line is required since the #PersistenceUnit annotation at the top of this class does not work
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("myPetStorePU");
EntityManager em = emf.createEntityManager();
System.out.println("Entity manager " + emf);
Query query = em.createQuery("SELECT t FROM Tag t ORDER BY t.refCount DESC, t.tag");
List<Tag> tags = query.setFirstResult(start).setMaxResults(chunkSize).getResultList();
em.close();
return tags;
}
If the annotated object is not managed by a container (either spring/CDI/EJB container), nothing gets injected into it.
So depending on your environment, obtain a contextual instance of that object.
If you are not using any of the above technologies (spring/CDI/EJB) - then you can't use #PersistenceUnit and #PersistenceContext. Use the manual way to obtain the unit.
For some reasons this happens when using this in you persistence.xml
<provider>org.hibernate.ejb.HibernatePersistence</provider>
switching to
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
fixes the problem
Related
I have a Java 7 / Spring 3.2.17 application which has to connect to two different databases, so I have two different persistence.xml files, each one declaring its own persistence unit.
In my application context I have defined two entity manager factories, such as:
<bean id="emf1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDatasource1" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence1.xml" />
<property name="persistenceUnitName" value="pu1" />
...
</bean>
And in my DAO classes I just let Spring inject the entity manager:
#PersistenceContext
private EntityManager entityManager;
public void setEntityManager (...) { ... }
Spring complains that I have two EM factories so it doesn't know which one to use:
NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: emf1,emf2
I have partially solved it by specifying which persistence unit I want to use, like this:
#PersistenceContext(unitName = "pu1")
private EntityManager entityManager;
public void setEntityManager (...) { ... }
That solved the problem for the classes connecting to the first database. My problem is that the classes for the other DB are part of a third-party library, so I can't modify them to add the unitName attribute. Is there any other way I can do it?
I have tried a few options, but all of them lead to the same error message:
Extending the class so I can "override the annotation":
public class MyDao extends TheDaoThatICannotModify {
#Override
#PersistenceContext(unitName = "pu2")
public void setEntityManager (EntityManager em) {
super.setEntityManager(em);
}
}
Instantiating the EM and injecting it myself:
<bean id="entityManager2" factory-bean="emf2" factory-method="getObject" />
<bean id="myDao" class="com.foo.TheDaoThatICannotModify">
<property name="entityManager" ref="entityManager2" />
</bean>
Adding the primary="true" attribute to my emf2 bean (and primary="false" to emf1).
Adding the autowire-candidate="false" attribute to my emf1 bean.
I got it working... by using Spring injection only with my own classes, and passing the EM to the evil DAOs myself:
public class MyDaoSingletonFactoryIsh {
#PersistenceContext(unitName = "pu2")
private EntityManager em; // Injected by Spring
private static TheDaoThatICannotModify dao = null;
public TheDaoThatICannotModify getDAO() {
if (dao == null) {
dao = new TheDaoThatICannotModify();
dao.setEntityManager(em);
}
return dao;
}
}
I don't know how to call this pattern: factory, singleton, wrapper? It doesn't really fit in any of these categories, it's a weird combination of them. Which isn't probably a good sign, it looks like a huge code smell and I'd prefer to avoid it. But at least it's working, so, lacking of a better solution...
I'm trying to implement a entitymanager-per-conversation pattern on a stateful proprietary web framework with JBoss 4.3.0 and Hibernate 4.3.5. In short, the goal is:
First HTTP request loads entity A with lazy-loading properties from the database
In second request, the lazy-loading properties of entity A are accessible without e.g. creating a new EntityManager and calling e.g. entityManager.merge(entityA).
Entitymanager-per-conversation seems like the perfect choice. Here's my attempt:
public class EntityManagerHolder {
private static ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
private static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myPersistence");
private static ConnectionProvider connectionProvider = new MyConnectionProvider();
public static synchronized EntityManager getEntityManager() {
createEntityManagerIfNeeded();
return entityManager.get();
}
public static synchronized void createEntityManagerIfNeeded() {
if (entityManager.get() == null) {
// Start the conversation
EntityManager newEntityManager = entityManagerFactory.createEntityManager();
entityManager.set(newEntityManager);
newEntityManager.getTransaction().begin();
} else {
// Entitymanager is alive but may have lost its connection
EntityManager existingEntityManager = entityManager.get();
SessionImpl session = existingEntityManager.unwrap(SessionImpl.class);
try {
if (session.connection() == null || session.connection().isClosed()) {
session.reconnect(connectionProvider.getConnection());
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
Persistence.xml:
<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="myEntityManagerFactory">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files from this JAR -->
<property name="hibernate.archive.autodetection" value="class, hbm" />
<!-- Database connection settings: Use framework connections for database connectivity -->
<property name="hibernate.connection.provider_class" value="foo.bar.MyConnectionProvider"/>
</properties>
</persistence-unit>
</persistence>
When a new HTTP request arrives via the framework, I call EntityManagerHolder.createEntityManagerIfNeeded(). On the second HTTP request, the JDBC connection of the EntityManager has closed and the attempt to revive it via session.reconnect() leads to an exception:
java.lang.IllegalStateException: cannot manually reconnect unless Connection was originally supplied
org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.manualReconnect(LogicalConnectionImpl.java:296)
org.hibernate.internal.SessionImpl.reconnect(SessionImpl.java:478)
I realize I'm probably doing things in a very backwards way, but it would be nice to understand how entitymanager-per-conversation should be implemented. I've found the filter-based Hibernate-specific sample implementation of this pattern, but haven't managed to bend it to my needs yet.
Turns out JBoss was closing the connections. Disabling JBoss from closing JDBC connections would have resolved the issue. However, we wanted to avoid keeping a large number of JDBC connections open for long periods of time.
Best solution found so far is to revive the JDBC connection of the EntityManager, provided that the old connection is closed. I wrote a rough implementation:
EntityManagerFactoryAdapter - Used to reconnect an EntityManager to a new JDBC connection
EntityManagerHolder - Keeps one EntityManager per thread.
At the start of each HTTP request, we invoke EntityManagerHolder.initializeEntityManager(freshJDBCConnectionFromFramework). When the state is removed from the server, we invoke EntityManagerHolder.closeEntityManager(). Persistence.xml no longer has the hibernate.connection.provider_class - we're passing in connections manually.
I'm posting this just in case someone encounters a similar issue. This solution is very unorthodox, I'm hoping to replace it with a better one later.
In the persistence.xml JPA configuration file, you can have a line like:
<persistence-unit name="com.nz_war_1.0-SNAPSHOTPU" transaction-type="JTA">
or sometimes:
<persistence-unit name="com.nz_war_1.0-SNAPSHOTPU" transaction-type=”RESOURCE_LOCAL”>
My question is:
What is the difference between transaction-type="JTA" and transaction-type=”RESOURCE_LOCAL” ?
I also noticed some persistence.xml files with the transaction-type missing. Is it correct?
Defaults
Default to JTA in a JavaEE environment and to RESOURCE_LOCAL in a JavaSE environment.
RESOURCE_LOCAL
With <persistence-unit transaction-type="RESOURCE_LOCAL"> you are responsible for EntityManager (PersistenceContext/Cache) creating and tracking
You must use the EntityManagerFactory to get an EntityManager
The resulting EntityManager instance is a PersistenceContext/Cache
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
You are not allowed to use #PersistenceContext to refer to a unit of type RESOURCE_LOCAL
You must use the EntityTransaction API to begin/commit around every call to your EntityManger
Calling entityManagerFactory.createEntityManager() twice results in two separate EntityManager instances and therefor two separate PersistenceContexts/Caches.
It is almost never a good idea to have more than one instance of an EntityManager in use (don't create a second one unless you've destroyed the first)
JTA
With <persistence-unit transaction-type="JTA"> the container will do EntityManager (PersistenceContext/Cache) creating and tracking.
You cannot use the EntityManagerFactory to get an EntityManager
You can only get an EntityManager supplied by the container
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
You are not allowed to use #PersistenceUnit to refer to a unit of type JTA
The EntityManager given by the container is a reference to the PersistenceContext/Cache associated with a JTA Transaction.
If no JTA transaction is in progress, the EntityManager cannot be used because there is no PersistenceContext/Cache.
Everyone with an EntityManager reference to the same unit in the same transaction will automatically have a reference to the same PersistenceContext/Cache
The PersistenceContext/Cache is flushed and cleared at JTA commit time
I'm trying to develop a simple JSP based web application with JPA and would like to know the correct usage for developing one.
In my sample application I have two JSP pages and a simple Java class to perform database operations. Both the JSP files use this Java class to perform DB operations.
I've annotated this class with #Stateless and injected an Entity manager as follows:
#PersistenceContext(unitName = "myjpa")
EntityManager em;
In my persistence.xml I've set the following property:
<property
name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"
/>
I'm calling the class in JSP using JNDI (as the class is annotated for a stateless session bean) as follows:
InitialContext ic = new InitialContext();
Sample sample = (Sample) ic.lookup("java:app/" + application.getContextPath() + "/Sample");
I'm facing the following scenarios:
When I try to use a transaction em.getTransaction().begin()/commit() for insert and update, it says can not use transaction with JTA case.
So in the constructor code of my Java class I use the following code:
Properties properties = new Properties();
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
emf = Persistence.createEntityManagerFactory("myjpa",properties);
em = emf.createEntityManager();
I tried to use transactions like em.getTransaction().begin()/commit().
But in this case the pages become very slow after 2-3 database update and load operations. Though I'm not getting any exception. Overall in my table I'm having less than 25 records.
To me it seems as if it is waiting internally for some operation to complete.
At the same time I also feel that the way I'm using JPA is wrong and hence soliciting advice for the correct approach for doing even simple web apps with JSP and JPA.
While I'm still exploring Java EE, in case you have any specific reference for such cases I'll like to read and look them too.
You should always strive to use JTA transactions which means the container will handle the transaction demarcations. In your case if you want to handle transactions by your self, you need to define it as a bean managed transaction. So in your EJB class, after the #Stateless annoattions, you should define the following annotation;
#TransactionManagement(TransactionManagementType.BEAN)
The usual best practice is to let the container handle the transactions, unless there is some explicit reason for you to use Bean managed transactions.
At the same time I also feel that the way I'm using JPA is wrong
Your usage indeed seems wrong. If you're using a (stateless) session bean you do not have to fiddle with em.getTransaction().begin()/commit() and you definitely don't have to use code such as Persistence.createEntityManagerFactory.
You also don't have to set the property org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform.
A session bean automatically manages the transaction for you, and within a Java EE AS (such as JBoss AS) you don't have to configure any transaction manager or similar things.
An example:
#Stateless
public class UserDAO {
#PersistenceContext
private EntityManager entityManager;
public void add(User user) {
entityManager.persist(user);
}
}
As for the persistence.xml file, something like the following should be enough to get started:
<?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="somePU">
<jta-data-source>java:app/someDS</jta-data-source>
</persistence-unit>
</persistence>
Some more examples:
http://jdevelopment.nl/sample-crud-app-with-jsf-and-richfaces
http://arjan-tijms.omnifaces.org/2011/08/minimal-3-tier-java-ee-app-without-any.html
This is my first attempt at Entity beans and I repeatedly get the following error:
java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
I wrote a simple entity beans example using a Netbeans 7.3 and GlassFish 3.1.2.2 Server. It seems there is a problem with my persistance.xml file. However, I am unable to fix this. I read up
JavaEE 6: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
Unable to retrieve EntityManagerFactory for unitName null for simple EJB - see nosferatum answer
But after hours also I have not quite been able to fix this. I am attaching the screenshot of my directory structure and also code for my XML file with the hope that someone can point out the mistake.
persistance.xml : ( Code autogenerated by NetBeans )
<?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="EnterpriseApplication3-ejbPU" transaction-type="JTA">
<jta-data-source>TestDatabase</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
Failing Code :
Declaration :
// This injects the default entity manager factory
#PersistenceUnit
private EntityManagerFactory emf;
Point of Invocation :
EntityManager em = emf.createEntityManager();
Also, a few people seem to do this :
#PersistenceContext(unitName = "myPU")
and have the same name in the persistance.xml. I did a quick search of all my project files and did not come up with the #PersistenceContext annotation. But I added
#PersistenceContext(unitName = "EnterpriseApplication3-ejbPU")
to my code that calls the EntityManagerFactory. But still no success :(
try this one:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnterpriseApplication3-ejbPU");
EntityManager em = emf.createEntityManager();