-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 37 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: HELP! Problems with transaction.
PostPosted: Fri Feb 27, 2004 8:41 am 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
I'm using Hibernate 2.1.1.
I want to deploy Hibernate as a MBean (SAR) in JBoss 3.2.3.
Here's my jboss-service.xml for the SAR:

Code:
<server>
<mbean code="net.sf.hibernate.jmx.HibernateService" name="jboss.jca:service=ArsolHibernateFactory,
                            name=ArsolHibernateFactory">
    <depends>jboss.jca:service=RARDeployer</depends>
    <depends>jboss.jca:service=LocalTxCM,name=arsolDS</depends>   
    <!-- Make it deploy ONLY after DataSource had been started -->
    <attribute name="MapResources">
      mapping/ArmazemMistura.hbm.xml,
      mapping/ArmazemMp.hbm.xml,
      mapping/ArmazemPa.hbm.xml,
      mapping/ArmazemPeca.hbm.xml
    </attribute>
    <attribute name="JndiName">java:/hibernate/ArsolHibernateFactory</attribute>
    <attribute name="Datasource">java:/arsolDS</attribute>
    <attribute name="Dialect">net.sf.hibernate.dialect.PostgreSQLDialect</attribute>
    <attribute name="TransactionStrategy">net.sf.hibernate.transaction.JTATransactionFactory</attribute>
    <attribute name="TransactionManagerLookupStrategy">net.sf.hibernate.transaction.JBossTransactionManagerLookup</attribute>
    <attribute name="UseOuterJoin">false</attribute>
    <attribute name="ShowSql">false</attribute>
    <attribute name="UserTransactionName">UserTransaction</attribute>
</mbean>
</server>


Here's my datasource file:

Code:
<?xml version="1.0" encoding="UTF-8"?>

<datasources>
  <local-tx-datasource>
    <jndi-name>arsolDS</jndi-name>
    <connection-url>jdbc:postgresql://localhost:5432/devdb</connection-url>
    <driver-class>org.postgresql.Driver</driver-class>
    <user-name>user</user-name>
    <password>pwd</password>
  </local-tx-datasource>

</datasources>


This is working great when using transaction per method.
But now I want to create a service layer using Session Beans to execute my logic. I want to use Container Managed Transaction (CMT). But I'm having trouble making this work. When I execute a business method with the SB it doesn't give me any error. The problem is that I see no changes in the database. So I think the problem is with the transaction configuration.
I don't know if the problem is in the SAR config file.

Here's my ejb-jar.xml to help:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar >

   <description><![CDATA[No Description.]]></description>
   <display-name>Generated by XDoclet</display-name>

   <enterprise-beans>

      <!-- Session Beans -->
      <session >
         <description><![CDATA[EJB Test]]></description>

         <ejb-name>MpBean</ejb-name>

         <home>pt.ejb.MpHome</home>
         <remote>pt.ejb.Mp</remote>
         <local-home>pt.ejb.MpLocalHome</local-home>
         <local>pt.ejb.MpLocal</local>
         <ejb-class>pt.ejb.MpBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>

      </session>

   </enterprise-beans>

   <!-- Relationships -->

   <!-- Assembly Descriptor -->
   <assembly-descriptor >

   <!-- finder permissions -->

   <!-- transactions -->
   <container-transaction >
      <method >
         <ejb-name>MpBean</ejb-name>
          <method-name>*</method-name>
       </method>
       <trans-attribute>Required</trans-attribute>
    </container-transaction>

   <!-- finder transactions -->
   </assembly-descriptor>

</ejb-jar>


Please help. At this problem two days now. Can't find the problem.
Really appreciate some help on this.

Thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 10:15 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
How are you getting Hibernate Session?

You should use the following routine to get session inside each you bean method.

HibernateUtil.openSession()
Code:
Context ctx = new InitialContext();
SessionFactory factory = (SessionFactory) ctx.lookup("java:/hibernate/ArsolHibernateFactory");
sess = factory.openSession();


Don't forget to cache your SessionFactory.

Also you should close each session inside each method, it is ok, SQL commit will be sent only when container transaction is finished.

your db access code should be similiar to the following pseudo-code:
Code:
Session session = null;
try
{
    session = HibernateUtil.openSession();
    .....
}
catch(..)
{
    sessionContext.setRollbackOnly();
    log.error(...)
}
finally
{
     if (null != session)
        session.close()
}


