How to use EJB 3 with persistence unit on a JBoss AS? - jboss

I have a JBoss AS, and on this server there is a standalone.xml file where there several properties, there are my datasources too, so how combine the datasources in the standalone.xml file with a persistence unit that I want to add to an EJB ?

Just add <jta-data-source>java:/ExampleDS</jta-data-source> providing your datasource jndi-name to the persistence.xml.
Example of Datasource:
<datasource jndi-name="java:/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
Example of persistence.xml referencing datasource ExampleDS:
<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="example">
<jta-data-source>java:/ExampleDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Example injecting Persistence Unit in your EJB3:
#Stateless
public class MyEJB {
#PersistenceContext(unitName="example") protected EntityManager entityManager;
public void createEmployee(String fName, String lName) {
Employee employee = new Employee();
employee.setFirstName(fName);
employee.setLastName(lName);
entityManager.persist(employee);
}
...
}

Related

JPA not generating ddl files

I'm setting up a JavaEE Webapplication and want to generate ddl files so I can see what they look like
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence"
version="2.1">
<persistence-unit name="contentAggregatorPU">
<class>contentAggregator.model.Item</class>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation.scripts.create-target" value="contentAggregatorCreate.ddl"/>
<property name="javax.persistence.schema-generation.scripts.drop-target" value="contentAggregatorDrop.ddl"/>
</properties>
</persistence-unit>
</persistence>
It just does not generate the files.
Honestly I never used the mechanism. While it seems to work for my local-resource minimal JPA playground it gave me errors when attempting to deploy to wildfly. I've always used a small utility class for generating a schema.
public class SchemaTranslator {
public static void main(String[] args) throws IOException {
Class<?>[] entityClasses = {
Class1.class,
Class2.class,
};
MetadataSources metadata = new MetadataSources(new StandardServiceRegistryBuilder()
.applySetting("hibernate.hbm2ddl.auto", "create")
.applySetting("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect")
// .applySetting("hibernate.physical_naming_strategy", "package.MyImprovedNamingStrategy")
.build()
);
// [...] adding annotated classes to metadata here...
for (Class<?> clazz : entityClasses)
metadata.addAnnotatedClass(clazz);
EnumSet<TargetType> targetTypes = EnumSet.of(TargetType.STDOUT, TargetType.SCRIPT);
SchemaExport export = new SchemaExport()
// .setHaltOnError( haltOnError )
.setOutputFile("db-schema.sql")
.setDelimiter(";");
export.create(targetTypes, (MetadataImplementor) metadata.buildMetadata());
}
}

EntityManager in JNDI

I need to use different databases in the same Web application, so I can't use a persistent.xml to define the target database. The database changes with the client which is connected.
I found this :
public EntityManager getEntityManager() {
if (em == null}
try{
em = (EntityManager)(new InitialContext())
.lookup("java:comp/ejb/EntityManager");
} catch (Exception e){};
}
return em;
}
at this URL : http://wiki.eclipse.org/EclipseLink/Examples/JPA/EMAPI
My question is now : how recording a EntityManager or a Persistence Unit in the JNDI of GlassFish ?
Suppose that my persistence.xml is:
<persistence version="2.1" 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">
<persistence-unit name="ctx-vendor" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
</persistence-unit>
</persistence>
We have two use case:
WAR application WEB-INF/web.xml file:
<persistence-context-ref>
<description>JNDI for lookup EntityManager</description>
<persistence-context-ref-name>persistence/ctx-vendor</persistence-context-ref-name>
<persistence-unit-name>ctx-vendor</persistence-unit-name>
<persistence-context-type>Transaction</persistence-context-type>
</persistence-context-ref>
EAR application META-INF/application.xml file:
<application 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/application_7.xsd"
version="7">
<description>My Vendor System</description>
<display-name>vendor-ear</display-name>
<module>
<web>
<web-uri>vendor-rest.war</web-uri>
<context-root>/vendor-rest</context-root>
</web>
</module>
<module>
<ejb>vendor-service.jar</ejb>
</module>
<library-directory>lib</library-directory>
<persistence-context-ref>
<description>JNDI for lookup EntityManager</description>
<persistence-context-ref-name>persistence/ctx-vendor</persistence-context-ref-name>
<persistence-unit-name>ctx-vendor</persistence-unit-name>
<persistence-context-type>Transaction</persistence-context-type>
</persistence-context-ref>
</application>
Stateless Session Bean
#PersistenceContext(name = "persistence/ctx-vendor", unitName = "ctx-vendor")
public class BaseFacade
{ }
#Stateless
#Local(CatalogFacade.class)
public class CatalogFacadeImpl extends BaseFacade implements CatalogFacade
{
}
Tested in Glassfish 4.1

