My entities are not persisting showing javax.persistence.TransactionRequiredException - jpa

I have recently migrated to JPA 2.0 (EclipseLink 2.4.2 Juno) in TomEE 1.7 in Eclipse IDE, As i am storing the values they are getting stored and retrieved fine, but they are not persisting into the database when is use entitymanager.flush()it is showing javax.persistence.TransactionRequiredException Here is my code
Create.java (register method)
public static int register(String first, String last, String email,
String date, String phone, String address, String pin, Login login) {
try {
System.out.println("registering persisting the entity");
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("FirstEE");
EntityManager manager = emf.createEntityManager();
manager.getTransaction().begin();
//
// Query query = manager
// .createQuery("select l from Truck l");
Login log = login;
System.out.println(log.getUsername() + "username"
+ log.getPassword() + "password");
User reg = new User();
reg.setLogin(log);
reg.setDate(date);
reg.setEmail(email);
reg.setFirst(first);
reg.setLast(last);
reg.setPhone(phone);
reg.setAddress(address);
reg.setPin(pin);
manager.persist(reg);
manager.getTransaction().commit();
manager.flush();
manager.close();
emf.close();
// FacesContext.getCurrentInstance().addMessage("reg:result",
// new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error Message",
// "Registered Successfully"));
FacesContext facesContext = FacesContext.getCurrentInstance();
FacesMessage facesMessage = new FacesMessage(
"Registered Successfully");
facesContext.addMessage(null, facesMessage);
System.out.println("after message global");
return 1;
} catch (Exception e) {
System.out.println("hai this is exception caught:" + e);
System.out.println("hai" + e.getMessage());
FacesContext.getCurrentInstance().addMessage(
"reg:result",
new FacesMessage("Something went wrong",
"\tSomething went wrong\t"));
// FacesContext facesContext = FacesContext.getCurrentInstance();
// FacesMessage facesMessage = new
// FacesMessage("Something went wrong");
// facesContext.addMessage(null, facesMessage);
}
return 0;
}
persistence.xml
<?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="FirstEE" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<non-jta-data-source>FirstEE</non-jta-data-source>
<!-- <exclude-unlisted-classes>false</exclude-unlisted-classes> -->
<class>com.jason.Entity.User</class>
<class>com.jason.ManagedBean.Login</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/yash" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="eclipselink.logging.level" value="FINEST" />
<property name="eclipselink.ddl-generation" value="create-tables" />
</properties>
</persistence-unit>
</persistence>
I cant figure out the problem data is getting retreived and stored but it is not updating and not getting persisted in database

The commit()method is committing your transaction immediately. Therefore, the changes are writting into the database & your previously open transaction also ends in this moment. When you call flush() afterwards, there is no open transaction so the flush() operation - complains as you experience it - with a javax.persistence.TransactionRequiredException. See also javax.persistence
Interface EntityManager#flush()
void flush()
Synchronize the persistence context to the underlying database.
Throws:
TransactionRequiredException - if there is no transaction
You should call the commit() method after you synced the state of your EntityManager, like so
manager.getTransaction.begin();
// ...
// do something with your entities in between
// ...
manager.persist(reg);
manager.flush(); // in your case: could also be skipped
// finally - if nothing fails - we are safe to commit
manager.getTransaction().commit();
Another hint:
You should avoid to mix your UI-side code (JSF...) with Backend code. This is generally considered 'spaghetti' anti-pattern here.
Moreover, do not open and close EntityManagerFactory every time (!) you call this UI-bound method (register(...)), as this is a performance killer - at least it produces unnecessary processing every time somebody tries to register here. At least, you should create an instance of EntityManagerFactory (or: EntityManager) as a field (via a DBService class) and reuse this to communicate with the application backend.

The error indicates you cant call flush outside of a transaction. Your code clearly shows you are calling flush right after calling manager.getTransaction().commit(). There is no need to call flush after commit, since the entityManager synchronizes to the database on commit or flush. You only use flush if you have a long running transaction and you want to synchronize at particular stages.
For the rest, turn on EclipseLink logging https://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging and it will show you want it is doing on the commit/flush calls.

Related

No active transaction in EJB #Schedule method

