Apache Karaf, can't inject entity manager - java

I want to use entity manager from container, but when I try to access it I get
java.lang.IllegalStateException: Need active coordination
persistence.xml
<persistence-unit name="data-point" transaction-type="JTA">
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=dvdrental)</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.archive.autodetection" value="class"/>
</properties>
bluprint.xml
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"
default-activation="eager"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.2.0"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0">
<jpa:enable />
<tx:enable-annotations />
<service id="filesEntityManager" ref="filesEntityManagerImpl" interface="ru.bia.karaf.dao.FilesEntityManager"/>
<bean id="filesEntityManagerImpl" class="ru.bia.karaf.dao.FilesEntityManagerImpl"/>
<bean id="testBean" class="ru.bia.karaf.web.TestBean" init-method="test">
<property name="filesEntityManager" ref="filesEntityManagerImpl"/>
</bean>
TestBean.java
public class TestBean {
private FilesEntityManagerImpl filesEntityManager;
public void test(){
System.out.println("hey bro from init");
System.out.println("filesEntityManager = " + filesEntityManager);
System.out.println("filesEntityManager.getEm() = " + filesEntityManager.getEm());
}
public FilesEntityManagerImpl getFilesEntityManager() {
return filesEntityManager;
}
public void setFilesEntityManager(FilesEntityManagerImpl filesEntityManager) {
this.filesEntityManager = filesEntityManager;
}
}
FilesEntityManagerImpl.java
#OsgiServiceProvider(classes = {FilesEntityManager.class})
#Transactional
public class FilesEntityManagerImpl implements FilesEntityManager {
#PersistenceContext(unitName="data-point")
EntityManager em;
...
}

The EntityManager that is injected into FilesEntityManagerImpl is a thread local proxy of the EntityManager. Its lifecycle is bound to a Coordination.
If you access em outside of a Coordination you get this error. You can make sure a Coordination is active by using the #Transactional annotations. If you
do not need an actual transaction but only the Coordination then use #Transactional(TxType.SUPPORTS).
You should also generally not access the EntityManager outside of the object that is injected with it.

Related

How to correctly inject EntityManager into JAX-WS web service?

I'm trying to implement a JAX-WS web service which has an endpoint that returns data from the configured data source. I managed to create the service and the client, but I can't access the database because I get Null Pointer Exceptions when I try to use the injected EntityManager.
Here is my service:
#WebService(serviceName="ViewDocuments")
public class ViewDocumentService {
#PersistenceContext(unitName = "HibernateJPA")
private EntityManager em;
#WebMethod
public String sayHello() {
return "Hello world!";
}
#Produces("application/json")
#WebMethod(operationName="getDocuments")
public List<File> getDocuments(#WebParam(name = "name") String filename) {
if(filename == null)
return em.createQuery("FROM File").getResultList();
else return null;
}
}
And here is my WebServiceClient:
#WebServiceClient(name="ViewDocuments", wsdlLocation = "http://localhost:8080/lab8/ViewDocuments?wsdl")
public class ViewDocumentClient extends Service {
protected ViewDocumentClient(URL wsdlDocumentLocation, QName serviceName) {
super(wsdlDocumentLocation, serviceName);
}
#WebEndpoint(name = "DocumentPort")
public ViewDocumentService getDocumentPort() {
return new ViewDocumentService();
}
}
I am trying to call the function here:
public class MainDocumentClient {
public static void main(String[] args) throws Exception {
URL wsdlUrl = new URL("http://localhost:8080/lab8/ViewDocuments?wsdl");
QName serviceName = new QName("http://webservices/", "ViewDocuments");
ViewDocumentClient service = new ViewDocumentClient(wsdlUrl, serviceName);
ViewDocumentService viewDocumentService = service.getDocumentPort();
System.out.println(viewDocumentService.sayHello());
System.out.println(viewDocumentService.getDocuments(null));
}
}
This is my persistence.xml file content:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="HibernateJPA" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/Postgres-Source8</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL95Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.archive.autodetection" value="class, hbm" />
</properties>
</persistence-unit>
<persistence-unit name="HibernateJPAForTests" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/lab8" />
<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="<password>" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL95Dialect" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.archive.autodetection" value="class, hbm" />
</properties>
</persistence-unit>
</persistence>
The sayHello() method works fine. I also tried to use an EntityManagerFactory, to instantiate my Repository by hand, to add the #Stateless annotation, but nothing seems to work. I just can't query my database.
After lots of research, I still can't seem to understand how to properly inject the EntityManager. Can someone explain this to me, please?
I am using Wildfly21.0.0.

Getting access to registred EntityManager in a Runnable

