-->
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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Problem storing object in JUnit, but works in app server
PostPosted: Mon Jul 18, 2005 8:08 pm 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
Hi,

I'm having problems with hibernate using JDBC and MySQL. When using this configuration the data is *not* stored on the database, although the object's ID is updated. The log shows the INSERT being issued. This happens in a JUnit stand-alone test.

The *EXACT* same object (and code) is used inside the Application Server, using a Datasource and everything works like a charm. The only difference between both scenarios is the database config file (i am attaching both versions here).

Also if i manually store the object using jdbc (in JUnit OR inside the app server) everything works fine. (in this scenario no hibernate is used). I just dont know what else to try. I was thinking it *might* be a Transaction issue, but i think that all new connections with com.mysql.jdbc.Driver have AUTOCOMMIT enabled (even though, i use the same drivers for both App Server & JUnit versions).

These are my products versions.
Hibernate: 2.1.3
MySQL: 4.0.20a-nt
App Server: Weblogic 8.1
Driver: dont know..but it is always the same one.


I am also attaching Hibernate's log when it boots up.

Thank you very much for your help.
Regards,
Andres Bernasconi

ATTACHMENTS:

---------- JDBC cfg file -------------------
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
   <!-- a SessionFactory instance listed as /jndi/name -->
   <session-factory>
      <!-- properties -->
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="connection.url">
         jdbc:mysql://localhost:3306/gastos
      </property>
      <property name="connection.username">root</property>
      <property name="connection.password"></property>
      <property name="show_sql">true</property>
      <property name="hibernate.transaction.factory_class">
         net.sf.hibernate.transaction.JDBCTransactionFactory
      </property>
      <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>

      <!-- mapping files -->
      <mapping resource="com/ntrc/gastos/bean/Periodo.hbm.xml"/>
   </session-factory>

</hibernate-configuration>


---------- App Server cfg file -------------------

Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
   <!-- a SessionFactory instance listed as /jndi/name -->
   <session-factory>
      <!-- properties -->
      <property name="connection.datasource">jdbc/gastosDataSource</property>
      <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>

      <!-- mapping files -->
      <mapping resource="com/ntrc/gastos/bean/Periodo.hbm.xml"/>
   </session-factory>

</hibernate-configuration>



---------- BOOT log (JUnit) -------------------
Code:
- Hibernate 2.1.3
- loaded properties from resource hibernate.properties: {hibernate.cache.provider_class=net.sf.hibernate.cache.OSCacheProvider, hibernate.cglib.use_reflection_optimizer=true, hibernate.connection.pool_size=10, hibernate.show_sql=false, hibernate.transaction.factory_class=net.sf.hibernate.transaction.JTATransactionFactory}
- using CGLIB reflection optimizer
- configuring from url: file:/C:/trabajo/workspaces/personal/gastos/classes/com/ntrc/gastos/conf/database/test-database.cfg.xml
- Mapping resource: com/ntrc/gastos/bean/Periodo.hbm.xml
- Mapping class: com.ntrc.gastos.bean.Periodo -> PERIODO
- Configured SessionFactory: null
- processing one-to-many association mappings
- processing one-to-one association property references
- processing foreign key constraints
- Using dialect: net.sf.hibernate.dialect.MySQLDialect
- Use outer join fetching: false
- Using Hibernate built-in connection pool (not for production use!)
- Hibernate connection pool size: 10
- using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/gastos
- connection properties: {user=root, password=}
- Transaction strategy: net.sf.hibernate.transaction.JDBCTransactionFactory
- No TransactionManagerLookup configured (in JTA environment, use of process level read-write cache is not recommended)
- Use scrollable result sets: true
- Use JDBC3 getGeneratedKeys(): true
- Optimize cache for minimal puts: false
- echoing all SQL to stdout
- Query language substitutions: {}
- cache provider: net.sf.hibernate.cache.OSCacheProvider
- Error reading /oscache.properties in CacheAdministrator.loadProps() java.lang.NullPointerException
- Ensure the /oscache.properties file is readable and in your classpath.
- instantiating and configuring caches
- building session factory
- reflection optimizer disabled for: com.ntrc.gastos.bean.Periodo, IllegalArgumentException: Cannot find matching method/constructor
- no JNDI name configured