I have an EJB with a #Schedule marked method, that persists an entity to a database. Within this method, when I'm calling EntityManager.flush() after persist(), I'm getting javax.persistence.TransactionRequiredException: No transaction is currently active
AFAIK all EJB methods are transactional, but I'm getting this error even if I additionally mark the method with #TransactionAttribute(REQUIRED).
When I manage a transaction manually by EntityTransaction.begin() and commit(), everything works OK.
I'm using Wildfly 10.0 Final on JDK 8u74, EclipseLink 2.6.0.
Here is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="mainPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/datasources/ExampleDS</jta-data-source>
<class>com.example.MyEntity</class>
</persistence-unit>
</persistence>
MyEJB.java:
package com.example;
import javax.ejb.*;
import javax.ejb.Timer;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Startup
#DependsOn("AppUtils")
#Singleton
public class MyEJB {
#PersistenceContext(unitName = "mainPU")
private EntityManager em;
#Schedule(hour = "*", minute = "*", second = "*/20", info = "", persistent = false)
private void doStuff(Timer timer) {
MyEntity entity = new MyEntity("Test" + Math.random(), "Test value");
em.merge(entity);
em.flush();
}
}
When you use JTA it commit and flush the changes into the database and close the current transaction. So, when you do em.flush(), the transaction is already closed.

JPA persist() method is not doing its job

I am working on a JPA, jsf2.0 Hibernate project. It is a management of the user's actions through a primefaces calendar that you can see here.
I managed to get user's actions and display them in the calendar, but when I want to add a new action it seems to work: I have no error message but in reality the action is not added in database. It seems like the persist method is not doing its job, it is not returning any error message so I don't know what to do to see why.
I put you here the 2 functions for these 2 actions (display and add):
Method to add an action (it does not work)
public void creerAction(Action action){
Date date = action.getDateAction();
action.setDateAction(date);
EntityManagerFactory emf = null;
try{
emf = Persistence.createEntityManagerFactory("GA2010-ejbPU-dev");
em = emf.createEntityManager();
em.persist(action);
FacesMessage message = new FacesMessage("Action " + action.getTexteAction()+ " ajouté avec succès");
FacesContext.getCurrentInstance().addMessage(null, message);
}catch(PersistenceException e){
System.out.println(e.getMessage());
}
}
and the method to get all actions of an user (it works)
public List<Action> getAllAction(){
HttpSession sess = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
String codeUser = (String) sess.getAttribute("codeUser");
EntityManagerFactory emf = null;
try{
emf = Persistence.createEntityManagerFactory("GA2010-ejbPU-dev");
em = emf.createEntityManager();
Query requete = em.createQuery(SELECT_ALL_ACTION);
requete.setParameter("codeUtilisateur", codeUser);
this.allAction= requete.getResultList();
}catch(Exception e){
this.message = new FacesMessage(e.getMessage()) ;
FacesContext.getCurrentInstance().addMessage( null, message );
}
return allAction;
}
And here is the declaration of my unit persistence
<persistence-unit name="GA2010-ejbPU-dev" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>dev</jta-data-source>
<class>entities.Utilisateur</class>
<class>entities.Action</class>
<properties>
<property name="eclipselink.target-server" value="SunAS9"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.ddl-generation.output-mode" value="sql-script"/>
<property name="eclipselink.application-location" value="C:/tmp"/>
</properties>
How can I see why persist does not persist and why I am not having an error message?
Persists need to be done from within a transaction. The object is not persisted until you commit the transaction:
Hibernate EntityManager tutorial

Transaction aware objects in stateless EJB

