Configuration to be able to #Inject EntityManager in Seam 3 - java

In my project I use Seam 3 and I am having issues injecting the EntityManager with the #Inject annotation. I am pretty sure there is some kind of configuration to make sure the EnityManager knows which PersistenceUnit to use. For example with EJB you can type:
#PersistenceContext(unitName="MY_PERSISTENCE_UNIT_NAME")
private EntityManager eManager;
which persistence unit is configured in the persistence.xml file. Here is my pseudo configuration:
<?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="MY_PERSISTENCE_UNIT_NAME" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/TimeReportDS</jta-data-source>
<mapping-file>META-INF/orm.xml</mapping-file>
<class>....</class>
<class>....</class>
<class>....</class>
<properties>
<property name="jboss.entity.manager.factory.jndi.name"
value="java:/modelEntityManagerFactory" />
<!-- PostgreSQL Configuration File -->
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.connection.password" value="password" />
<property name="hibernate.connection.url" value="jdbc:postgresql://192.168.2.125:5432/t_report" />
<property name="hibernate.connection.username" value="username" />
<!-- Specifying DB Driver, providing hibernate cfg lookup
and providing transaction manager configuration -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="hibernate.archive.autodetection" value="class" />
<!-- Useful configuration during development - developer can see structured SQL queries -->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
</properties>
</persistence-unit>
</persistence>
I have read some articles about Seam 2 but there the configuration is made in components.xml file by adding the:
<persistence:managed-persistence-context
name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/modelEntityManagerFactory" />
inside the <components> tag. The next step in Seam 2 is to add the:
<property name="jboss.entity.manager.factory.jndi.name"
value="java:/modelEntityManagerFactory" />
in the persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
<persistence-unit name="MY_PERSISTENCE_UNIT_NAME" ...>
...
<properties>
...
<property name="jboss.entity.manager.factory.jndi.name"
value="java:/modelEntityManagerFactory" />
</properties>
</persistence-unit>
</persistence>
but it seam that in Seam 3 there is no file components.xml. Also there is no attribute unitName in #Inject annotation to specify the persistence unit.
So please help me to configure my project so I can use the #Inject with EntityManager as shown in many examples on the net.
I use Postgres database and JBoss AS 7.
EDIT: Adding an example. I don't use the EntityManager in an Entity class.
#Named("validateReportAction")
#SessionScoped
public class ValidateReportAction extends ReportAction implements Serializable {
private static final long serialVersionUID = -2456544897212149335L;
#Inject
private EntityManager em;
...
}
Here in this #Inject I get warning from Eclipse "No bean is eligible for injection to the injection point [JSR-299 ยง5.2.1]"
If I use the #Inject on some beans that are marked as Entity the #Inject works fine.

You can use #PersistenceContext on a CDI bean. It doesn't have to be an EJB.
If for some reason you want to use #Inject, you have to do more work. #Inject doesn't know about the EntityManager; it can only inject other managed beans. Happily, there is a simple workaround - use a producer method that acts as a simple trampoline.
#ApplicationScoped
public class EntityManagerProducer {
#PersistenceContext
private EntityManager entityManager;
#Produces
#RequestScoped
public EntityManager getEntityManager {
return entityManager;
}
public void closeEntityManager(#Disposes EntityManager em) {
if (em != null && em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em != null && em.isOpen()) {
em.close();
}
}
}
You can now use #Inject to inject the EntityManager. The injected EntityManager will be RequestScoped, while the EntityManagerProducer is ApplicationScoped. Furthermore, the entityManager must be closed.

Related

How to inject SessionFactory when persistence unit is defined?

