Solved

How to get EJB Transaction Type?

Posted on 2004-09-29
19
4,517 Views
Last Modified: 2013-12-03
Hi all,
Is there any method where we can use to retrieve EJB Transaction Type? wheter it is Bean-Managed Transaction or Contained-Managed Transaction?


thanks
0
Comment
Question by:pleasure
  • 7
  • 6
  • 4
  • +2
19 Comments
 
LVL 35

Assisted Solution

by:girionis
girionis earned 20 total points
Comment Utility
I do not think there is, the transaction type is defined in the ejb-jar.xml file. Why do you want to do that?
0
 
LVL 35

Accepted Solution

by:
TimYates earned 30 total points
Comment Utility
girionis is right...  There is no reason for the client/beans to know this, so it is unavaliabel in a cross app server way...  you may be able to get at the info via JMX with JBoss though...
0
 

Author Comment

by:pleasure
Comment Utility
good question..:p

I have created a stateless session bean in JBoss 3.2.5. As i know, when we create a database connection in session bean. The transaction is managed by container (by default). At the same time, the auto commit mode is defaulted to false when we create a database connection within session bean.

I usually close a database connection  when i have finished with it, before i close a connection i usually commit whatever u commited connection. So, if i have created a connection from session bean, the container won't allow me to do so (commit any uncommited transaction).

So, what i'm thinking of is, to check whether the connection is Container-Managed Transcation, if yes, then I won't commit the transaction and let the container do it for me.

Hope you understand what i'm trying to do. How peoples normally deal with this issue??

0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
> I usually close a database connection  when i have finished with it,
> before i close a connection i usually commit whatever u commited
> connection. So, if i have created a connection from session bean, the
> container won't allow me to do so (commit any uncommited transaction).

The commit should happen automatically anyway, regardless if you have a container managed or bean managed transaction.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
You might want to try setting the auto commit to false if tyou want to commit the changes manually:

connection.setAutoCommit(false);
0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
There are different levels..

CMT as you describe, where you just get your JDBC connection from your DataSource, use it, with no transactional method calls (setAutoCommit, commit, rollback, etc), and when the session's method returns successfully the changes will be committed by the container (Throwing EJBException will cause a rollback).

BMT can be done in two ways -

using TransactionType  = "Bean", use the JDBC connection in the same way as CMT, but your session bean controls transaction using the SessionContext of the session bean (SessionContext.getUserTransaction(), userTransaction.begin() to begin a transaction, userTransaction.commit() to commit, userTransaction.rollback() to rollback).

Otherwise, you can use TransactionType="NotSupported" which will allow you to manipulate the JDBC connection directly, using setAutoCommit(), commit(), rollback(), etc. If you are doing this, you may want to restore the autoCommit property before Connection.close(), as JBoss uses wrapped Connections to manage Connection pooling, and I'm not sure if the pool restores the commit policy (it probably does, but just to be on the safe side one line of code doesn't hurt!)

Cheers,
C.
0
 

Author Comment

by:pleasure
Comment Utility
Actually I have a common class (says, DBManager.java) which I use it to handle database connection. So, it's basically shared by other classes regardless it's session bean or normal class.
Therefore I cannot assume that the commit will happen automatically from other class. May be i should have a separate DBManager specifically handle database connection created from Session Bean, any advice??
0
 

Author Comment

by:pleasure
Comment Utility
hi girionis,
nope, we are not allowed to do "connection.setAutoCommit(false)" in CMT, JBoss will throw an exception when we try to do so.


0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
How do you execuet the SQL statement? I guess you have a prepared statement. When you do thsi: ps.executeUpdate() then the commit should happen automatically. I really do not see whay you would need to do it manually.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:pleasure
Comment Utility
hi C,
do u mean that if we use  TransactionType="NotSupported" , the trancation type in session bean will behave like normal java class??

i have tried to set it to NorSupported by doing so
         <transaction-type>NotSupported</transaction-type>
but jboss throws me error saying that the transaction type must be Container or Bean. So, how can i set the value to NotSupported?
0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
Pleasure, Oops, mixed up "transaction-type" and "transaction" (we use XDoclet to generate the META-INF XML...)
There should be a "transactions" portion of the "ejb-jar.xml", e.g.

   <!-- transactions -->
   <container-transaction >
      <method >
         <ejb-name>TestSession</ejb-name>
          <method-name>*</method-name>
       </method>
       <trans-attribute>NotSupported</trans-attribute>
    </container-transaction>

