how to set UserTransaction Eclipselink/Glassfish in multitenancy web-app - jpa

i spend a lot of time arround this question my project deals with WEB-APP/multitenancy
Eclipselink
Glassfish v4.1
Persistence Usage for Multiple Tenants : Persistence Unit per Tenant (according to eclipselink docs : Persistence Usage for Multiple Tenants
the persistence.xml si set as follow :
<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="myPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/mydata</jta-data-source>
<mapping-file>META-INF/eclipselink-orm.xml</mapping-file>
<class>...</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.multitenant.tenants-share-cache" value="false" />
<property name="eclipselink.exclude-eclipselink-orm" value="false"/>
<property name="objectdb.query-language" value="JPA" />
<property name="javax.persistence.lock.timeout" value="5000" />
</properties>
</persistence-unit>
</persistence>
inside a listener i put every new created EntityManagerFactory per tenant in a MAP and i call a static method to obtain an entity manager when needed
public static EntityManager createEntityManager(String tenant){
if(mapEMF.containsKey(tenant)){
return mapEMF.get(tenant).createEntityManager();
}else{
HashMap<String, String> properties = new HashMap<>();
properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant);
properties.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, "false");
properties.put(PersistenceUnitProperties.SESSION_NAME, tenant);
properties.put(PersistenceUnitProperties.CONNECTION_POOL_USER, "dbuser");
properties.put(PersistenceUnitProperties.CONNECTION_POOL_PASSWORD, "dbpass");
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, properties);
mapEMF.put(tenant, emf);
return emf.createEntityManager();
}
}
my big question is how to obtain a transaction !
i have used but with no success
#Resource UserTransaction trasaction;
have created UserTransaction
transaction = (UserTransaction)new
InitialContext().lookup("java:comp/UserTransaction");
with em.joinTransaction();
the only method that works is em.getTransaction.begin()/em.getTransaction.commit();
but according the API/docs getTransaction is used in RESOURCE_LOCAL witch is not recommended for java ee web-app where we are called to use JTA as transaction type
Please HELP.

Related

database access from a jar inside ear

In an ear-file I have a persistence-unit for managing entities inside that ear which works fine. Additionally, there is a commons jar-file located in APP-INF/lib which is a dependency in other ears as well (other ear-modules on the same level). In this commons-jar I would like to have a single entity and create the possibility for CRUD on that entity. Now it is a jar only with an additional persistence unit (but same db as for the ear) and I can't manage to set it all up. Would that persistence unit be managed as well by the container? Could I use EJBs inside that jar file as well? Is it possible at all to do what I want?
I created the entity as follows
#Entity
public class ConfigEntity {
#Id
private Long id;
#Version
private Long version;
[further fields, getters and setters omitted]
}
With the following "Dao" I try to call isEntityManagerNull from a bean inside the ear.
public class ConfigBEDao {
#PersistenceContext(unitName = "configurationPU")
EntityManager entityManager;
public boolean isEntityManagerNull() {
return entityManager == null;
}
}
persistence.xml
<?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 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="configurationPU" transaction-type="RESOURCE_LOCAL">
<description/>
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/db</jta-data-source>
<properties>
<property name="eclipselink.target-database" value="${database.dialect}"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>
From a bean inside the ear file I call
ConfigBEDao dao = new ConfigBEDao();
dao.isEntityManagerNull();
which gives me the following exception already when trying to deploy on the server (payara):
java.lang.RuntimeException: Could not resolve a persistence unit corresponding to the persistence-context-ref-name [ConfigBEDao/entityManager] in the scope of the module called [main_ear-1.0-SNAPSHOT#main_ejb-1.0-SNAPSHOT.jar]. Please verify your application.
at com.sun.enterprise.deployment.BundleDescriptor.findReferencedPUViaEMRef(BundleDescriptor.java:733)
at org.glassfish.ejb.deployment.descriptor.EjbBundleDescriptorImpl.findReferencedPUs(EjbBundleDescriptorImpl.java:889)
at org.glassfish.persistence.jpa.JPADeployer.createEMFs(JPADeployer.java:186)
at org.glassfish.persistence.jpa.JPADeployer.prepare(JPADeployer.java:168)
Then I changed the persistence.xml as follows but that didn't work either although the application can be deployed:
<?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 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="configurationPU" transaction-type="RESOURCE_LOCAL">
<description/>
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/db"/>
<property name="javax.persistence.jdbc.user" value="db"/>
<property name="javax.persistence.jdbc.password" value="secret"/>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
</properties>
</persistence-unit>
</persistence>
which gave me
javax.persistence.PersistenceException: No Persistence provider for EntityManager named configurationPU
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)