---------- BOOT log (App Server) -------------------
Code:
- Hibernate 2.1.3
- loaded properties from resource hibernate.properties: {hibernate.cache.provider_class=net.sf.hibernate.cache.OSCacheProvider, hibernate.cglib.use_reflection_optimizer=true, hibernate.connection.pool_size=10, hibernate.show_sql=false, hibernate.transaction.factory_class=net.sf.hibernate.transaction.JTATransactionFactory}
- using CGLIB reflection optimizer
- configuring from url: file:C:/bea/user_projects/myserver/.wlnotdelete/gastos/webapp/WEB-INF/classes/com/ntrc/gastos/conf/database/database.cfg.xml
- Mapping resource: com/ntrc/gastos/bean/Periodo.hbm.xml
- Mapping class: com.ntrc.gastos.bean.Periodo -> PERIODO
- Configured SessionFactory: null
- processing one-to-many association mappings
- processing one-to-one association property references
- processing foreign key constraints
- Using dialect: net.sf.hibernate.dialect.MySQLDialect
- Use outer join fetching: false
- JNDI InitialContext properties:{}
- Using datasource: jdbc/gastosDataSource
- Transaction strategy: net.sf.hibernate.transaction.JTATransactionFactory
- JNDI InitialContext properties:{}
- No TransactionManagerLookup configured (in JTA environment, use of process level read-write cache is not recommended)
- No TransactionManagerLookup configured (in JTA environment, use of process level read-write cache is not recommended)
- Use scrollable result sets: true
- Use JDBC3 getGeneratedKeys(): true
- Optimize cache for minimal puts: false
- Query language substitutions: {}
- cache provider: net.sf.hibernate.cache.OSCacheProvider
- Error reading /oscache.properties in CacheAdministrator.loadProps() java.lang.NullPointerException
- Ensure the /oscache.properties file is readable and in your classpath.
- instantiating and configuring caches
- building session factory
- reflection optimizer disabled for: com.ntrc.gastos.bean.Periodo, IllegalArgumentException: Cannot find matching method/constructor
- no JNDI name configured


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 1:40 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
The code between session creation and session close could helpt to solve your problem.

HTH
Ernst


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 5:49 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
ernst_pluess wrote:
The code between session creation and session close could helpt to solve your problem.


Yeah...

Andres, didn't you forget about CMT? I mean that in your JUnit test you should manage your transactions manually. Transaction.commit() should solve your problem.

_________________
Leonid Shlyapnikov


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 9:39 am 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
i think I already tried that. Either way, if autocommit is enabled, why is this happening? why do i need to transaction.commit() ?

This is the code snippet where i save the object. It is the same piece of code executing every time, so there should be no difference:

Code:
   public Periodo guardarPeriodo(Periodo p) throws DataAccessException {

      try {
         [b]session.save(p);[/b]
      } catch (HibernateException e) {
         throw new DataAccessException("Error guardando periodo '" +
               p.getId() + "'");
      }
      
      return p;
   }


The session is opened and the factory configured the same way both times.
When I debug in the App Server, after executing session.save(p) the database is updated (so this rules out the need of the transaction.commit() line, i guess). But if i do the same in the JUnit case, no record is written. ¿?. I also tried doing session.flush(), and session.close() AFTER session.save(p), just to see, and nothing happens. I also tried doing
Code:
Transaction t = session.getTransaction(); //or whatever the method name is
session.save(p);
session.close();
t.commitTransaction();

and still didn't work. Is there a way to force autocommit in the connection URL? I'm really stunned about this. Also, i am not using EJBs, so no transaction is being managed for my in the app server.
Any help would be apreciated. [/code][/b]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 10:28 am 
Expert
Expert

Joined: Tue Oct 05, 2004 9:45 am
Posts: 263
why are you closing the session bevor doing the "commit"?
I think commit-first an then close the session is better ;)

gtx
curio


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 11:14 am 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
Ok..i will try that, but that still doesnt explain why it works inside the app server :s


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 19, 2005 12:23 pm 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
I tried closing first the transaction and THEN closing the session, and it works. But i really don't want to handle transaction in there... I need to know why this works inside the application server when no (explicit) transaction handling is being made, and why it needs to be done if autocommit is true. I tried forcing autocommit with hibernate.connection.autocommit=true, but it didn't work. I also tried changing Connection Pooling to DBCP, but it failed too.

Any other answer will be apreciated. Thanks a lot,
AB


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 1:56 am 
Expert
Expert

Joined: Thu Jan 29, 2004 2:31 am
Posts: 362
Location: Switzerland, Bern
There are a number of things to be aware of:

  1. In order to get your session synchronized with the DB Hibernate has to flush the session. In you case this is triggered by the commit which in turn is called by the AppServer.
  2. In the JUnit case you have to call transaction.commit or session.flush to make the synchronizing (flushing) happen.
  3. Do you really want to use autocommit=true? I'd prefer a Template approach. See the attached code as an example. Spring is also a good resource in order to learn more about the TransactionTemplate pattern.