This should allow you to specify the type of transactions being managed by the Container, so a combination of "tranaction-type" set to "Container" and "trans-attribute" (as in the above snippet) should allow you to have Container-managed-no-transactions, thus allowing you to directly use basic JDBC control (Personally I find the CMT approach the cleanest, but for sessions that do larger jobs that require multiple commitals (and especially those that allow partial failures) BMT is the way to go...

I have a several general utility classes that provides DB access using JDBC connections, that are sometimes called from within CMT, sometimes from within BMT, and sometimes from non-EJB code.

For the classes that are CMT and BMT only (i.e. don't have to support non-EJB use) I just use InitialContext to get the DataSource, and then DataSource.getConnection() inside the class, use this returned Connection without worrying about setAutoCommit(), commit(), rollback() etc, as JBoss handles the transactionality of this Connection (my session bean then either is CMT, which does no direct manipulation, or uses the UserTransaction code I described for BMT...

For the classes that have to support non-EJB callers, I provide overloaded methods to pass in a JDBC connection. When the method without the overloaded Connection parameter is called it uses DataSource.getConnection, and then calls the overloaded method. The overloaded method assumes that the caller will handle transactions on the supplied connection (e.g. commit() on successful return, rollback on exception, etc). Then when calling from within CMT/BMT, use the methods without Connection argument, and from within non-EJB code, create a connection, call Connection.setAutoCommit( false ), and then Connection.commit() or Connection.rollback() as required after the call.

0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
girionis, yup, the Connection is used in the session bean as if AutoCommit is enabled, but the transaction is actually managed seperately (see my description above regarding the differences between CMT and BMT. (actually, using any transactional methods (setAutoCommit, commit, rollback, etc) on a Connection are disallowed for either type of managed transactions, causing JBoss to raise an exception!)
0
 

Author Comment

by:pleasure
Comment Utility
hi C,
So, basically we need to have different code to handle connection created from EJB and connection from non-EJB, rite?
0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
well... yes and no....

Take the following example:

public class ExampleDataManager {
    // ... several methods not implemented....

    public void addEntry( DataEntry entry ) throws Exception {
        Connection conn = null;
        try {
            addEntry( getDataSource().getConnection(), entry );
        }
        finally {
            if( conn != null ) {
                try {
                     conn.close();
                }
                catch( Exception e ) { log.warn( "Failed to close Connection", e ); }
        }
    }

    public void addEntry( Connection conn, DataEntry entry ) throws Exception {
        PreparedStatement pstmt = null;
        try {
            pstmt = conn.prepareStatement( ADD_ENTRY_SQL );
            pstmt.setLong( 1, entry.getID() );
            pstmt.setString( 2, entry.getName() );
            pstmt.executeUpdate();
        }
        finally {
            if( pstmt != null ) {
                   try { pstmt.close(); } catch( Exception e ) {}
            }
         }
}


This example is a simple outline for what I described earlier, whereby the "addEntry( DataEntry )" method would be called from within the Managed Transaction (in Session EJB), so no need for transactionality here, and the "addEntry( DataEntry, Connection )" would be called from code not in EJB, with some boilerplate wrapper code to 1) create a JDBC connection, 2) setAutoCommit( false ), 3) call the method, and commit/rollback as necessary...

e.g.

CMT Session EJB:

try {
    ExampleDataManager.getInstance().addEntry( entry );
}
catch( Exception e ) {
    log.error( "Failed to add entry", e );
}

Non EJB-Code

// Method to get connection left out (standard JDBC connection creation code!)
Connection conn = getConnection();
conn.setAutoCommit(false);
try {
    ExampleDataManager.getInstance().addEntry( entry, conn );
    conn.commit();
}
catch( Exception e) {
    conn.rollback();
    conn.close();
}

Actually, if you have several instances of this, you could probably develop an abstract class for the ExampleDataManager, which performs the boilerplate...

Hope this helped.
C.
0
 

Author Comment

by:pleasure
Comment Utility
yupe..that can be one of the ways to achieve the objective...:-)

thanks for all the response.
0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
why did I not get a point [:-(
0
 

Author Comment

by:pleasure
Comment Utility
ooopppppppppssssssssss.... i made a big mistake.. i actually wish to give u the point but accidently awarded to TimYates. I'm sorry... can I undo it??? :(
0
 
LVL 11

Expert Comment

by:cjjclifford
Comment Utility
I'd say moderator might be able to... not to worry anyway, glad I could be of help.
 
0
 
LVL 8

Expert Comment

by:mnrz
Comment Utility
To find out whether the tx is Bean managed or container managed we have following code to roll back manually in case of an exception in an interceptor
@Resource

SessionContext context
 

try {

	context.getUserTransaction();

          int status = context.getUserTransaction().getStatus();

          if(status != Status.STATUS_MARKED_ROLLBACK &&

          		status != Status.STATUS_ROLLEDBACK &&

          		status != Status.STATUS_ROLLING_BACK &&

                  status != Status.STATUS_NO_TRANSACTION) {

          	context.getUserTransaction().rollback();

          }

}catch (IllegalStateException ise) {

	//transaction management is of type CMT

	context.setRollbackOnly();

}

Open in new window

0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Suggested Solutions

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now