I'm little confused how transactions work in EJBs. I've always thought that all transaction aware objects in container managed EJBs are all committed or rollbacked when a method with TransactionAttribute=REQUIRED_NEW is finished but unfortunately it's not in my case. I don't have my code in front of me so I can't include whole example but what I ask for is just the confirmation of the idea of how it should work.
Only key points of my code just from the top of my head are presented:
EntityManager em; //injected
[...]
public void someEJBMethod() {
[...]
em.persist(someObject);
[...]
Session session = JpaHelper.getEntityManager(em).getActiveSession();
[...]
session.executeQuery(query, args);
[...]
if (someCondition) {
throw new EJBException();
}
[...]
}
And my problem is that when EJBException is thrown database changes caused by em.persist are rollbacked but changes caused by session.executeQuery are committed.
Is it expected behaviour?
I'm using Glassfish 3.1.2, EclipseLink 2.3.2 with Oracle database
Update (test case added)
I've created working test case to show the problem
First database objects:
create table txtest
(id number not null primary key,
name varchar2(50) not null);
create or replace function txtest_create(p_id number, p_name varchar2) return number is
begin
insert into txtest
(id, name)
values
(p_id, p_name);
return p_id;
end;
Definition of a database connection (from domain.xml)
<jdbc-connection-pool driver-classname="" datasource-classname="oracle.jdbc.pool.OracleConnectionPoolDataSource" res-type="javax.sql.ConnectionPoolDataSource" description="" name="TxTest">
<property name="User" value="rx"></property>
<property name="Password" value="rx"></property>
<property name="URL" value="jdbc:oracle:thin:#test:1529:test"></property>
</jdbc-connection-pool>
<jdbc-resource pool-name="TxTest" description="" jndi-name="jdbc/TxTest"></jdbc-resource>
persistence.xml
<?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="txTest">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/TxTest</jta-data-source>
<class>txtest.TxTest</class>
</persistence-unit>
</persistence>
session bean:
#Stateless
public class TxTestBean implements TxTestBeanRemote, TxTestBeanLocal {
private static Logger log = Logger.getLogger(TxTestBean.class.getName());
#PersistenceContext(unitName="txTest")
EntityManager em;
#SuppressWarnings({ "unchecked", "rawtypes" })
#Override
public void txTest(boolean throwException) {
TxTest t = new TxTest();
t.setId(1L);
t.setName("em.persist");
em.persist(t);
Session session = JpaHelper.getEntityManager(em).getActiveSession();
log.info("session : " + String.valueOf(System.identityHashCode(session)));
PLSQLStoredFunctionCall call = new PLSQLStoredFunctionCall();
call.setProcedureName("txtest_create");
call.addNamedArgument("p_id", JDBCTypes.NUMERIC_TYPE);
call.addNamedArgument("p_name", JDBCTypes.VARCHAR_TYPE, 50);
call.setResult(JDBCTypes.NUMERIC_TYPE);
ValueReadQuery query = new ValueReadQuery();
query.setCall(call);
query.addArgument("p_id");
query.addArgument("p_name");
t = new TxTest();
t.setId(2L);
t.setName("session.executeQuery");
List args = new ArrayList();
args.add(t.getId());
args.add(t.getName());
Long result = ((Number)session.executeQuery(query, args)).longValue();
//added to see the state of txtest table in the database before exception is thrown
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("result=" + result.toString());
if (throwException) {
throw new EJBException("Test error #1");
}
}
}
entries from server.log when txTest(true) is invoked:
[#|2012-05-21T12:04:15.361+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.connection|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|client acquired: 21069550|#]
[#|2012-05-21T12:04:15.362+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.transaction|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|TX binding to tx mgr, status=STATUS_ACTIVE|#]
[#|2012-05-21T12:04:15.362+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.transaction|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|acquire unit of work: 16022663|#]
[#|2012-05-21T12:04:15.362+0200|FINEST|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.transaction|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|persist() operation called on: txtest.TxTest#11b9605.|#]
[#|2012-05-21T12:04:15.363+0200|INFO|glassfish3.1.2|txtest.TxTestBean|_ThreadID=167;_ThreadName=Thread-2;|session : 16022663|#]
[#|2012-05-21T12:04:15.364+0200|FINEST|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.query|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|Execute query ValueReadQuery()|#]
[#|2012-05-21T12:04:15.364+0200|FINEST|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.connection|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|Connection acquired from connection pool [read].|#]
[#|2012-05-21T12:04:15.364+0200|FINEST|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.connection|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|reconnecting to external connection pool|#]
[#|2012-05-21T12:04:15.365+0200|FINE|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.sql|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|
DECLARE
p_id_TARGET NUMERIC := :1;
p_name_TARGET VARCHAR(50) := :2;
RESULT_TARGET NUMERIC;
BEGIN
RESULT_TARGET := txtest_create(p_id=>p_id_TARGET, p_name=>p_name_TARGET);
:3 := RESULT_TARGET;
END;
bind => [:1 => 2, :2 => session.executeQuery, RESULT => :3]|#]
[#|2012-05-21T12:04:15.370+0200|FINEST|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.connection|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|Connection released to connection pool [read].|#]
[#|2012-05-21T12:04:35.372+0200|INFO|glassfish3.1.2|txtest.TxTestBean|_ThreadID=167;_ThreadName=Thread-2;|result=2|#]
[#|2012-05-21T12:04:35.372+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.transaction|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|TX afterCompletion callback, status=ROLLEDBACK|#]
[#|2012-05-21T12:04:35.372+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.transaction|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|release unit of work|#]
[#|2012-05-21T12:04:35.372+0200|FINER|glassfish3.1.2|org.eclipse.persistence.session.file://txTest/_txTest.connection|_ThreadID=167;_ThreadName=Thread-2;ClassName=null;MethodName=null;|client released|#]
[#|2012-05-21T12:04:35.373+0200|WARNING|glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=167;_ThreadName=Thread-2;|EJB5184:A system exception occurred during an invocation on EJB TxTestBean, method: public void txtest.TxTestBean.txTest(boolean)|#]
[#|2012-05-21T12:04:35.373+0200|WARNING|glassfish3.1.2|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=167;_ThreadName=Thread-2;|javax.ejb.EJBException: Test error #1
What surprised me the most is that when I checked txtest table during this 20 sec. sleep the record (2,"session.executeQuery") was already there.
It seems like session.executeQuery somehow commits its work (but not the whole transaction).
Can someone explain this behaviour?
I'm not sure what JpaHelper.getEntityManager(em).getActiveSession(); is supposed to do exactly, but it seems likely this doesn't return a container managed entity manager. Depending on how it's exactly implemented, this may not participate in the ongoing (JTA) transaction.
Normally though, transactional resources all automatically participate in the ongoing JTA transaction. In broad lines they do this by checking if there's such on ongoing transaction, and if there indeed is, they register themselves with this transaction.
In EJB, REQUIRES_NEW is not the only mode that can start a transaction 'REQUIRES' (the default) also does this incase the client didn't start a transaction.
I've got it solved!!!
It turned out that EclipseLink uses read connection pools for processing read queries (and obviously that kind of pools uses autocommit or even don't use transactions at all) and default connection pools for data modification queries. So what I had to do was changing:
ValueReadQuery query = new ValueReadQuery();
into
DataModifyQuery query = new DataModifyQuery();
and it works like a charm.
Update
DataModifyQuery doesn't allow to get the result of the function. It returns the number of modified rows. So I got back to ValueReadQuery but used configuration parameter in persistance.xml
<property name="eclipselink.jdbc.exclusive-connection.mode" value="Always"/>
This parameter tells EclipseLink to use default connection pool for both reads and writes.

Dynamic datasource lookup using JPA

I want to bind variable dataSourceString(possible value:HR,FINANCE : i am getting dataSourceString value dynamically by jsp) to DataSource. When dataSourceString value is HR then connect to TESTDS and when dataSourceString value is FINANCE then connect to TESTDS1.Means based on dataSourceString value i want to connect to datasource.
Enviornment : EJB3,weblogic10.3.3,JPA
Note:One more thing i dont want to write if-else loop in sessionbean like when dataSourceString is HR then connect to this EnityManage else to different EntityManager.currently there are 10-15 possible value of dataSourceString. I want to write code like if in future if a new dataSourceString is added then only i have to change persistence.xml.
After research i came to the following code,But getting some error.
Error:-
No persistence unit named 'em' is available in scope test.jar. Available persistence units: [HR, FINANCE]
at weblogic.ejb.container.deployer.EJBModule.prepare(EJBModule.java:467)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:199)
at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:507)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:41)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:149)
Truncated. see log file for complete stacktrace
Caused By: java.lang.IllegalArgumentException: No persistence unit named 'em' is available in scope test.jar. Available persistence units: [HR, FINANCE]
at weblogic.deployment.ModulePersistenceUnitRegistry.getPersistenceUnit(ModulePersistenceUnitRegistry.java:132)
at weblogic.deployment.BasePersistenceContextProxyImpl.<init>(BasePersistenceContextProxyImpl.java:38)
at weblogic.deployment.TransactionalEntityManagerProxyImpl.<init>(TransactionalEntityManagerProxyImpl.java:35)
at weblogic.deployment.BaseEnvironmentBuilder.createPersistenceContextProxy(BaseEnvironmentBuilder.java:974)
at weblogic.deployment.BaseEnvironmentBuilder.addPersistenceContextRefs(BaseEnvironmentBuilder.java:855)
Truncated. see log file for complete stacktrace
Error is obvious that there is no persistence unit for em is available in persistence.xml
But how can i achieve lookup of datasource using jpa dynamically.
Following is my code
Session Bean
package entity.library;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import java.io.Serializable;
import javax.ejb.*;
#Remote(TestInterface.class)
#Stateless(mappedName="ejb3/TestBeans")
public class TestSessionBean implements Serializable, TestInterface
{
protected TestJPA test;
protected Collection <TestJPA> list;
#PersistenceContext
private EntityManager em;
#PersistenceUnit
private EntityManagerFactory emf;
public Collection <TestJPA> getAllList(String dataSourceString) {
emf = Persistence.createEntityManagerFactory(dataSourceString);
em = emf.createEntityManager();
list=em.createQuery("SELECT test FROM TestJPA test").getResultList();
return list;
}
}
persistence.xml
<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="HR" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>TESTDS</jta-data-source>
<non-jta-data-source>TESTDS</non-jta-data-source>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
<persistence-unit name="FINANCE" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>TESTDS1</jta-data-source>
<non-jta-data-source>TESTDS1</non-jta-data-source>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>
If there is a single persistence unit defined in persistence.xml, then it default unit for application & the same is is injected by annotation.
You can lookup manually the specific persistence context at runtime.
javax.persistence.EntityManager entityManager =
(javax.persistence.EntityManager)initCtx.lookup(
"java:comp/env/" + persistenceContext);
Even better...
Instead of:
#PersistenceContext(name="myPU")
private EntityManager em;
specify:
#PeristenceContext(unitName="myPU")
private EntityManager em;

Lookup multiple datasource in ejb3.0

I am looking up multiple datasource, depending an value of x In EJB 3.0.
To do this I have written following code.
Session Bean
package entity.library;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.io.Serializable;
import javax.ejb.*;
#Remote(TestInterface.class)
#Stateless(mappedName="ejb3/TestBeans")
public class TestSessionBean implements Serializable, TestInterface {
/**
*
*/
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName="EntityBeanDS1")
EntityManager emds1;
#PersistenceContext(unitName="EntityBeanDS2")
EntityManager emds2;
protected TestJPA test;
protected Collection <TestJPA> list;
public Collection <TestJPA> getAllList(int x) {
System.out.println("TestInterface.java:getAllPmns x "+x);
if(x==1)
{
System.out.println("going to lookup datasource1");
list=emds1.createQuery("SELECT test FROM TestJPA test").getResultList();
}
else if(x==2)
{
System.out.println("going to lookup datasource2");
list=emds2.createQuery("SELECT test FROM TestJPA test").getResultList();
}
return list;
}
}
Persitence.xml
<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="EntityBeanDS1" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>TESTDS</jta-data-source>
<non-jta-data-source>TESTDS</non-jta-data-source>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
<persistence-unit name="EntityBeanDS2" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>TESTDS1</jta-data-source>
<non-jta-data-source>TESTDS1</non-jta-data-source>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>
Above code is working successfully.but i think this is not a good tech for following reasons.
1. There are 10-15 multiple session beans, in each bean i have to write if-else for lookup of datasource.
2. In future if new data source is added or any newvalue of x is added, then i have to modify all 10-15 files.
Can one give me code , for connecting to multiple data source such that i change a single file for any change in value of x.
How that single file will look like so that i can retrieve 'EntityManager' object. or there is any other method (like modification in persistence.xml) to do this?
You could inject both entity managers into another session bean (QueryBean) and inject QueryBean into your session beans instead of the entity managers themselves. Then delegate the query creation to QueryBean. This bean then decides which entity manager to use depending on the value of x.
When adding another entity manager or a new value of x you just have to adjust QueryBean.