I have a fully working Spring 4 + Hibernate application. Hibernate is configured via <persistence-unit>... My unit test does all DB-related work without a problem. But now I want to access Hibernate session; to do that I should inject SessionFactory. How to inject it considering the following configuration?
I know I could define a bean like LocalSessionFactoryBean but don't know how to configure it. (I want no duplicated aconfiguration also.)
MyTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/test-context.xml" })
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class})
public class MyTest {
#Inject
SessionFactory sessionFactory; // want it injected
}
test-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:annotation-config/>
<context:component-scan base-package="com.mycompany"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="hibernateJpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="persistenceUnitName" value="my-persistence-unit"/>
</bean>
</beans>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="..." version="2.0">
<persistence-unit name="my-persistence-unit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/my</jta-data-source>
<class>com.mycompany.entity.Document</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.hbm2ddl.auto" value="validate"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="false"/>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
Because I use JPA I should inject EntityManager, not SessionFactory. This solved my task finally.
#PersistenceContext
private EntityManager entityManager;
...
entityManager.refresh(obj); // working with H-session
...
This is exactly by the #m-deinum's comment; if he will add his own answer then I'll mark it as decision.

How Persistence Unit works in JPA

I am trying to learn JPA with Hibernate implementation. There are lot of blog of net about this but still i am struggling to implement it. I have written one Dao class which creates the EntityManagerFactory. But while looking this PERSISTENCE_UNIT it says
javax.persistence.PersistenceException: No Persistence provider for EntityManager named test
private final String PERSISTENCE_UNIT = "test";
private EntityManager entityManager;
public GenericDao() {
EntityManagerFactory factory = Persistence
.createEntityManagerFactory(PERSISTENCE_UNIT);
entityManager = factory.createEntityManager();
}
I also created one persistence.xml file which is in META-INF folder of web application. It looks like this.
<?xml version="1.0" encoding="UTF-8" ?>
<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" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgres://localhost:1532/test" />
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="postgres" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
For deployment Tomcat8 is being used. Please let me know why application not able to lookup PERSISTENCE_UNIT.
As per comment - the problem is your persistence.xml location. It needs to be exactly where your application expects it to be:
WEB-INF/classes/META-INF/persistence.xml
Now, why did you encounter this problem is another matter, connected with how you create your .war file. Solution that should work however, is trusting Maven to take care of that. If you set packaging to war, and put your META-INF folder into resources (src/main/resources/META-INF/persistence.xml) it should take care of things.

#PersistenceContext is null on Glassfish embedded (no ejb)

im facing following problem. In my application I'm trying to use #PersistenceContext injected into the NON ejb instance of DAO by Glassfish embedded server. So it's a pojo controlled by CDI. Like this :
#Named
public class DummyDAO implements Serializable {
#PersistenceContext private EntityManager entityManager;
public void testManager() {
if (entityManager == null) {
throw new RuntimeException("It's null!!");
}
System.out.println("Hello! I'm injected");
}
}
This dummy DAO injects into a JSF bean by CDI like this :
#ManagedBean
#SessionScoped
public class OrderImportManagerBean implements Serializable {
#Inject
DummyDAO dummyDAO;
public void testManager() {
dummyDAO.testManager();
}
}
testManager() called from an xhtml page like #{orderImportManagerBean.testManager}
entityManager is always null. The CDI itself works, all instances injected as they should but not this one. I have persistence.xml and orm.xml under resources/META-INF catalog. So after the project is packaged I get META-INF and stuff in right place (classes/META-INF). Here is my 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="persistance-unit" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:testdb"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name = "hibernate.show_sql" value = "true" />
</properties>
</persistence-unit>
</persistence>
Now I'm wondering what is wrong with my configuration? Any suggestions?
Thanks.

Cannot test JPA + Spring