Code:
/**
* <pre>
*      new TransactionTemplate(){
*         protected void execute() {
*            XmlDAO avTransverDao = (XmlDAO) CapiDaoFactory.getInstance().getDAO(AvTransfer.class);
*            XmlInput xmlInput = new FileInput(tmpFile.getAbsolutePath());
*            
*            AvTransfer avTransfer = (AvTransfer) avTransverDao.read(xmlInput);
*            AvEigentumsverhaeltnis avEigentumsVh = (AvEigentumsverhaeltnis) avTransfer.getData().getEigentumsverhaeltnisse().get(0);
*         }
*      }.run();
* </pre>
*
*/
public abstract class TransactionTemplate {
   
    private Transaction trx;
   
   public TransactionTemplate() {
       trx =  TransactionManager.beginTransaction();
   }
      
   
   /**
    * Fuert den Test innerhalb einer Transaktion aus. Im Fehlerfall wird
    * das {@link Throwable}geloggt, die Transaktion zurueckgefahren und
    * das {@link Throwable}wieder geworfen.
    */
   public void run() {
      try {
          TransactionManager.setCurrentTrx(trx);
         execute();
         TransactionManager.commitTransaction();
      } catch (Throwable e) {
         LOG.error("", e);
         TransactionManager.rollbackTransaction();
         throw new RuntimeException(e);
      }
   }

   /**
    * Enthaelt den eigentlichen Test.
    */
   protected abstract void execute();

}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 6:20 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
sotretus wrote:
i think I already tried that. Either way, if autocommit is enabled, why is this happening? why do i need to transaction.commit()

1. suggestion: do not rely on autocommit in real applications
2. answer: hibernate Session is a first-level cache, to flush it use session.flush(), so you did not flush it, hibernate did not generate insert/update and did not execute them, and there was not job for your autocommit. Transaction.commit() flushes the session and it is enough to call tx.commit() only.

_________________
Leonid Shlyapnikov


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 6:28 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
sotretus wrote:
But i really don't want to handle transaction in there...

11.2.6. Declarative transaction demarcation http://www.springframework.org/docs/reference/orm.html#d0e6990
11.2.7. Transaction management strategies http://www.springframework.org/docs/reference/orm.html#d0e7023

sotretus wrote:
I need to know why this works inside the application server when no (explicit) transaction handling is being made

You application server manages transactions (Container Managed Transactions) if hibernate configured properly.

sotretus wrote:
and why it needs to be done if autocommit is true.

I think it is because of you did not call session.flush() see the previous post

_________________
Leonid Shlyapnikov


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 10:01 am 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
I tried session.flush() (with no transaction.commit() ) and it did not store anything.

I understand that spring resolves this things, but i dont want to use it, at least not right now.

I still don't understand the difference (that's the question here, since now i know how to solve the problem, and actually there is no problem because in the App Server it works fine).

In the App server AFTER EXECUTING THE LINE ' session.save(p)' (debuggin the application) i check the database an the info is inserted. Before any .flush(), and before any .commit(). In JUnit it does not happen that.

Now why could THAT be?
I am not trying to base my app in autocommit, but it is useful when JUnit-testing code (because i don't manage transactions in JUnit right now).

Best Regards, and please keep posting as i am really interested in learning more about this.

Thanks again
AB


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 11:59 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
sotretus wrote:
I tried session.flush() (with no transaction.commit() ) and it did not store anything.

...
Now why could THAT be?
I am not trying to base my app in autocommit, but it is useful when JUnit-testing code (because i don't manage transactions in JUnit right now).


if you need autocommit check this in your JUnit test:
Code:
assertTrue( session.connection().getAutoCommit() )


where session.connection() returns real JDBC Connection.

I don't know maybe you did not configure autocommit property.

_________________
Leonid Shlyapnikov


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 12:03 pm 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
oh, great! i will check that both inside the app server and in JUnit and come back with an answer...i think we can get to the bottom-line of this.

regards
ab


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 12:27 pm 
Newbie

Joined: Mon Jul 05, 2004 5:20 pm
Posts: 11
GREAT!
i found out that autocommit is false in the JUnit test! just like i suspected... now i wonder why the connection isnt being initialized correctly :s

this is my config file:
Code:
<property name="hibernate.connection.autocommit">true</property>


any suggestions of any other way of doing it?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 20, 2005 12:38 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
sotretus wrote:
any suggestions of any other way of doing it?


The simplest way:
Code:
session.connection().setAutoCommit(true);


But I would prefer to commit() transaction in JUnit test manually. AUTOCOMMIT IS EVIL

_________________
Leonid Shlyapnikov


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  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.