jpa 2.0 not injecting EntityManager

I have a simple implemenation of JPA 2.0 annotations that is not working. This is running in karaf 4.0.5 as a server. Below are listed the relevant excerpts from persistence.xml, blueprint.xml and the class. The exception is listed at the bottom.
The issue is that the EntityManager em is always null. I expected this to be injected by blueprint.
Can anyone point out where I've gone wrong?
Class
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
#Transactional
public class LookupMfgService implements ILookupMfgService {
private static Logger logger = LoggerFactory.getLogger(LookupMfgService.class);
#PersistenceContext(unitName = "pu_motordb3")
private EntityManager em;
#Override
public List<String> getPreferredMfgNames() throws BusinessException {
List<String> list = new ArrayList<>();
try {
// em is null here so NPE thrown
TypedQuery<String> q = em.createNamedQuery("listMfgPreferredNames", String.class);
list = q.getResultList();
} catch (Throwable t) {
logger.error("Error selecting list of manufacturers", t);
throw JpaExceptionFactory.createGeneralError(t, this.getClass().getName());
}
return list;
}
public void setEm(EntityManager entityManager) {
logger.debug(this.getClass().getName() + ".setEntityManager()");
logger.debug("setEntityManager called with " + (entityManager == null ? "null" : entityManager.toString()));
this.em = entityManager;
}
}
DataSource.xml
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 ">
<bean id="dataSource" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
<property name="serverName" value="XXX"/>
<property name="user" value="XXX"/>
<property name="password" value="XXX"/>
<property name="dataSourceName" value="pgConnectionPool"/>
<property name="initialConnections" value="5"/>
<property name="maxConnections" value="50" />
</bean>
<service interface="javax.sql.DataSource" ref="dataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="MotorDB"/>
</service-properties>
</service>
</blueprint>
Blueprint.xml
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v2.0.0" xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0 http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0
http://aries.apache.org/xmlns/transactions/v2.0.0 http://aries.apache.org/xmlns/transactions/v2.0.0
http://aries.apache.org/xmlns/jpa/v2.0.0 http://aries.apache.org/xmlns/jpa/v2.0.0
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
<jpa:enable />
<tx:enable />
<service id="mfgLookupService" ref="mfgLookupEntityImpl" interface="ILookupMfgService"/>
</blueprint>
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_2_0.xsd"
version="2.0">
<persistence-unit name="pu_motordb3" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=MotorDB)</jta-data-source>
Classes listed here
</persistence-unit>
</persistence>
Karaf log
2016-09-01 09:45:48,689 | INFO | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Found persistence unit reference3 in bundle entity with provider org.apache.openjpa.persistence.PersistenceProviderImpl.
2016-09-01 09:45:48,695 | INFO | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Found persistence unit pu_motordb3 in bundle entity with provider org.apache.openjpa.persistence.PersistenceProviderImpl.
2016-09-01 09:45:48,695 | INFO | PersistenceBundleTracker | 90 - org.apache.aries.jpa.container - 2.3.0 | Persistence units added for bundle com.easa.server.entity event 128
Exception
2016-08-31 18:42:49,286 | ERROR | nelWorkerThread0 | LookupMfgService | Error selecting list of manufacturers
java.lang.NullPointerException
at LookupMfgService.getPreferredMfgNames(LookupMfgService.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_91]
at java.lang.reflect.Method.invoke(Method.java:498)[:1.8.0_91]
at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl.handleMessage(ChannelEndpointImpl.java:1265)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]
at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl$2.run(ChannelEndpointImpl.java:315)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]
at ch.ethz.iks.r_osgi.impl.ChannelEndpointImpl$1.run(ChannelEndpointImpl.java:280)[69:ch.ethz.iks.r_osgi.remote:1.0.8.RC1_v20160823-2221]
Your datasource configuration appears to be missing. You are using osgi.jndi.service.name=MotorDB that is nowhere declared. So there is no service implementing javax.sql.DataSource
There has to be something similar to the following example which uses Oracle.
Change accordingly for other DBMS:
...
<bean id="dataSourceBeanMfgLookupService" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="???"/>
<property name="user" value="???"/>
<property name="password" value="???"/>
</bean>
<service id="dataSourceMfgLookupService" interface="javax.sql.DataSource" ref="dataSourceBeanMfgLookupService">
<service-properties>
<entry key="osgi.jndi.service.name" value="MotorDB" />
</service-properties>
</service>
...
Furthermore you may have to specify a persistence-provider in your persistence.xml. If you used hibernate with Oracle 10g it would look somehow like this:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" ...>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
...
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false" />
...
Then you can link your datasource to your service:
<bean id="mfgLookupEntityImpl" class="LookupMfgService">
<jpa:context property="em" unitname="pu_motordb3" />
<tx:transaction method="*" value="Required" />
</bean>
If this still does not inject the EM provide a setter:
public void setEm(EntityManager entityManager) {
this.em = entityManager;
}
AFAIK there was/is a bug that property injection only worked if a setter was available.
The cause was an issue with karaf 4.0.5 and openjpa 2.4.1. It has been resolved in karaf 4.0.6