I have the following test case:
#ContextConfiguration("/spring/test-context.xml")
#TransactionConfiguration(transactionManager="txManager")
#Transactional()
public class MyEntityDaoTestCase extends AbstractJUnit4SpringContextTests {
#Autowired
private MyEntityDao dao;
#Test
public void testSave_success() {
MyEntity e = new MyEntity();
dao.save(e);
MyEntity result = dao.findById(e.getId());
assertNotNull(result);
}
}
My DAO definition has as follows:
public abstract class MyEntityDAO {
#PersistenceContext
private EntityManager mEntityManager;
public void save(MyEntity entity) {
mEntityManager.persist(entity);
}
public MyEntity findById(Long id) {
return mEntityManager.find(mEntityClass, id);
}
}
My Spring config is the following:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--
Bean post-processor for JPA annotations
-->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<!--
JPA entity manager factory
-->
<bean id="jpaEntityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="unit-test-pu"/>
</bean>
<!--
Transaction manager
-->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="jpaEntityManagerFactory"/>
</bean>
<!--
Enable the configuration of transactional behavior based on annotations
-->
<tx:annotation-driven transaction-manager="txManager"/>
<!--
DAO instance beans
-->
<bean id="mockEntityDao" class="mypackage.MyEntityDao"></bean>
</beans>
I get no errors while executing my test but it won't pass. It looks like the findById() method will not find the entity in the database. Can anyone advise on how to correctly test this case?
EDIT:
My JPA provider is hibernate. I am using an in-memory HSQLDB for my unit tests and have the following configuration:
<?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="unit-test-pu" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
You could try using #TransactionalConfiguration annotation and the Spring JUnit runner.
Something like changing your class to this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/spring/test-context.xml")
#TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
#Transactional
public class MyEntityDaoTestCase {
This also means you don't need to extend the abstract case (because you are using the Spring runner) - unless you particularly like that approach.
Here more details
If you follow TDD strictly you should not use an in memory database but instead have everything mocked. The problem is that the persist method returns void. So you can not test the correct response (an entity with an id generated by a database) One way to work around this is to us the Mockito doAnswer method, here an example:
#RunWith(MockitoJUnitRunner.class)
public class CookieRepositoryTest {
#Mock
EntityManager em;
#Mock
TimeService timeService;
#InjectMocks
CookieRepository underTest = new CookieRepository();
#Test
public void testCreateEntity() throws Exception {
Cookie newCookie = new Cookie();
when(timeService.getTime()).thenReturn(new DateTime(DateTimeZone.UTC));
doAnswer(new Answer<Brand>() {
#Override
public Brand answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments();
Cookie cookie = (Cookie) args[0];
cookie.setId(1);
return null;
}
}).when(em).persist(any(Brand.class));
Cookie persistedCookie = underTest.createEntity(newCookie);
assertNotNull(persistedCookie.getId());
}
}
A complete explanation can be found on my blog post.
I think you should be extending AbstractTransactionalJUnit4SpringContextTests instead of AbstractJUnit4SpringContextTests for the #Transactional-annotations to have any effect.
If you want to test the persistence layer, you could also take a look at DBUnit capabilities.
You can find a nice article from Petri Kainulainen here about testing the persistence layer (in this case with JPA) in a Spring based scenario:
http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-integration-testing/
With this, you test if the DAO classes behave as expected, writing and reading into/from the DB, and on the service layer you can avoid testing this aspect, focusing more on the "mock" approach for the business logic.
Hope it helps
Fran

#PersistenceUnit annotation not working

I want to use the #PersistenceUnit annotation in my app to create an application managed EntityManager
#PersistenceUnit(unitName="primary")
private static EntityManagerFactory entityManagerFactory;
EntityManager entityManager = entityManagerFactory.createEntityManager();
This doesn't seem to be working. I run my code through a debugger and discover that entityManagerFactory is null. My guess is that the injection of Persistence context with the #PersistenceUnit annotation is not working.
My app is a CDI app. It was not previously a CDI application - I converted it to CDI by creating a beans.xml file in WEB-INF, I needed to in order to do something like this.
Is there anything I need to configure within CDI to get the annotation to work? Thanks.
I have a JPA application running with only Java SE. I don't have a WEB-INF/beans.xml, but I do have a META-INF/persistence.xml configuration file:
<?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="JPAPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>jpa.Container</class>
<class>jpa.Item</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:D:\NetBeansProjects\JPA\jpaTestDB;create=true"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.user" value=""/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Container and Item are the two persistence classes in my jpa package.
This was generated automatically by Netbeans. There is also some information about using JPA without Java EE in the official (Sun/Oracle) Java EE tutorial in the persistence chapter.

Categories