Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

transaction question 1

Status
Not open for further replies.

Themuppeteer

Programmer
Apr 4, 2001
449
BE
Hello,
Can anyone tell me what happens when you do the following thing in J2ee (in jboss for instance)

I have 2 session beans with the first a function f1 and second the function f2, each calling the same 2 entity beans.Each function runs in a transaction as usual in J2ee


f1()
{
a.changeIt();
b.changeIt();
}

f2()
{
b.changeIt();
a.changeIt();
}

f1 and f2 run at the same time.
a and b are entity beans.
Normally you would have a deadlock situation here.
Will a and b be locked from the start of the function ?
or will it just create the deadlock and then break it with an exception and rollback (so nothing will have happenned ?
What exactely will go on here ?


Thanks.

Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
Its very unlikely that these methods will run at EXACTLY the same time.

The situation may pan out like this :

f1 a.changeIt();
f2 a.changeIt();
f2 b.changeIt();
f1 b.changeIt();

OR :

f1 a.changeIt();
f1 b.changeIt();
f2 a.changeIt();
f2 b.changeIt();

OR EVEN :

f2 a.changeIt();
f2 b.changeIt();
f2 a.changeIt();
f2 b.changeIt();

It all depends on thread prioritys etc.

If you need to make sure these changeIt() methods are run syncronously, either synchronize the appropriate code, or have the method synchronized - this will ensure Thread safety and concurrency.

Code:
public void changeIt() {
  // do some stuff
  
  synchronized(this) {
    // do some critical concurrent stuff
  }
  //do some more stuff

}

OR :

Code:
public synchronized void changeIt() {
  // do some critical concurrent stuff
}

Bear in mind though that synchronized code causes other threads wishing to access it to go into a Thread.wait() method, because in effect a thread accessing a synchronized method enables a Thread.lock(), so you should synchronize only the bear essentials.



--------------------------------------------------
Free Database Connection Pooling Software
 
All those threads.. are we still talking J2EE here ?

I forgot to say that must asume that the db is only in a consistent state after that a.changeIt() AND b.changeIt() are done. (think of the typical bank account application)
So in this case,
f1 a.changeIt();
f2 a.changeIt();
f2 b.changeIt();
f1 b.changeIt();

we are in trouble.

and in case of

f1 a.changeIt();
f2 b.changeIt();

then follows (to achieve f1 b.changeIt(); f2 a.changeIt())

b must be locked by f1 but this doesn't go because f2 still has a lock on b.
and
a must be locked by f2 but this doesn't go because f1 still has a lock on a.

and we have a deadlock.



Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
No, there will be no deadlock because the lock is held on the method, not the object.

--------------------------------------------------
Free Database Connection Pooling Software
 
hmm,

what does this mean exactely ? Will a and b be locked from the start of the method until the end of the method ?
Guess not since you suggested:

f1 a.changeIt();
f2 a.changeIt();
f2 b.changeIt();
f1 b.changeIt();

?

or will the method of that bean not be accessible for 2 clients at the same time ?


Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
In this scenario :

f1 a.changeIt();
f2 a.changeIt();
f2 b.changeIt();
f1 b.changeIt();

what will happen is this :

f1 locks the a.changeIt();
f1 releases the lock.
f2 locks the a.changeIt();
f2 releases the lock.
f2 locks the b.changeIt();
f2 releases the lock.
f1 locks the b.changeIt();
f1 releases the lock.



--------------------------------------------------
Free Database Connection Pooling Software
 
ah ok..I see..

But that means that in my method f1, I can not change a and b in 1 turn. Because while I'm changing a, somebody else might change b and I can not stop him.

Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
Well if you need to do that, you should have one "access-to-changeit" method - synchronize this, and within that method change a and b.

--------------------------------------------------
Free Database Connection Pooling Software
 
Aha, now I understand :)

thanks a lot for the clarification sedj!

Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
Hello sedj,

I thought I understood it, but when I explained it to my colleagues, they had serious doubts with your answer..

