sotix
sotix

Reputation: 822

PersistenceContext not injecting EntityManager

I am getting a NullPointerException when trying to access the EntityManager via annotation PersistenceContext

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

@Stateless
public class UserService {

    @PersistenceContext(unitName = "jcrdb")
    private EntityManager em;

    ...
}

My persistence.xmlin path src/main/webapp/META-INF:

<?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="jcrdb" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <!-- <jta-data-source>jdbc/jcrdb</jta-data-source> -->
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <!-- this tell Hibernate to update the DDL when it starts, very useful 
                for development, dangerous in production -->
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="javax.persistence.logging.level" value="INFO" />
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:5432/jcrdb" />
            <property name="javax.persistence.jdbc.user" value="jcr_admin" />
            <property name="javax.persistence.jdbc.password" value="q1w2e3r4" />
            <!-- <property name="tomee.jpa.factory.lazy" value="true" />-->
        </properties>
    </persistence-unit>
</persistence>

The User-class:

@Entity
@Table(name = "Users")
public class User {

    @Id
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private int UserId;
    private String alias;
    private String email;
    @OneToOne(fetch = FetchType.LAZY)
    private Person person;
    @OneToMany
    private List<Role> roles;

    public User() {

    }

    // constructor, getters, setters...
}

There is no problem getting the EntityManager directly like this:

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jcrdb");
em = entityManagerFactory.createEntityManager();

I tried running this in jetty and tomEE.

It seems to me that the ejb-stuff isn't working. What am I missing here (new to all this)?

Upvotes: 3

Views: 13102

Answers (3)

Eugene Maysyuk
Eugene Maysyuk

Reputation: 3388

Sometimes this happens because PersistenceAnnotationBeanPostProcessor is not registered by Spring. To fix that you can define it manually as follows:

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

A default PersistenceAnnotationBeanPostProcessor will be registered by the <context:annotation-config/> and <context:component-scan/> XML tags.

Upvotes: 1

Faraz
Faraz

Reputation: 6285

Where are you picking up that persistence.xml file? I know how you can pick it up if you have your configuration in java (instead of XML configuration)

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setPersistenceXmlLocation(
"classpath:...../persistence.xml"
);
//factory.setPersistenceUnitName("whatever");
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setDataSource(this.springJpaDataSource());
return factory;
}

You will also need to setup DataSource:

@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/ABCXYZ");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}

Also, you will need @EnableTransactionManagement annotation over the configuration file

If you want to get rid of persistence.xml and need to make persistence configuration totally in java, then you will need to replace above that returns LocalContainerEntityManagerFactoryBean with this:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("com.wrox.site.entities");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
Configuring Persistence in Spring Framework ❘ 605
factory.setJpaPropertyMap(properties);
return factory;
}

Upvotes: 0

Quincy
Quincy

Reputation: 4433

EntityManagerFactory must be used if the persistent unit is RESOURCE_LOCAL.

@PersistenceUnit    
private EntityManagerFactory emf;

You might refer to this question and answers for the full detail.

Upvotes: 2

Related Questions