How do I get my project to use a container managed Enitymanager lifecycle rather an Application managed one?

I've been at this for a while - hoping to get some help. The first persistence.xml gives the output below it. The alternate persistence.xml crashes with: javax.persistence.PersistenceException: No Persistence provider for EntityManager named com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU Please let me know if there's anything I can ad to make this clearer.
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
#Stateless
public class NewClass {
#PersistenceContext(unitName ="com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU")
static EntityManager containerManagedEntityManager;
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(
"com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU");
EntityManager applicationManagedEntityManager = emf.createEntityManager();
System.out.println("Container managed entityManager: "+containerManagedEntityManager);
System.out.println( "Application managed entityManager: " +applicationManagedEntityManager);
}
}
The output:
[EL Info]: 2016-08-16 01:51:13.395--ServerSession(33510911)--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[EL Info]: connection: 2016-08-16 01:51:13.535--ServerSession(33510911)--file:/Users/me/NetBeansProjects/mavenproject1/target/classes/_com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU login successful
[EL Warning]: metamodel: 2016-08-16 01:51:13.552--The collection of metamodel types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units. Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element
Container managed entityManager: null
Application managed entityManager: org.eclipse.persistence.internal.jpa.EntityManagerImpl#6f139fc9
My persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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="com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/nutrition_DB"/>
<property name="javax.persistence.jdbc.user" value="app"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.password" value="pass"/>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
Alternate persistence.xml:
<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="persistenceUnit" transaction-type="JTA">
<jta-data-source>jdbc/dataSource</jta-data-source>
<class>test.domain.TestEntity</class>
</persistence-unit>
</persistence>
In order to have a container-managed entity manager, your should use the Java Transaction API (JTA) instead of RESOURCE_LOCAL. The different between them are :
JTA means the persistence is managed by the application server
RESOURCE_LOCAL means the persistence is managed by yourself.
You can see more difference for Persistence unit as RESOURCE_LOCAL or JTA?
So in your case, I suggest you to do the following :
Make sure you're in a Java EE environment, e.g. Tomcat, WildFly and not a Java SE.
Modify your PU com.topcat_mavenproject1_jar_1.0-SNAPSHOTPU, set transaction-type="JTA"
Make sure that your JTA data source (DS) is configured in the server and activated
Describe this data source in your persistence XML in tag jta-data-source
Inject the EntityManager into you java class using PersistenceContext as you've done. Since the persistence is managed by the application server, do not use entity manager factory anymore except you know exactly what you're doing.
However, it seems that you're under the Java SE environment. In the case, there isn't any Java EE container (application server). And therefore, you cannot benefit the JTA configuration :( You must use RESOURCE_LOCAL mode and manage everything yourself.

Container-managed EntityManger is null on Injection

I'm nearly new to JavaEE (JRE7/JDK1.7.0) and startet my first (maven based) Project on Eclipse (Luna).
Applicationserver is JBoss EAP 6.2.0.GA (AS 7.3.0.Final-redhat-14) which I updated to JSF2.2 by adding jsf-api-2.2.7.jar and jsf-impl-2.2.7.jar and registering in module.xml - which works perfect, by the way.
The problem/question is, why can't I get the EntityManager from the container (AS) with Injection, with following code in my Project:
#Stateless
public class SCatRep {
#PersistenceContext
EntityManager em;
private ...
*In persistence.xml there is only one persistenceunit defined. So no further arguments are necessary ... in my opinion?!
On the other hand, when I try to get the EntityManager from container with a lookup, the EntityManager is present and everything works fine. I used this code (for testing):
#Stateless
#PersistenceContext(unitName="scha", name="persistence/em")
public class SCatRep {
EntityManager em;
public SCatRep() {
try {
Context ic = new InitialContext();
em = (EntityManager) ic.lookup("java:comp/env/persistence/em");
} catch (NamingException e) {
e.printStackTrace();
}
}
I read a lot forums and tutorials - because this behaviour is discussed a lot - but can't get a solution or answer. Hope somebody can help me and point me to the right direction.
Thanks in advance.
EDIT:
I'm using EJB 3.1. And here is the persistence.xml:
<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="scha" transaction-type="JTA">
<jta-data-source>java:/scha_jndi</jta-data-source>
<properties>
<!-- SQL dialect -->
<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class" value="thread" />
<!-- Echo all executed SQL to stdout -->
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
Thanks for help.
I tried to access the EntityManager in constructor ... which is not possible, due to the initializationprocess.
Now I put the Initial loading (databaseaccess) in a #PostConstruct-annotated method and this works perfectly.

How to use 2 PersistenceUnits in one Persistence.xml in a JavaEE application?

I am trying to access 2 different tables in my database.
Initially my persistence.xml was as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="Persistence">
<jta-data-source>jdbc/classicmodels</jta-data-source>
<class>com.tugay.maythirty.model.Customers</class>
<class>com.tugay.maythirty.model.Products</class>
<class>com.tugay.maythirty.model.Employee</class>
<class>com.tugay.maythirty.model.Office</class>
</persistence-unit>
</persistence>
So I defined a DataSource in Glassfish following this great artical and my application was working fine. I was using #PersistenceContext annotation in my DAO classes with name="Persistence"
This basically is connected to a table called "classicmodels".
Then I needed to fetch some data from a table called "sakila". I added these lines to my persistence.xml:
<persistence-unit name="sakila">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.tugay.maythirty.model.Actor</class>
<class>com.tugay.maythirty.model.Film</class>
<class>com.tugay.maythirty.model.FilmActor</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sakila"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="password"/>
</properties>
</persistence-unit>
And I have used this code in my DAO:
public List<Actor> getAllActors(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("sakila");
EntityManager em = emf.createEntityManager();
TypedQuery<Actor> actorTypedQuery = em.createQuery("Select a from Actor a",Actor.class);
return actorTypedQuery.getResultList();
}
When I deploy my application to GlassFish however I started getting this Exception:
java.lang.RuntimeException: Could not resolve a persistence unit corresponding to the persistence-context-ref-name [Persistence] in the scope of the module called [may-thrity]. Please verify your application.
So it seems that now my Persistence Unit with name "Persistence" is gone.
What is it that I am doing wrong?
Have you tried explicitly declaring your persistence unit with
#PersistenceContext(unitName="Persistence")
instead of
#PersistenceContext(name="Persistence")
PersistenceContext doc

Basic Standalone JPA example with Postgres using Eclipse

I have been trying to get a very basic standalone JPA example to work with Postgres using the Eclipse IDE.
I have a persistance.xml defined which looks like this.
<?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="sample" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>package.class</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="INFO" />
<property name="eclipselink.jdbc.driver" value="org.postgresql.Driver" />
<property name="eclipselink.jdbc.url"
value="jdbc:postgresql://localhost:5432/sample" />
<property name="eclipselink.jdbc.user" value="scott" />
<property name="eclipselink.jdbc.password" value="tiger" />
</properties>
</persistence-unit>
</persistence>
This file lives in the src/main/resources/META-INF folder. I have included the src/main/resources folder to my source directory in eclipse. I have one simple Entity defined named User. When I try and create that entity
EntityManagerFactory entityManagerFactory
= Persistence.createEntityManagerFactory("sample");
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
User user = new User();
user.setEnabled(false);
user.setEmailId("test#test.com");
tx.begin();
em.persist(user);
tx.commit();
} catch (Exception e) {
em.getTransaction().rollback();
} finally {
em.close();
}
I get the following exception - Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named sample
It seems like my persistance.xml file is not being picked up. Where does the JPA framework look to load the persistance.xml file?
This was a dumb mistake. The file needs to called persistence.xml and not persistance.xml.