If you want, I could post HibernateUtil class (http://www.hibernate.org/hib_docs/reference/html/quickstart.html#d0e301)
modified to work inside CMT.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 10:22 am 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
How are you getting Hibernate Session?

You should use the following routine to get session inside each you bean method...

If you want, I could post HibernateUtil class (http://www.hibernate.org/hib_docs/reference/html/quickstart.html#d0e301)
modified to work inside CMT.


Thanks for the reply.
I have a class identical to HibernateUtil but with diferent name (HibernateSession).

My idea is to have methods in the Session Bean like the following:

Code:
public void updateMP(Mp mp) {
      
   try {
      Session session = HibernateSession.currentSession();
      MpBO.updateMP(session, mp);
      HibernateSession.closeSession();
   }
   catch(Exception e) {
      System.out.println(">>> MP_EJB: Exception");
   }
}   


I want to pass the "session" in to the business method. The container will be responsible for the transaction (CMT).

Please... any ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 10:28 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
What happen if you set
Code:
session.flush();

before
Code:
HibernateSession.closeSession();

Look into jboss debug log (server.log).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 10:33 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
And one important thing, your SessionFactory should be got from context else your session is not binded to CMT.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 10:44 am 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
What happen if you set
Code:
session.flush();

before
Code:
HibernateSession.closeSession();

Look into jboss debug log (server.log).


I've put the "session.flush()" and it worked!
In the "server.log" didn't notice nothing strange.
Shouldn't the TransactionManager flush the data automatically?


PS: thanks very much for the help.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 11:08 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
[url]file:///home/shl/javalib/hibernate-2.1/doc/116.html#A24[/url]

Quote:
Class Transaction
public void commit()
throws HibernateException
Flush the associated Session and end the unit of work. This method will commit the underlying transaction if and only if the transaction was initiated by this object.


Are you getting SessionFactory from the context?
If you use code from HibernateUtil it is not the right approach for CMT. Your openSession should looks like:
Code:
Context ctx = new InitialContext();
SessionFactory factory = (SessionFactory) ctx.lookup("java:/hibernate/ArsolHibernateFactory");
sess = factory.openSession();


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 11:18 am 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
Are you getting SessionFactory from the context?
If you use code from HibernateUtil it is not the right approach for CMT. Your openSession should looks like:
Code:
Context ctx = new InitialContext();
SessionFactory factory = (SessionFactory) ctx.lookup("java:/hibernate/ArsolHibernateFactory");
sess = factory.openSession();


Here is my code to get the SessionFactory (HibernateFactory):

Code:
package pt;

import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import pt.BadFactoryException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import java.io.FileInputStream;

public class HibernateFactory {

   public static SessionFactory createFactory() throws BadFactoryException {
      SessionFactory sessionFactory = null;
   
      try {
         Context ctx = new InitialContext();
         sessionFactory = (SessionFactory)ctx.lookup("java:/hibernate/ArsolHibernateFactory");
      }
      catch(Exception e) {
         throw new BadFactoryException("Error.");
      }
      return(sessionFactory);
   }
}


Here is the code to create a "Session" similar to HibernateUtil:

Code:
package pt;

import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Session;
import net.sf.hibernate.HibernateException;

public class HibernateSession {

     public static final ThreadLocal session = new ThreadLocal();
   
    public static Session currentSession() throws BadFactoryException, HibernateException {
        Session s = (Session) session.get();
     
         try {
            if (s == null) {
         SessionFactory sf = HibernateFactory.createFactory();
               s = sf.openSession();
               session.set(s);
           }
         }
         catch(BadFactoryException e) {
      log.fatal(e.getMessage());
            throw new BadFactoryException(e.getMessage());
         }
         return s;
    }

    public static void closeSession() throws HibernateException {
       Session s = (Session) session.get();
          session.set(null);
          if (s != null) s.close();
    }
}


Isn't this the correct way to implement CMT?
Is there a better way?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 11:52 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Yes, it is OK.

Our team uses hibernate with jboss CMT, and everything is OK.
If you want I could look into your code, home at week-end (shl at vlinkmail dot com) or send you part of our project.

If I were at your place I would try to avoid transmitting session from one session bean to another, let each bean uses HibernateSession.currentSession(), and I would put session.flush() before each HibernateSession.closeSession().
Code:
public void updateMP(Mp mp) {
   try {
      Session session = HibernateSession.currentSession();
      MpBO.updateMP(session, mp);
                                  ^^^^
      HibernateSession.closeSession();
   }
   catch(Exception e) {
      System.out.println(">>> MP_EJB: Exception");
   }
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 11:56 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
You can also include the standard hibernate transaction handling in the code, it will integrate with a CMT and do a flush on commit, too (tx.commit() will not commit really when using CMT)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 12:03 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Code:
public void updateMP(Mp mp) {
   try {
      Session session = HibernateSession.currentSession();
      MpBO.updateMP(session, mp);
      HibernateSession.closeSession();
   }
   catch(Exception e) {
      System.out.println(">>> MP_EJB: Exception");
   }
}


And look better for the string ">>> MP_EJB: Exception" in your logs :)
It would be more usable to log the exception :).
Or for testing replace it for System.out.println(">>> MP_EJB: Exception" + e.toString());


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 12:15 pm 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
Code:
public void updateMP(Mp mp) {
   try {
      Session session = HibernateSession.currentSession();
      MpBO.updateMP(session, mp);
      HibernateSession.closeSession();
   }
   catch(Exception e) {
      System.out.println(">>> MP_EJB: Exception");
   }
}


And look better for the string ">>> MP_EJB: Exception" in your logs :)
It would be more usable to log the exception :).
Or for testing replace it for System.out.println(">>> MP_EJB: Exception" + e.toString());


