Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » UnitOfWork.beginEarlyTransaction not having expected effect(In the case of a Distributed Transaction, UnitOfWork.beginEarlyTransaction is tried to allow reads of updates in another transaction branch before anything is written to the database)
UnitOfWork.beginEarlyTransaction not having expected effect [message #662879] Fri, 01 April 2011 10:58 Go to next message
J F is currently offline J FFriend
Messages: 256
Registered: July 2009
Senior Member
I'm afraid another question on the behaviour of EclipseLink in a Distributed Transactional non clustered environment.
We are using these test cases to try and understand how things happen at runtime, please bear with us.

In the ELUG at http://wiki.eclipse.org/Using_Advanced_Unit_of_Work_API_%28E LUG%29#Reading_Through_the_Write_Connection
it specifies 3 mechanisms to get something to "read from the write connection".

I have a deployment that consists of an JEE 6 EAR using JPA and eclipselink as the JPA provider.
The EAR is running under Eclipselink 2.2 and JDK1.6b24 on glassfish 3.1 under Windows Server 2008R2

The EAR is deployed across 2 non clustered boxes. Both PUs point to the same Oracle 11gR2 database instance.

The peristence.xml is as follows;

<?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" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="ExperimentjndiPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>ExperimentOra</jta-data-source>
<properties>
<property name="eclipselink.session.customizer" value="uk.co.his.experiment.eclipselink.Customizer"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.session" value="true"/>
<property name="eclipselink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>


ExperimentOra is a JDBC Resource whose Resource Pool is of type javax.sql.XADataSource with a DataSource class of oracle.jdbc.xa.client.OracleXADataSource
The pool was set up using the AdminConsole wizard, here is the xml from domain.xml;

<jdbc-connection-pool driver-classname="" datasource-classname="oracle.jdbc.xa.client.OracleXADataSource" res-type="javax.sql.XADataSource" description="" name="oracle_ExperimentPool" ping="true">
<property name="internal_logon" value="sysdba"/>
<property name="User" value="xxxx"/>
<property name="DatabaseName" value="orcl"/>
<property name="Password" value="xxxx"/>
<property name="DataSourceName" value="OracleXADataSource"/>
<property name="ServerName" value="lil"/>
<property name="ExplicitCachingEnabled" value="false"/>
<property name="MaxStatements" value="0"/>
<property name="NativeXA" value="false"/>
<property name="NetworkProtocol" value="tcp"/>
<property name="ImplicitCachingEnabled" value="false"/>
<property name="PortNumber" value="1521"/>
<property name="LoginTimeout" value="0"/>
<property name="URL" value="jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl"/>
</jdbc-connection-pool>
<jdbc-resource pool-name="oracle_ExperimentPool" description="" jndi-name="ExperimentOra"/>
</resources>


In the AdminConsole GUI I note the following;

TransactionIsolation level is Oracle default.
Allow Non Component Callers is false

The test consists of 2 EARs both running on 2 boxes lil and liepa, the single db instance is on lil.
The flassfishs are not clustered.

The first EAR 'Experiment' consists of a web app which contains a servlet which runs the tests and two EJBs A and B which both share the same Entity class(es)

@Entity
public class Person {
	@Id
	private String id;
	
	private String name;
	
	
	public static Person createNewInstance()
	{
		Person p = new Person();
		p.setIdFromUUID();
		return p;
	}
	
	@ElementCollection
	private List<String> comments = new ArrayList<String>();

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	public void setIdFromUUID()
	{
		id = java.util.UUID.randomUUID().toString();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public void addComment(String comment)
	{
		comments.add(comment);
	}
	
	public List<String> getComments()
	{
		return Collections.unmodifiableList(comments);
	}

	@Override
	public String toString() {
		@SuppressWarnings("unused")
		String superRes = super.toString();
		StringBuilder str = new StringBuilder();
		str.append("id: " + id + ", ");
		str.append("name: " + name + ", ");
		str.append("comments: \n");
		for (String comment : comments) {
			str.append("\tcomment: " + comment + "\n");
		}
		return str.toString();
	}
	
}


The customizer is trivial;

package uk.co.his.experiment.eclipselink;

...imports deleted

public class Customizer implements org.eclipse.persistence.config.SessionCustomizer {
	
	public Customizer()
	{
		System.err.println("The Customizer has been started");
	}

	@Override
	public void customize(Session session) throws Exception {
		System.err.println("Customize a " + session);
		System.err.println("Customize session called " + session.getName());
	}

}


Bean A is as follows

package uk.co.his.experiment;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.SystemException;


/**
 * Session Bean implementation class BeanA
 */
@Stateless(mappedName = "BeanA")
@LocalBean
public class BeanA implements BeanARemote {

	@PersistenceContext(name="ExperimentjndiPU")
	EntityManager em;
	
	/*@Resource(mappedName="java:appserver/TransactionManager") //java:appserver/TransactionManager"
	private TransactionManager txManager;*/
	
    /**
     * Default constructor. 
     */
    public BeanA() {
        // TODO Auto-generated constructor stub
    }


	private String getContextInfo() throws SystemException
	{
		StringBuilder str = new StringBuilder();
		str.append("Thread: " + Thread.currentThread().getName() + ":" + Thread.currentThread().getId() + "\n");
		str.append("EntityManager delegate: " + em.getDelegate() + "\n");
		return str.toString();
	}

	private static final boolean useEclipseLinkBeginEarly = true;
	@SuppressWarnings("unused")
	@Override
	public void function3(boolean writeBeforeReading) throws NamingException, SystemException {
		System.out.println("Entering BeanA::function3:\n"  + getContextInfo() + "\n" );


		
		String hostname = "Unknown";
		try {
			hostname = InetAddress.getLocalHost().getCanonicalHostName();
		} catch (UnknownHostException e) {
		}
		
		if(writeBeforeReading)
		{
			Person p = Person.createNewInstance();
			p.setName("Created in A function 3 on " + hostname);
			p.addComment("Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function");
			em.persist(p);
			em.flush();
		}
		
		
		String people = getPeople(em);
		System.out.println("People in BeanA function3:");
		System.out.println(people);
		
		Person p2 = Person.createNewInstance();
		p2.setName("Created in A function 3 on " + hostname);
		if(writeBeforeReading )
		{
			p2.addComment("Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function");
		}
		else
		{
			p2.addComment("Normally called inside the same EAR running on a DIFFERENT box");
		}
		em.persist(p2);
		em.flush();

		System.out.println("Exiting BeanA::function3:\n"  + getContextInfo() + "\n" );
	}
	
	private String getPeople(EntityManager em)
	{
		StringBuilder str = new StringBuilder();
		TypedQuery<Person> q = em.createQuery("select x from Person x", Person.class);
		//!!Commented Out....q.setLockMode(LockModeType.PESSIMISTIC_READ); !!
		List<Person> results = q.getResultList();
		for (Person person : results) {
			str.append("Found Person " + person + "\n");
		}
		if(results.isEmpty())
		{
			str.append("Nobody was found");
		}
		return str.toString();
	}

}



Bean B is as follows;

package uk.co.his.experiment;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.transaction.SystemException;

import uk.co.his.experiment2.BeanXRemote;
import uk.co.his.experiment2.BeanYRemote;

/**
 * Session Bean implementation class BeanB
 */
@Stateless(mappedName = "BeanB")
@LocalBean
public class BeanB implements BeanBRemote {

	@PersistenceContext(name="ExperimentjndiPU")
	EntityManager em;
	

	@EJB(mappedName="BeanX")
    private BeanXRemote beanX;
	

    /**
     * Default constructor. 
     */
    public BeanB() {
        // TODO Auto-generated constructor stub
    }

	@Override
	public void function5(boolean writeBeforeReading) throws NamingException, SystemException
	{
		String hostname = "Unknown";
		try {
			hostname = InetAddress.getLocalHost().getCanonicalHostName();
		} catch (UnknownHostException e) {
		}

		System.out.println("BeanB function5 start");
		
		
		Person p = Person.createNewInstance();
		p.setName("Created in B function 5 on " + hostname);
		p.addComment("The only person created directly in the 'controller' bean");
		em.persist(p);
		em.flush();
		{
			String str = getPeople(em);
			System.out.println("People in BeanB function5 before calling X");
			System.out.println(str);
			System.out.println("end get people before calling X");
		}

		System.out.println("Calling X locally");
		try
		{
			beanX.functionXR(writeBeforeReading);
		}
		finally
		{
			System.out.println("Called X locally");
		}
		try
		{
			String str = getPeople(em);
			System.out.println("People in BeanB function5 after first X call - expect " + (writeBeforeReading?"two":"one") + " person from liepa");
			System.out.println(str);
			System.out.println("end get people");
		}
		finally
		{

			System.out.println("BeanB function5 getPeople 1");
		}
		
		System.out.println("Calling X locally 2");
		try
		{
			beanX.functionXR(writeBeforeReading);
		}
		finally
		{
			System.out.println("Called X locally 2");
		}
		try
		{
			String str = getPeople(em);
			System.out.println("People in BeanB function5 final - expect " + (writeBeforeReading?"four":"two") + " people from liepa");
			System.out.println(str);
			System.out.println("end get people");
		}
		finally
		{

			System.out.println("BeanB function5 end");
		}
	}
	
	private String getPeople(EntityManager em)
	{
		StringBuilder str = new StringBuilder();
		TypedQuery<Person> q = em.createQuery("select x from Person x", Person.class);
		List<Person> results = q.getResultList();
		for (Person person : results) {
			str.append("Found Person " + person + "\n");
		}
		if(results.isEmpty())
		{
			str.append("Nobody was found");
		}
		return str.toString();
	}
}


The servlet in the web-app in EAR 'Experiment' merely serves to call BeanB function5;

@EJB(mappedName="BeanB")
	private BeanBRemote beanBr;

	private void test18() throws NamingException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException {
		System.out.println("ControllerServlet test18 start");
		try
		{
			beanBr.function5(false);
			System.out.println("ControllerServlet BeanB function5 called");
		}
		finally
		{
			System.out.println("ControllerServlet test18 end");
		}
	}
	
	private void test19() throws NamingException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException {
		System.out.println("ControllerServlet test18 start");
		try
		{
			beanBr.function5(true);
			System.out.println("ControllerServlet BeanB function5 called");
		}
		finally
		{
			System.out.println("ControllerServlet test18 end");
		}
	}


The second EAR 'Experiment2' consists of one EJB BeanX which merely calls back into Experiment Bean A on a different box.

package uk.co.his.experiment2;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.SystemException;

import uk.co.his.experiment.BeanARemote;

/**
 * Session Bean implementation class BeanX
 */
@Stateless(mappedName = "BeanX")
@LocalBean
public class BeanX implements BeanXRemote {

        @EJB(mappedName="corbaname:iiop:liepa:3700#BeanA")
    private BeanARemote beanAr;
	/**
     * Default constructor. 
     */
    public BeanX() {
        // TODO Auto-generated constructor stub
    }


	@Override
	public void functionXR(boolean writeBeforeReading) throws NamingException, SystemException {
		System.out.println("Calling A on liepa!");
		beanAr.function3(writeBeforeReading);
		System.out.println("Called A on liepa!");
	}
}


The tests are as follows

Servlet test18 called on lil;

Bean B function5 called with false on lil.
This creates and persists a single Person in the ExperimentjndiPU.
It also flushes the EM and the persistence.xml is set to <property name="eclipselink.cache.shared.default" value="false"/> so the L2 cache should not be being used.
so this person should be visible within the same Global Transaction on any box using standard JDBC/SQL. ( We switched to Oracle to achieve this, it seems that Derby does not do tightly coupled transaction branches )
It then calls BeanX functionXR on lil which
Calls function3 on BeanA on liepa
This does a query for any people to see if it can see what was created in BeanB. Again eclipselink.cache.shared.default=false and anyway this is a query to the db
It then creates and persists a new person and flushes the EM before returning, so this person should be visible within the
function3 on liepa::BeanA returns to lil:BeanX funtionXR which then returns back to lil:BeanB
BeanB then queries the DB to get all people and see if it can see the person created by BeanA on liepa as well as the person it last created.
Bean B then calls functionXR a second time and repeats the exercise.
It then calls BeanX functionXR on lil which
Calls function3 on BeanA on liepa
This does a query for any people to see if it can see what was created in BeanB. Again eclipselink.cache.shared.default=false and anyway this is a query to the db
It then creates and persists a new person and flushes the EM before returning, so this person should be visible within the
function3 on liepa::BeanA returns to lil:BeanX funtionXR which then returns back to lil:BeanB
BeanB then queries the DB to get all people and see if it can see the person created by BeanA on liepa as well as the person it last created.


Servlet test19 called on lil;

This does the same test with the difference that liepa::BeanA::function3 inserts a Person into the db before querying the db for all the people.
In other words it does a WRITE before READING.

Before the tests I drop and recreate the database. I stop and start both glassfish instances before doing each tests


Here are the (slightly edited) traces


Test18 on lil

INFO: ControllerServlet test18 start

INFO: BeanB function5 start
INFO: uk.co.his.experiment.Person actually got transformed
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolv er.

SEVERE: The Customizer has been started
SEVERE: Customize session called file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU


INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913

FINE: Detected Vendor platform: org.eclipse.persistence.platform.database.oracle.Oracle10Pla tform
CONFIG: connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
CONFIG: connecting(DatabaseLogin(
platform=>OraclePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
INFO: file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU login successful
FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]

FINE: SELECT ID, NAME FROM PERSON
INFO: People in BeanB function5 before calling X
INFO: Found Person id: de42f641-7869-4bb8-978b-cff1ab1ed2d5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean


INFO: end get people before calling X
INFO: Calling X locally
INFO: Calling A on liepa!

INFO: Called A on liepa!
INFO: Called X locally
FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanB function5 after first X call - expect one person from liepa
INFO: Found Person id: d76c5baa-9619-4d40-869f-93a3a72e44c2, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box
Found Person id: de42f641-7869-4bb8-978b-cff1ab1ed2d5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

INFO: end get people
INFO: BeanB function5 getPeople 1
INFO: Calling X locally 2
INFO: Calling A on liepa!
INFO: Called A on liepa!
INFO: Called X locally 2
FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanB function5 final - expect two people from liepa
INFO: Found Person id: d76c5baa-9619-4d40-869f-93a3a72e44c2, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box
Found Person id: b7fe9735-524a-4aa6-b783-a3040d445251, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box
Found Person id: de42f641-7869-4bb8-978b-cff1ab1ed2d5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

INFO: end get people
INFO: BeanB function5 end
INFO: ControllerServlet BeanB function5 called
INFO: ControllerServlet test18 end


Test18 on liepa

INFO: uk.co.his.experiment.Person actually got transformed
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolv er.
SEVERE: The Customizer has been started
SEVERE: Customize session called file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU

INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913

FINE: Detected Vendor platform: org.eclipse.persistence.platform.database.oracle.Oracle10Pla tform
CONFIG: connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
CONFIG: connecting(DatabaseLogin(
platform=>OraclePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
INFO: file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU login successful




INFO: Entering BeanA::function3:
Thread: p: thread-pool-1; w: 5:88
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@4c885c

FINE: SELECT ID, NAME FROM PERSON
INFO: People in BeanA function3:
INFO: Nobody was found


FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]

INFO: Exiting BeanA::function3:
Thread: p: thread-pool-1; w: 5:88
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@4c885c




INFO: Entering BeanA::function3:
Thread: p: thread-pool-1; w: 7:92
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@4c885c

FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanA function3:
INFO: Found Person id: d76c5baa-9619-4d40-869f-93a3a72e44c2, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box
Found Person id: de42f641-7869-4bb8-978b-cff1ab1ed2d5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]

INFO: Exiting BeanA::function3:
Thread: p: thread-pool-1; w: 7:92
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@4c885c




Test 19 traces....


Test19 on lil:

INFO: ControllerServlet test18 start
INFO: BeanB function5 start
INFO: uk.co.his.experiment.Person actually got transformed

INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolv er.
SEVERE: The Customizer has been started
SEVERE: Customize session called file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU
INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913

FINE: Detected Vendor platform: org.eclipse.persistence.platform.database.oracle.Oracle10Pla tform
CONFIG: connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
CONFIG: connecting(DatabaseLogin(
platform=>OraclePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))

CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
INFO: file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU login successful
FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]

FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]
FINE: SELECT ID, NAME FROM PERSON

INFO: People in BeanB function5 before calling X
INFO: Found Person id: 65a7669b-7dc7-4d12-a033-03e1a46788f5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

INFO: end get people before calling X
INFO: Calling X locally
INFO: Calling A on liepa!

INFO: Called A on liepa!
INFO: Called X locally
FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanB function5 after first X call - expect two person from liepa
INFO: Found Person id: da585b65-8448-41ca-b831-3ebef7cfcf0a, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: 6f746d01-0538-4363-93f2-7ff11a85b960, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function
Found Person id: 65a7669b-7dc7-4d12-a033-03e1a46788f5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

INFO: end get people
INFO: BeanB function5 getPeople 1
INFO: Calling X locally 2
INFO: Calling A on liepa!
INFO: Called A on liepa!
INFO: Called X locally 2
FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanB function5 final - expect four people from liepa
INFO: Found Person id: da585b65-8448-41ca-b831-3ebef7cfcf0a, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: 6f746d01-0538-4363-93f2-7ff11a85b960, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function
Found Person id: 47cbc80d-fb6d-465c-8bc9-376d02208f06, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: a5948e3a-3d6e-4300-8670-b5e55e562907, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function
Found Person id: 65a7669b-7dc7-4d12-a033-03e1a46788f5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

INFO: end get people
INFO: BeanB function5 end
INFO: ControllerServlet BeanB function5 called
INFO: ControllerServlet test18 end


Test19 on liepa:

INFO: uk.co.his.experiment.Person actually got transformed
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolv er.
SEVERE: The Customizer has been started
SEVERE: Customize session called file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU
INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913

FINE: Detected Vendor platform: org.eclipse.persistence.platform.database.oracle.Oracle10Pla tform
CONFIG: connecting(DatabaseLogin(
platform=>DatabasePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))
CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
CONFIG: connecting(DatabaseLogin(
platform=>OraclePlatform
user name=> ""
connector=>JNDIConnector datasource name=>null
))

CONFIG: Connected: jdbc:oracle:thin:xxxx/xxxx@lil:1521:orcl
User: SGF
Database: Oracle Version: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Driver: Oracle JDBC driver Version: 11.2.0.1.0
INFO: file:/C:/Users/Administrator/workspace/glassfish31eclipsedef aultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel. jar/_ExperimentjndiPU login successful


INFO: Entering BeanA::function3:
Thread: p: thread-pool-1; w: 5:85
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@12f1eff

FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]
FINE: SELECT ID, NAME FROM PERSON
FINE: SELECT t0.COMMENTS FROM Person_COMMENTS t0 WHERE (t0.Person_ID = ?)
bind => [1 parameter bound]
INFO: People in BeanA function3:
INFO: Found Person id: da585b65-8448-41ca-b831-3ebef7cfcf0a, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: 65a7669b-7dc7-4d12-a033-03e1a46788f5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean


FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]
INFO: Exiting BeanA::function3:
Thread: p: thread-pool-1; w: 5:85
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@12f1eff




INFO: Entering BeanA::function3:
Thread: p: thread-pool-1; w: 7:89
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@12f1eff

FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]
FINE: SELECT ID, NAME FROM PERSON
INFO: People in BeanA function3:
INFO: Found Person id: da585b65-8448-41ca-b831-3ebef7cfcf0a, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: 6f746d01-0538-4363-93f2-7ff11a85b960, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function
Found Person id: 47cbc80d-fb6d-465c-8bc9-376d02208f06, name: Created in A function 3 on Liepa, comments:
comment: Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function
Found Person id: 65a7669b-7dc7-4d12-a033-03e1a46788f5, name: Created in B function 5 on Lil, comments:
comment: The only person created directly in the 'controller' bean

FINE: INSERT IGNORE INTO PERSON (ID, NAME) VALUES (?, ?)
bind => [2 parameters bound]
FINE: INSERT IGNORE INTO Person_COMMENTS (Person_ID, COMMENTS) VALUES (?, ?)
bind => [2 parameters bound]
INFO: Exiting BeanA::function3:
Thread: p: thread-pool-1; w: 7:89
EntityManager delegate: org.eclipse.persistence.internal.jpa.EntityManagerImpl@12f1eff



