cdi does not inject entitymanager - java

cdi don't injects entitymanager, always the nullpointer. Following configuration:
persistence.xml
<?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_1_0.xsd"
version="1.0">
<persistence-unit name="tutoroo" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/tutoroo</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</properties>
</persistence-unit>
</persistence>
public class ProdutorEntityManager implements Serializable {
private EntityManagerFactory factory = Persistence.createEntityManagerFactory("tutoroo");
//private EntityManager entityManager = factory.createEntityManager();
#Produces
#PersistenceContext
#RequestScoped
public EntityManager criaEntityManager(){
return factory.createEntityManager();
}
public void dispose(#Disposes EntityManager em) {
em.close();
}
}
public class UsuarioDaoImp implements UsuarioDao {
#Inject
private EntityManager manager;
public void salvar(Usuario usuario) {
manager.persist(usuario);
}
}
When I debug the EntityManager UsuarioDaoImp class, this exception occurs: com.sun.jdi.InvocationException occurred invoking method.
I do not know what I'm doing wrong. Can anyone help?
Server is: jboss-as-7.1.1

First off, don't create the persistence units yourself in an app server, but let the server inject it for you.
Here's why, from JavaDocs:
The Persistence class is available in a Java EE container environment as well; however, support for the Java SE bootstrapping APIs is not required in container environments.
Not sure how jbos-as-7 behaves, but it is generally discouraged because of reasons such as loosing JTA support.
For simplicity, I assume you only have one persistence unit in your application. Please ask and I'll edit if you need examples for an application with multiple persistence units.
To simply use the entity manager in any CDI managed bean:
public class CDIBean {
// the container injects it
#PersistenceContext
private EntityManager em;
// just use it
public void someMethod(Entity someEntity) {
this.em.persist(someEntity);
}
}
That's all there is to it.
However, in many examples, a combination of producers / disposers are declared for various reasons. I bet this is where the confusion comes from. Some of the use cases:
To allow you to use #Inject EntityManger em; instead of #PersistenceContext EntityManager em;
// to make it available for injection using #Inject
public class CDIProducer {
// again, the container injects it
#PersistenceContext
private EntityManager em;
// this will have the default dependent scope
#Produces
public EntityManager em() {
return em;
}
public void dispose(#Disposes EntityManager em) {
em.close();
}
}
// to use it
public class CDIBean {
#Inject
private EntityManager em;
// just use it
public void someMethod(Entity someEntity) {
this.em.persist(someEntity);
}
}
or to bind an entity manager to a particular scope.
// to make it available for injection using #Inject, and bind it to the #RequestScope
public class CDIProducer {
// again, the container injects it
#PersistenceContext
private EntityManager em;
// this will be in the request scope
#Produces
#RequestScoped
public EntityManager em() {
return em;
}
public void dispose(#Disposes #RequestScoped EntityManager em) {
em.close();
}
}
// to use it
public class CDIBean {
#Inject
private EntityManager em;
// just use it
public void someMethod(Entity someEntity) {
this.em.persist(someEntity);
}
}
Finally, the method producers above can be converted to field producers. This is equivalent to the last example:
// to make it available for injection using #Inject, and bind it to the #RequestScope
public class CDIProducer {
#PersistenceContext
#Produces
#RequestScoped
private EntityManager em;
public void dispose(#Disposes #RequestScoped EntityManager em) {
em.close();
}
}

I think that #RequestScoped is not allowed as parameter injection.

Related

Retrieve Alternative entityManager on unit test though CDI

I'm using Junit 5, Java bath that run under a webapp EE8 environment.
On the web app, I actually have a resources class that is employed as a producer:
#ApplicationScoped
public class Resources {
#Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
#Produces
#PersistenceContext(unitName = "primary")
private EntityManager entityManager;
}
Now I want to write some SE test, and I need to retrieve an alternative entity manager, something like:
public class MockResources {
#Alternative
#JobScoped
#Produces
public EntityManager getEntityManager() {
return Persistence.createEntityManagerFactory("primary").createEntityManager();
}
}
The issue is that I don't know how to retrieve this alternative entity , as beans.xml want a class (I tried with Hibernate SessionImpl but it doesn't work), neither #Stereotype looks good for my case.
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<class>org.hibernate.internal.SessionImpl</class>
</alternatives>
</beans>
Any help ?
You should create an entire #Alternative Resources producer bean, as in
#Alternative
#ApplicationScoped
public class TestResources {
#Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
#Produces
private EntityManager getEntityManager() {
// create your new entitymanager here
return Persistence.createEntityManagerFactory("testunitname").createEntityManager();
}
}
Then define your test alternative class on test beans.xml as described on your question.