I have a working JSF application with JPA. The JTA-DataSource is wildfly-managed.
Now I have to run some database operations periodically. As mentioned here ( SO: How to run a background task in a servlet based web application? ) I created the two classes:
#WebListener
public class Scheduler implements ServletContextListener {
private ScheduledExecutorService scheduler;
#SuppressWarnings("deprecation")
#Override
public void contextInitialized(ServletContextEvent event) {
Calendar c = new GregorianCalendar();
Date d = c.getTime();
int stm = 60 - d.getSeconds();
int mth = 60 - d.getMinutes();
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new TestRunner(), stm, 60, TimeUnit.SECONDS);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
public class TestRunner implements Runnable {
private EntityManager em;
public TestRunner() {
}
#Override
public void run() {
this.Test();
}
public void Test() {
System.out.println("Test executed...");
if (this.em != null) {
System.out.println(em.find(Ship.class, 2).getName());
System.out.println(em.find(Commodity.class, 1).getName());
} else {
System.out.println("EntityManager is null");
}
}
}
The best whould be to access the registered Persistence Unit.
I tried to get the EM via #PersistenceContext(unitName = "PU"), tried to register the Persistence in the web.xml to get it via JNDI, but had no luck.
Where is my mistake?
Found a solution for me: define a second persistence content.
First, my persistence unit:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
version="2.1">
<persistence-unit name="PU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:jboss/datasources/mysqldb</jta-data-source>
<class>model.Commodity</class>
<class>...</class>
<properties>
<!-- <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/> -->
<!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<!-- <property name="hibernate.show_sql" value="true" /> -->
<property name="hibernate.enable_lazy_load_no_trans" value="true" />
</properties>
</persistence-unit>
<persistence-unit name="RLPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:jboss/datasources/mysqldb</jta-data-source>
<class>model.Commodity</class>
<class>...</class>
<properties>
<!-- <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/> -->
<!-- <property name="hibernate.hbm2ddl.auto" value="update" /> -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<!-- <property name="hibernate.show_sql" value="true" /> -->
<property name="hibernate.enable_lazy_load_no_trans" value="true" />
</properties>
</persistence-unit>
</persistence>
In JSF I use the EntityManager within the CDI-Beans via
#PersistenceContext(unitName = "PU", type = PersistenceContextType.EXTENDED)
private EntityManager em;
Within the CronJob/Scheduler/Runnable I create the EntityManager via
public TestRunner() {
this.em = Persistence.createEntityManagerFactory("RLPU").createEntityManager();
}
So can I use the Persistence Context both in a container managed class and in unmanaged classes.

Provider org.hibernate.envers.event.EnversIntegrator not a subtype error in CDI+JPA2.1+Restful

I am trying to call JPA from a rest web service. but it throws me
org.hibernate.integrator.spi.Integrator: Provider org.hibernate.envers.event.EnversIntegrator not a subtype at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:170) at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:136) at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:204) at
org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:101) at
org.apache.openejb.server.cxf.rs.AutoJAXRSInvoker.invoke(AutoJAXRSInvoker.java:68) at org.apache.cxf.interceptor.ServiceInvokerInterceptor
I have used maven 4, JPA 2.1, CDI.
My code:
JPA part:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("defaultMainUnit", null);
EntityManager entityManager = entityManagerFactory.createEntityManager();
Persistence.generateSchema("defaultMainUnit", null);
Query master Query = entityManager
.createNamedQuery("master.findAll");
List<Master > masterList = masterQuery.getResultList();
for(Master master : masterList){
System.out.println("Master id: "+master .getMaster TrackingId());
}
entityManager.clear();
entityManager.close();
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="defaultMainUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>core.Master</class>
<class>core.Child</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:defaultDB" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.connection.release_mode" value="after_statement"/>
<!-- insert data using sql file -->
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.create-source" value="metadata"/>
<property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
<property name="javax.persistence.sql-load-script-source" value="mcb-test-import.sql"/>
</properties>
</persistence-unit>
Restservice:
package restcdi.rest;
#Path("/")
public class GreetREST {
#Inject
private EnglishGreet greet;
#GET
#Path("/greet")
#Produces(MediaType.TEXT_PLAIN)
public String greet() {
return greet.greet();
}
#GET
#Path("/master")
#Produces(MediaType.APPLICATION_JSON)
public List master() throws FileNotFoundException, IOException{
CheckJPAProperties check = new CheckJPAProperties();
List masterList = check.runMe();
return masterList;
}
}
in the above code, runMe() returns all the masters in database using JPA code above. when i run the JPA code without a rest service in main it runs fine and returns everything. I am not sure what I am missing. I tried including the hibernate-envers dependency in pom.xml but it still throws the same error.
please help.
ps: just in case this is needed i am including my applicationConfig
package restcdi.rest;
import java.util.Set;
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("rest")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
resources.add(GreetREST.class);
return resources;
}
}

Hibernate JPA interceptor doesn't get call