What I observe is that;

**** In test18 BeanA on liepa CANNOT see the Person created by lil::BeanB, until it is called a second time (i.e. it has used the EM to WRITE before READING). ****
**** In test19 when BeanA on liepa does a WRITE before READING it can see the Person created by lil::BeanB ****


From which I concluded that this had something to do with the http://wiki.eclipse.org/Using_Advanced_Unit_of_Work_API_%28E LUG%29#Reading_Through_the_Write_Connection

Sure enough if I put in the line q.setLockMode(LockModeType.PESSIMISTIC_READ); in BeanA.getPeople() then I can see the person created in B as described.
My question is though .. why does EclipseLink not go to the DB anyway? I assumed at first that this was because it had a separate Read connection, and therefore ammended function3 in BeanA as follows;

private static final boolean useEclipseLinkBeginEarly = true;
	@SuppressWarnings("unused")
	@Override
	public void function3(boolean writeBeforeReading) throws NamingException, SystemException {
		System.out.println("Entering BeanA::function3:\n"  + getContextInfo() + "\n" );

		if(useEclipseLinkBeginEarly)
		{
			Session session = SessionManager.getManager().getSession("file:/C:/Users/Administrator/workspace/glassfish31eclipsedefaultdomain/eclipseApps/ExperimentEAR/lib/ExperimentEARmodel.jar/_ExperimentjndiPU");
			if(session != null)
			{
					session = session.getActiveSession();
					UnitOfWork work = session.getActiveUnitOfWork();
					work.beginEarlyTransaction();
					System.out.println("Unit of work beginEarlyTransaction called - read on a transactional connection");
			}
			else
			{
				System.err.println("Default session is null");
			}
		}
		else
		{
			System.out.println("Doing the default Eclipselink thing - read on a non transactional connection");
		}
		
		String hostname = "Unknown";
		try {
			hostname = InetAddress.getLocalHost().getCanonicalHostName();
		} catch (UnknownHostException e) {
		}
		
		if(writeBeforeReading && (!useEclipseLinkBeginEarly))
		{
			Person p = Person.createNewInstance();
			p.setName("Created in A function 3 on " + hostname);
			p.addComment("Normally called inside the same EAR running on a DIFFERENT box - 1 of 2 created in this function");
			em.persist(p);
			em.flush();
		}
		
		
		String people = getPeople(em);
		System.out.println("People in BeanA function3:");
		System.out.println(people);
		
		Person p2 = Person.createNewInstance();
		p2.setName("Created in A function 3 on " + hostname);
		if(writeBeforeReading && (!useEclipseLinkBeginEarly))
		{
			p2.addComment("Normally called inside the same EAR running on a DIFFERENT box - 2nd of 2 created in this function");
		}
		else
		{
			p2.addComment("Normally called inside the same EAR running on a DIFFERENT box");
		}
		em.persist(p2);
		em.flush();

		System.out.println("Exiting BeanA::function3:\n"  + getContextInfo() + "\n" );
	}