I know... :-)
Took out some lines to simplify reading.

I've looked at the debug info in "server.log".

Code:
2004-02-27 15:24:25,015 DEBUG [net.sf.hibernate.persister.EntityPersister] Updating entity: [vo.Mp#1]
2004-02-27 15:24:25,015 DEBUG [net.sf.hibernate.impl.BatcherImpl] about to open: 0 open PreparedStatements, 0 open ResultSets
2004-02-27 15:24:25,015 DEBUG [net.sf.hibernate.SQL] update mp set referencia=?, designacao=?, modelo=?, tipo=?, peso=?, fornecedor_fk=?, data_monitorizacao=?, desenho_material=?, norma=?, legislacao=?, fabricante=?, estado=?, estado_monit=?, user_id=?, dt_hr=? where id=?
2004-02-27 15:24:25,015 DEBUG [net.sf.hibernate.impl.BatcherImpl] preparing statement
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.persister.EntityPersister] Dehydrating entity: [vo.Mp#1]
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding 'REFMP' to parameter: 1
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding 'NOVAMP' to parameter: 2
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding 'TONECAS' to parameter: 3
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 4
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.BigDecimalType] binding '1.00' to parameter: 5
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 6
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.DateType] binding null to parameter: 7
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 8
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 9
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 10
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding '1' to parameter: 11
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding 'A' to parameter: 12
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding null to parameter: 13
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.StringType] binding 'dp1' to parameter: 14
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.TimestampType] binding '27 Fevereiro 2004 15:24:21' to parameter: 15
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.LongType] binding '1' to parameter: 16
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.BatcherImpl] Adding to batch
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.BatcherImpl] Executing batch size: 1
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.BatcherImpl] done closing: 0 open PreparedStatements, 0 open ResultSets
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.BatcherImpl] closing statement
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.SessionImpl] post flush
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.SessionImpl] closing session
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.SessionImpl] disconnecting session
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.engine.CacheSynchronization] transaction before completion callback
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.engine.CacheSynchronization] transaction after completion callback, status: 3
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.impl.SessionImpl] transaction completion

( ... )

2004-02-27 15:24:51,359 DEBUG [net.sf.hibernate.impl.SessionImpl] running Session.finalize()
2004-02-27 15:24:51,359 DEBUG [net.sf.hibernate.impl.SessionImpl] running Session.finalize()
2004-02-27 15:24:51,359 DEBUG [net.sf.hibernate.impl.SessionImpl] running Session.finalize()


By the looks of it, the transaction is working. Need to test some "rollbacks".
What's strange is the lots of "Session.finalize()" that are executed.
Is this normal?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 1:50 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
About Session.finalize(). I looked into my debug log and saw the same picture (one or three Session.finalize() calls one after another, three calls at the application session end as I got).

One trick. After that update execute the following SQL query:
Code:
select count(*) from mp where id=1

It should return 1, because of:
Code:
2004-02-27 15:24:25,015 DEBUG [net.sf.hibernate.SQL] update mp set referencia=?, designacao=?, modelo=?, tipo=?, peso=?, fornecedor_fk=?, data_monitorizacao=?, desenho_material=?, norma=?, legislacao=?, fabricante=?, estado=?, estado_monit=?, user_id=?, dt_hr=? where id=?
...
2004-02-27 15:24:25,031 DEBUG [net.sf.hibernate.type.LongType] binding '1' to parameter: 16

Maybe before update you did have the row with id=1 in 'mp' table. But as I remember hibernate should warn you about such things.

And one more trick, check your datasource points to the same db as you look using your sql tool :)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 1:55 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
And if you use version for your class, try to set batch-size="0" for the Mp class. In FAQ it is recommeded for some old JDBC drivers.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 5:34 pm 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
About Session.finalize(). I looked into my debug log and saw the same picture (one or three Session.finalize() calls one after another, three calls at the application session end as I got).


Maybe before update you did have the row with id=1 in 'mp' table. But as I remember hibernate should warn you about such things.

And one more trick, check your datasource points to the same db as you look using your sql tool :)



I have a row with id=1 in my DB. That's why I'm doing an update. :-)
It's stange so much "Session.finalize()". It's not good for performance.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 37 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.