The setup I have an old project that is stuck to jdk 1.5, thus spring and hibernate versions are also the maximum possible to support this version of java. Hibernate is 3.3.2.GA and spring is 3.1.1.RELEASE. Setup is the following:
<persistence-unit name="myUnit" transaction-type="RESOURCE_LOCAL">
<mapping-file>persistence-query.xml</mapping-file>
...
<properties>
<property name="hibernate.max_fetch_depth" value="3" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.ejb.interceptor" value="com.myproj.common.dao.AuditInterceptor"/>
</properties>
</persistence-unit>
application context:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="..."/>
<tx:annotation-driven transaction-manager="transactionManager" />
<aop:aspectj-autoproxy/>
<bean id="applicationContextProvder" class="com.myproj.common.utils.ApplicationContextProvider"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:persistence.xml" />
<property name="persistenceUnitName" value="myUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<!-- Local transaction management -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
and my interceptor:
#Component
public class AuditInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 98658932451L;
#Autowired
private JdbcTemplate jdbcTemplate;
public void afterTransactionBegin(Transaction tx) {
if (user != null) {
jdbcTemplate.execute("call ah_audit_pkg.SetAudit('test')");
super.afterTransactionBegin(tx);
}
}
}
I run a junit to test that interceptor is getting called and it is not. In debug mode, I am able to see this:
Any help is appreciated! Why my intercetprot is not getting called.
Edit:
I also tried the interceptor to override the afterTransactionBegin but it didn't help.
I ended up with the following solution:
I have my entityt that extends from a superclass mapped entity:
#Entity
#Table(name = "my_table")
public class MyTable extends AuditInfo
The AuditInfo entity has the following mapping:
#MappedSuperclass
public abstract class AuditInfo implements Serializable {
...
#PrePersist
void onCreate() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is stored
}
#PreUpdate
void onPersist() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is updated
}
#PreRemove
void onRemove() throws SQLException {
//this empty method is needed for AOP to trigger the audit information insert before entity is removed
}
}
And the Aspect class:
#Aspect
#Component
public class MyAspect {
#Before("execution(* com.mypackage.entities.AuditInfo.on*(..))")
public void setAuditHistory(JoinPoint jp){
final AuditInfo info = ((AuditInfo)jp.getThis());
JdbcTemplate jdbcTemplate = ApplicationContextProvider.getApplicationContext().getBean(JdbcTemplate.class);
jdbcTemplate.execute(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection conn) throws SQLException {
CallableStatement stmt = conn.prepareCall("begin ah_audit_pkg.SetAudit(?,?); end;");
stmt.setString(1, info.getAuditUser());
if(info.getAuditLocation() != null && info.getAuditLocation().trim().length() !=0) {
stmt.setString(2, info.getAuditLocation());
} else {
stmt.setString(2, info.getAuditUser());
}
return stmt;
}
}, new CallableStatementCallback<Object>() {
public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
return cs.executeUpdate();
}
});
}
}
It is to be noted that the Spring beans are extracted from the context and not autowired - this is because AOP is a singleton class in spring implementation, and none of the autowired beans will be ever instantiated even if they are available in the context. So I had to manually retrieve them for later usage.

JPA entries are not created or retrieved

I'm having program that creates JPA entries with the entity manager.
during the process I don't get any errors.
...
factory = Persistence.createEntityManagerFactory("perst");
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(object);
entityManager.getTransaction().commit();
...
entityManager.close();
I have created a program like follows to read the data but it doesn't return any data,
the query returns empty. What could be the reason ?
This is the program to read the data:
static List<String> classList = new ArrayList<String>();
private static EntityManagerFactory factory;
public static void main(String[] args) {
// TODO Auto-generated method stub
factory = Persistence.createEntityManagerFactory("perst");
EntityManager entityManager = factory.createEntityManager();
classList.add("LeaveRequest");
classList.add("person");
for (Object classOjc : classList) {
String className = classOjc.toString();
Query query = entityManager.createQuery("SELECT p FROM " + className + " p");
#SuppressWarnings("rawtypes")
List resultList = query.getResultList();
System.out.println(resultList.size());
for (Object result : resultList) {
System.out.println(result.toString());
}
}
}
the xml persist is:
<?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="perst" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>LeaveRequest</class>
<class>person</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:derby:/home/vogella/databases/simpleDb;create=true" />
<property name="javax.persistence.jdbc.user" value="Sales" />
<property name="javax.persistence.jdbc.password" value="" />
<!-- EclipseLink should create the database schema automatically -->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
<property name="eclipselink.logging.level" value="SEVERE" />
<property name="eclipselink.logging.exceptions" value="true" />
</properties>
</persistence-unit>
</persistence>
You configured eclipselink to drop and recreate the schema each time the app is started:
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
So obviously, if you run a first application that persists some entries, and then a second application which tries to read what the first one has written, you won't find anything anymore, since eclipselink drops everything and recreates the schema every time.

Categories