First of all, people were wondering if 'synchonized' is allowed in J2ee (since threads aren't allowed either).

Second, presume that you have that one access-to-changeit" method , how can you forbid somebody else to call your b.changeIt from another bean behind your back while you are still busy with the a.changeit in your synchronized method ?




Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

"Those who say they understand chess, understand nothing"

-- Robert HUBNER
 
muppeteer :

First of all, people were wondering if 'synchonized' is allowed in J2ee (since threads aren't allowed either).

What ?!

Synchronized is a keyword of the Java langauage - considering that J2EE is only a set of API extensions to J2SE - of course it will work.

Of course threads are *allowed* in J2EE. There is no JVM/JRE out there (J2EE or SE) that does not use threads. Its like saying cars don't use engines.


I would suggest to your collegues they reconsider where they get their information on.

Remember that J2EE is JUST AN EXTENSION to J2SE - there is nothing magical about J2EE, and it runs exactly the same as a J2SE JVM would run.

Most J2EE servers these days are completely, and I mean completely reliant on JMX - which is the most heavy user of threading I have ever seen.

--------------------------------------------------
Free Database Connection Pooling Software
 
One other thing - if they don't think threads are allowed in J2EE - then ask them if they think EJB is not a part of EJB !

EJB uses RMI as its transport level.
RMI uses Socket and ServerSocket classes as its base TCP/IP socket layer.
Each EJB request spawns another Socket object passed into a Thread by the ServerSocket.

If this was not threaded - then you would only ever be able to make one EJB call at a time. But you don't do you ....



--------------------------------------------------
Free Database Connection Pooling Software
 
Hello sedj,
thanks for your quick answer.
Didn't mean to offend you, sorry if I did. I was just telling the state of mind over here. We have 6 months of experience with J2ee and are still in learning fase.

If you write a bean wich uses threads, you'll get errors when trying to deploy it to your application server.
So you simply may not use them. We are not 'thinking' we can't use them. They simply wont work.
Threads are not allowed in a J2EE application server (that was the whole point of session beans I thought, to avoid thread complexity). Of course the application server uses threads, I know that. Its just that we can't use them in our beans.

I think if you could answer this question, it would clarify a lot.
<quote>
Second, presume that you have that one access-to-changeit" method , how can you forbid somebody else to call your b.changeIt from another bean behind your back while you are still busy with the a.changeit in your synchronized method ?
</quote>

My best guess is the answer is the you can only have 1 accesser function (like you said),wich changes a and b, and that you must avoid to have another bean with a function wich changes b and a (in that sequence) or else you'll get a deadlock wich jboss will detect and throw an exception.



Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

&quot;Those who say they understand chess, understand nothing&quot;

-- Robert HUBNER
 
Hello again ...

I've used threading in EJB before plenty of times, but just to check I was not going mad, I implemented a very simple EJB, which proves that spawning new Threads in EJB is perfectly fine.

I will post the relevant snippets below :

This first snippet is the Bean class of a Remote EJB. As you can see, in the ejbCreate() method, I spawn 1000 new Threads.


Code:
   public Integer ejbCreate(Integer id) throws CreateException
   {
      this.setId(id);

		int numberOfThreads = 0;
		while (numberOfThreads < 1000) {
			// this is a class that extends Thread ...
      		new ProveThreadingWorks(numberOfThreads++).start();
		}



      return null;

   }

And here is the class that is the spawned thread - as you can see, it also uses internal threading within it to sleep.

Code:
public class ProveThreadingWorks extends Thread {
	int n = 0;

	public ProveThreadingWorks(int n) {
		this.n = n;
	}
	public void run() {
		int runFor = 100;
		while (runFor < 1000) {
			try {Thread.sleep(1000); } catch (Exception e) {}

			System.err.println("[ProveThreadingWorks] Hello Thread " +n +" :" + (new java.util.Date()));
			runFor++;
		}
	}
}

--------------------------------------------------
Free Database Connection Pooling Software
 
And what application server are you using ?
Jboss does not let you deploy your bean if it contains threading. And it shouldn't either if I can believe the sun-site
-----------------------
and click on discussion on threads:


says:

Why is thread creation and management disallowed?

The EJB specification assigns to the EJB container the responsibility for managing threads. Allowing enterprise bean instances to create and manage threads would interfere with the container's ability to control its components' lifecycle. Thread management is not a business function, it is an implementation detail, and is typically complicated and platform-specific. Letting the container manage threads relieves the enterprise bean developer of dealing with threading issues. Multithreaded applications are still possible, but control of multithreading is located in the container, not in the enterprise bean.
----------------------


Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

&quot;Those who say they understand chess, understand nothing&quot;

-- Robert HUBNER
 
I'm testing on JBoss 3.2.3_RC4.

That article says that Thread creation would interrupt the passivate and destroy lifecycle of EJB, and should be discouraged - it does not say that its impossible.

But I guess if you want to follow the blueprints to the letter, then you shouldn't sync your code either - "EJB should not use thread synchronization primitives to synchronize access with other enterprise bean instances".

Well I never did.

Oh well. Live and learn ... never did like EJB anyway !



--------------------------------------------------
Free Database Connection Pooling Software
 
OK, anyway. Back to the problem in hand.

So, one would hope then that the container would manage thread safety of your critical methods. But lets imagine for a moment it doesn't...

So, the problems are :

According to EJB "best practice" - we should not use either
synchronization in the EJB itself - but we don't trust the server to manage our critical methods.

So, I would maybe look at creating a static Helper class - maybe something like this :

Code:
public class CriticalHelper {
	static CriticalHelper staticInstance = new CriticalHelper();

	public void criticalMethodA() {
		// do some stuff
	}


	public void criticalMethodB() {
		// do some stuff
	}

	public void criticalMethodCommit() {
		// make sure that only our single instance class
		// updates A and B methods, and does in synchronously
		synchronized(staticInstance) {
			staticInstance.criticalMethodA();
			staticInstance.criticalMethodB();
		}
	}


}

This will then mean that there will only be a static single instance of CriticalHelper in the JVM that performs the transactional logic - no matter how many clients call it. It also means that the methods will be called synchronously, because the single instance of CriticalHelper only performs a synchronized method.

What do you think ?! Crazy maybe, but also quite crafty methinks !


--------------------------------------------------
Free Database Connection Pooling Software
 
Well, this would work, but then you have to make it a final static variable, otherwise it is also not permitted (see text below).
But the problem is that the two changeit methods are not in the same class (remember a.changeit(), b.changeit())

------------------


Why can't I use nonfinal static fields in my enterprise bean?

Nonfinal static class fields are disallowed in EJBs because such fields make an enterprise bean difficult or impossible to distribute. Static class fields are shared among all instances of a particular class, but only within a single Java Virtual Machine (JVM). Updating a static class field implies an intent to share the field's value among all instances of the class. But if a class is running in several JVMs simultaneously, only those instances running in the same JVM as the updating instance will have access to the new value. In other words, a nonfinal static class field will behave differently if running in a single JVM, than it will running in multiple JVMs. The EJB container reserves the option of distributing enterprise beans across multiple JVMs (running on the same server, or on any of a cluster of servers). Nonfinal static class fields are disallowed because enterprise bean instances will behave differently depending on whether or not they are distributed.


It is acceptable practice to use static class fields if those fields are marked as final. Since final fields cannot be updated, instances of the enterprise bean can be distributed by the container without concern for those fields' values becoming unsynchronized.
--------------------



Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

&quot;Those who say they understand chess, understand nothing&quot;

-- Robert HUBNER
 
Well, make it a final instance then :

static final CriticalHelper staticInstance = new CriticalHelper();

Thats a not a problem.

Also, its fine to call other class methods from the CriticalHelper method, because the method is syncronized from a static class - so this will resolve your concurrency issue.

Code:
public class CriticalHelper {
	static final CriticalHelper staticInstance = new CriticalHelper();

	public void criticalMethodA() {
		// do some stuff
               A a = new A();
               a.something();
	}


	public void criticalMethodB() {
		// do some stuff
               B b = new B();
               b.something();
	}

	public void criticalMethodCommit() {
		// make sure that only our single instance class
		// updates A and B methods, and does in synchronously
		synchronized(staticInstance) {
			staticInstance.criticalMethodA();
			staticInstance.criticalMethodB();
		}
	}


}


IMHO, the EJB spec/best practice guide (ie that link you keep quoting from) seems very good at saying what you cannot do, but does not hint at what you can do instead !


--------------------------------------------------
Free Database Connection Pooling Software
 
You're right about the site,but knowing what you can't do is a start, and its better to search for an alternative solution then doing it wrong and being in troubles in a year because you started on the wrong foot I think.

This would mean that all A and B calls would have to go via the CriticaHelpen class. You can never be sure of that.
Lets say that in a few years somebody else has to extend my program, he has to change B and then A. Without him knowing about the criticalHelper class and what it stands for he could still write the code in his bean to change B and then A and then we're off again (presuming that a and b are entity beans),
1)CriticalHelper updates A
2)Newbie updates B
3)CriticalHelper wants to lock B -->waits
4)Newbie wants to lock A --> waits

am I right ?

Greetz,
img


NOSPAM_themuppeteer@hotmail.com (for mails, remove the NOSPAM_)

&quot;Those who say they understand chess, understand nothing&quot;

-- Robert HUBNER
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top