NamedQuery not found Hibernate4 Seam 2.2 JPA 2.0 and Jboss eap 6

I am receiving the Named Query not found error message on JBOSS EAP 6.3 server. I am using Hibernate4 Seam 2.2 JPA 2.0 and Jboss eap 6 in my application.
Caused by: java.lang.IllegalArgumentException: Named query not found: findOfficerByEmpIDFetchAssigners
at org.hibernate.ejb.AbstractEntityManagerImpl.createNamedQuery(AbstractEntityManagerImpl.java:601) [hibernate-entitymanager-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]
at org.jboss.seam.persistence.EntityManagerProxy.createNamedQuery(EntityManagerProxy.java:46) [jboss-seam-2.2.0.GA.jar:2.2.0.GA]
at com.wachovia.apps.amaster.BatchProcessorBean.getLoggedInUser(BatchProcessorBean.java:68) [amaster-ejb-1.0.jar:]
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_2_0.xsd"
version="2.0">
<persistence-unit name="AccountMaster">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/jdbc/AccountMaster</jta-data-source>
<properties>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.show_sql" value="false"/>
<property name="jboss.entity.manager.jndi.name" value="java:jboss/AmasterEntityManager"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/AmasterEntityManagerFactory"/>
<property name="hibernate.default_schema" value="AMASTER"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.id.new_generator_mappings" value="false"/>
<property name="jboss.as.jpa.managed" value="false"/>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="jboss.as.jpa.adapterModule" value="org.jboss.as.jpa.hibernate:4"/>
<property name="jboss.as.jpa.adapterClass" value="org.jboss.as.jpa.hibernate4.HibernatePersistenceProviderAdaptor"/>
</properties>
My Entity class,
#Entity
#Table(name="OFFICER")
#NamedQueries({
#NamedQuery(name="findOfficerByEmployeeId",
query="from Officer where upper(employeeId)=upper(:id) order by employeeId"),
#NamedQuery(name="findOfficerByEmpIDFetchAssigners",
query="from Officer o left join fetch o.assigners ass where upper(o.employeeId) = :id")
})
public class Officer implements java.io.Serializable {
And Here is my Stateless bean class I am calling the NamedQuery,
#Stateless
#Name("batchProcessor")
#AutoCreate
#TransactionManagement(TransactionManagementType.BEAN)
public class BatchProcessorBean implements BatchProcessor, Serializable {
private static final long serialVersionUID = 395715959808111918L;
#SuppressWarnings("seam-unresolved-variable")
#In(value = "entityManager")
private EntityManager em;
public Officer getLoggedInUser(String employeeID) {
UserTransaction instance = Transaction.instance();
List<Officer> list = em.createNamedQuery("findOfficerByEmpIDFetchAssigners").setParameter("id", employeeID).getResultList();
I placed the persistence.xml in the under ejb/resources/META-INF folder. I have tried the previous posts regarding the NamedQuery Not found issue. That is not fixing my issue
Please help me to figure out the issue. Thanks
I have resolved the issue. I have added the the following class tag in persistence.xml to resolve the issue,
<class>com.wachovia.apps.amaster.orm.Officer</class>
The order of the tags are important in persistence.xml. In my case, this class tag must be added before the <properties> tag and after the <jta-data-source> tag.

Migrating data between two different EntityManager in a RestEasy endpoint

I'm using a RestEasy endpoint to migrate data between an SQL Server database and an Oracle database. I have both datasources defined on JBoss
<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
<datasource jndi-name="java:jboss/datasources/oracleDS"
pool-name="oracle" enabled="true"
use-java-context="true">
<connection-url>jdbc:oracle:thin:#127.0.0.1:1521:XE</connection-url>
<driver>oracle</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
<prefill>true</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>SOURCE</user-name>
<password>source</password>
</security>
</datasource>
<datasource jndi-name="java:jboss/datasources/sqlserverDS" pool-name="sqlserver"
enabled="true" use-java-context="true">
<connection-url>jdbc:sqlserver://localhost:1433;databaseName=DEST</connection-url>
<driver>sqlserver</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
<prefill>true</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<user-name>DEST</user-name>
<password>dest</password>
</security>
</datasource>
</datasources>
My persistence.xml 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="primary">
<jta-data-source>java:jboss/datasources/oracleDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
</properties>
</persistence-unit>
<persistence-unit name="secondary" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/sqlserverDS</jta-data-source>
<class>com.foobar.model.sqlserver.SourceEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
And my RestEasy endpoint
package com.foobar.rest;
import com.foobar.model.DestEntity;
import com.foobar.model.sqlserver.SourceEntity;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
/**
*
* #author Andres
*/
#Stateless
#Path("/endpoint")
public class FoobarEndpoint {
private static final Logger logger = Logger.getLogger(FoobarEndpoint.class);
#PersistenceContext(unitName = "primary")
private EntityManager csEm;
#PersistenceContext(unitName = "secondary")
private EntityManager vhEm;
#GET
#Path("/migration")
public Response migration() {
logger.trace("Starting migration process");
TypedQuery<SourceEntity> sourceQuery = this.vhEm.createNamedQuery("SourceEntity.findAll", SourceEntity.class);
List<SourceEntity> sourcePeriodsList = sourceQuery.getResultList();
this.csEm.createNamedQuery("DestEntity.deleteAll").executeUpdate();
int i = 0;
for (SourceEntity sourcePeriod : sourcePeriodsList) {
DestEntity entity = new DestEntity();
// Set DestEntity fields
entity = this.csEm.merge(entity);
}
return Response.noContent().build();
}
}
The problem arises after I retrieve the data from source and attempt to delete data from the destination, with JBoss giving me this error:
javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffff7f000001:-47dbad9f:53b43ae8:a38 status: ActionStatus.ABORT_ONLY >
Apparently, it attempts to do both operations in the same transaction, and since they come from different servers, it fails to do so.
Any ideas of a workaround?
I couldn't do it the way I wanted to. I ended up querying the source by using plain JDBC and inserting to the destination using JPA.