3
votes

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.

1
What problem are you having? You only have to use a discriminator in your annotation if you have multiple persistence units within the same persistence.xml. As it is you only have one which will be the default. Make sure your persistence.xml is in the same module (JAR) as your DAO and Entity classes. - Perception
@Perception please look at my post that I edited and give me some example for the discriminator. - nyxz
Maistora - you do not need a discriminator annotation, you only have one PU in your persistence.xml. But based off the error message you added I am pretty sure Eclipse is not finding your JBoss JEE implementation files. If you are using Maven then you need to add the jboss-javaee-web-6.0 dependency to your POM. If you are using some other build tool then you need to find and add the JAR to your project classpath manually. - Perception
If the message is that what bothers you I must say that I successfully use [et]Inject on some beans. For example @Inject private UserBean userBean; where the UserBean is marked as Entity. - nyxz

1 Answers

5
votes

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.