I assumed this would bind the UOW to the current J2EE txn branch and use a connection in the context of that txn, however it makes no difference; BeanA on liepa cannot see the Person created by BeanB on lil.
What am I doing wrong - or is the pesimistic lock the only solution?
Re: UnitOfWork.beginEarlyTransaction not having expected effect [message #663325 is a reply to message #662879] Mon, 04 April 2011 15:42 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Since you are using JTA, and not specifying a non-JTA DataSource, and not using a shared cache, I can't see how every query would not be querying the current transaction. i.e. the only data-source you are giving EclipseLink is a JTA data-source which must always be bound to the current transaction.

If you also gave EclipseLink and <non-jta-data-soure> tag, then this would occur, as EclipseLink would use the non-jta data-source for non-transactional queries. But, you don't seem to be setting this, perhaps Glassfish automatically sets this (you could check in your customizer by inspecting the readConnectionPool login)?

Irregardless, to have all queries use the JTA connection you can configure this is two ways using persistence unit properties,

"eclipselink.transaction.join-existing"="true"

or,

"eclipselink.jdbc.exclusive-connection.mode"="Always"

The code you are using is oriented at non-JPA applications, so probably will not work correctly.

In general, I would not recommend having multiple different servers share the same transaction.





James : Wiki : Book : Blog : Twitter
Re: UnitOfWork.beginEarlyTransaction not having expected effect [message #664406 is a reply to message #663325] Fri, 08 April 2011 16:28 Go to previous message
J F is currently offline J FFriend
Messages: 256
Registered: July 2009
Senior Member
Tried the example with eclipselink.transaction.join-existing=true and it all works as expected without having to do anything but bulk standard JPA.

Thanks.
Previous Topic:Problems with @PreUpdate and flush()
Next Topic:NullPointerException in DescriptorEventManager.notifyListener
Goto Forum:
  


Current Time: Thu Apr 25 06:33:56 GMT 2024

Powered by FUDForum. Page generated in 0.03347 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top