How to prevent implicit caching in Spring Boot 1.5.1 Hibernate

I am trying to understand why, after creating a new entity and persisting it whilst the application is running, when retrieving a list of these entities, the new entity should be retrieved from the database, but isn't?
For example:
I created a new entity (from the UI) and persisted it successfully like so:
#Repository
public class BaseDAOHibernate {
Session session;
public BaseDAOHibernate() {
session = HibernateUtils.getSessionFactory().openSession();
}
public void save(Object object) {
Transaction tx = session.beginTransaction();
session.save(object);
tx.commit();
}
...
I verified that the entity is persisted in the database.
Next, when I refresh the UI which lists these entities (for which I added a new one to the database) the new entity is not included and was not retrieved from the following:
#Repository
#SuppressWarnings("unchecked")
public class PasswordDAOHibernate extends BaseDAOHibernate implements PasswordDAO {
#Override
public Collection<Password> getPasswords() {
Query query = session.createQuery("select ...");
return query.list();
}
Here is the interface:
public interface PasswordDAO {
Password getPassword(Integer id);
Collection<Password> getPasswords();
Collection<Password> getPasswords(PasswordSearchParameters params);
Collection<PasswordType> getPasswordTypes();
}
...
Which is called from a controller:
#Controller
public class PasswordsController extends BaseControllerHelper {
#Autowired
private PasswordDAOHibernate passwordDAO;
#RequestMapping("/passwords.htm")
public void passwords(Map model,
HttpServletRequest request) {
Collection<Password> passwords = passwordDAO.getPasswords();
model.put("passwords", passwords);
}
Here is the configuration currently setup:
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">password</property>
<property name="hibernate.connection.url">jdbc:mysql://host:3306/server</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<mapping class="com.crm.entity.User"></mapping>
<mapping class="com.crm.entity.Role"></mapping>
<mapping class="com.crm.entity.Property"></mapping>
<mapping class="com.crm.entity.Menu"></mapping>
<mapping class="com.crm.entity.Password"></mapping>
<mapping class="com.crm.entity.PasswordType"></mapping>
</session-factory>
</hibernate-configuration>
HibernateUtils.java
#Component
public class HibernateUtils {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
return new Configuration().configure().buildSessionFactory();
}
catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
getSessionFactory().close();
}
}
When I restart the server application the new entity displays in the list.
Is there some kind of implicit caching going on that I need to clear? Note, I have not implemented any explicit caching at this stage.
The problem is your dao, which is flawed in a very dangerous way. A Session isn't thread safe and shouldn't be shared. It should be opened for each action (or at least the current session should be used).
Plain Hibernate Solution
You DAO should look something like this.
private final SessionFactory sessionFactory;
protected BaseDAOHibernate(SessionFactory sessionFactory) {
this.sessionFactory=sessionFactory;
}
protected Session getSession() {
return this.sessionFactory.getCurrentSession();
}
public void save(Object object) {
getCurrentSession().save(object);
}
Now you specific dao should reuse the getSession method.
#Repository
#Transactional
public class PasswordDAOHibernate extends BaseDao implements PasswordDao {
#Autowired
public PasswordDAOHibernate(SessionFactory sessionFactory) {
super(sessionFactory);
}
#Override
public Collection<Password> getPasswords() {
return getSession.query("select ...", Password.class).list();
}
When doing so you probably will run into issues with an error stating that no session can be found due to no transaction (or something along those lines).
To fix this use Spring Boot (and some manual configuration).
First move the hibernate.connection properties to your application.properties and remove them from hibernate.cfg.xml.
spring.datasource.url=jdbc:mysql://host:3306/server
spring.datasource.username=username
spring.datasource.password
Now Spring will create a Datasource for you. Next remove your HibernateUtils and configure the SessionFactory using Springs LocalSessionFactoryBean.
#Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setDataSource(dataSource);
return factory;
}
You will also need the appropriate transaction manager
#Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
Now due to everything being setup in Spring, the injection of the SessionFactory and the #Transactional you will get a managed Session which will be properly opened and closed for you.
Controller Fix
Your controller is also flawed as you should be injecting a PasswordDao and not the concrete type (which would now fail due the the creation of a proxy for the transactions).
#Controller
public class PasswordsController extends BaseControllerHelper {
#Autowired
private PasswordDAO passwordDAO;
JPA Solution
However while all of this will probably work I would strongly suggest to use JPA and the EntityManager instead of the Session and SessionFactory approach.
To do so remove the LocalSessionFactoryBean and the HibernateTransactionManager and add the remaining properties of the hibernate.cfg.xml to the application.properties.
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
Next to the spring.datasource properties that is all you need and you can delete the hibernate.cfg.xml file.
Now instead of using the SessionFactory use the EntityManager in your dao.
public abstract class BaseDao {
#PersistenceContext
protected EntityManager em;
public void save(Object o) {
em.persist(o);
}
}
And your specific dao.
#Repository
#Transactional
public PasswordJpaDao extends BaseDao implements PasswordDao {
#Override
public Collection<Password> getPasswords() {
return em.createQuery("select ...", Password.class).getResultList();
}
Spring Data JPA Solution
When using JPA you could even drop your generic dao approach and implementations and use Spring Data JPA instead. Your whole PasswordDao would then look like
public interface PasswordDao extends JpaRepository<Password, Long> {}
All the crud functionality (findAll, findOne, save etc.) is available out-of-the-box. Creating queries is pretty easy and saves you from writing the boilerplate code.
You can use #Cacheable(false) on your entity
or disable the shared cache altogether for all your entities by adding this to your persistence.xml
<shared-cache-mode>NONE</shared-cache-mode>
For Hibernate you can also use
session.setCacheMode(CacheMode.IGNORE);
see this link for more information about the different cache levels in JPA

Can I use CDI to inject a resource into a JAX-RS Application/ResourceConfig?

I'd like for my ResourceConfig to have access to a database for its configuration. I've tried this:
#ApplicationPath("/api")
public class ApplicationConfig extends ResourceConfig {
#PersistenceContext(unitName = "myPU")
private EntityManager em;
#Inject
private MyEjb myEjb;
#PostConstruct
public void init() {
// em and myEjb are both null
...
}
But neither the EntityManager, not the EJB, are injected (both are null)
Is there a special way to do this in JAX-RS?
NOTE: I'm able to inject resources into a Path-annotated class just fine. I'm having trouble doing it in the actual ApplicationPath-annotated class.

Spring Entities Not Saved To Database

We have set up the Spring Framework like this:
#Eager
public interface CatalogElementRepository extends PagingAndSortingRepository<CatalogElementEntity, Long> {
}
#Service
public class CatalogImpl implements CatalogManager {
#Inject
CatalogElementRepository catalogElementRepository;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.catalogElementRepository.save(catalogElement);
}
}
#Stateless
#Remote(CatalogManager.class)
public class CatalogManagerBean implements CatalogManager {
#Inject
CatalogManager delegate;
#Override
public CatalogElement createCatalogElement(CatalogElementEntity catalogElement) {
return this.delegate.createCatalogElement(catalogElement);
}
}
So whenever someone calls the method on the remote interface createCatalogElement, I'd assume the entity gets stored in the database. It does not (weirdly enough, findOne still returns the very same entity, but it can't be found via findByProperty).
Other questions said to add #Transactional, so I added #javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional on the methods and classes to be on the safe side, nothing worked.
What could be the problem?
I don't see any configuration files for the Spring Framework, but it's a legacy project, so they might just be hidden very well.
For some reason using this class as a producer for the EntityManager helped:
public class SpringConfig {
#PersistenceUnit
EntityManagerFactory emf;
#PersistenceContext
EntityManager em;
#Produces
#ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return this.emf;
}
#Produces
public EntityManager createEntityManager() {
return this.em;
}
public void close(#Disposes EntityManagerFactory entityManagerFactory) {
entityManagerFactory.close();
}
public void close(#Disposes EntityManager entityManager) {
entityManager.close();
}
}

No transactional entitymanager available in #PostConstruct

Problem:
entityManager.unwrap(SessionImplementor.class) cause no transactional entitymanager available exception.
Code:
#Component
public class HibernateEventWiring {
#Autowired
private ViewListener listener;
#PersistenceContext(unitName = "config-punit")
private EntityManager entityManager;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = getSessionFactory();
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(listener);
}
#Transactional
private SessionFactory getSessionFactory() {
// EXCEPTION: No transactional entitymanager available
return entityManager.unwrap(SessionImplementor.class).getFactory();
}
}
According to this excelent answer:
In the #PostConstruct (as with the afterPropertiesSet from the InitializingBean interface) there is no way to ensure that all the post processing is already done, so (indeed) there can be no Transactions.
As I see, you do not need a transaction nor an entity manager bean, but rather an entity manager factory bean. I think you should simply autowire the EntityManagerFactory and then unwrap the Hibernate SessionFactory from it.
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
...
}

Categories

Resources