views:

1036

answers:

3

Hello good fellas! in my journey of learning hibernate i came across an article on hibernate site. i' learning spring too and wanted to do certain things to discover the flexibility of spring by letting you implement you own session.yes i don't want to use the hibernateTemplate(for experiment). and i'm now having a problem and even the test class.I followed the article on the hibernate site especially the section an "implementation with hibernate" so we have the generic dao interface :

public interface GenericDAO<T, ID extends Serializable> {

T findById(ID id, boolean lock);

List<T> findAll();

List<T> findByExample(T exampleInstance);

T makePersistent(T entity);

void makeTransient(T entity);

}

it's implementation in an abstract class that is the same as the one on the web site.Please refer to it from the link i provide.i'll like to save this post to be too long

now come my dao's messagedao interface

package com.project.core.dao;

import com.project.core.model.MessageDetails;
import java.util.List;

public interface MessageDAO  extends GenericDAO<MessageDetails, Long>{
//Message class is on of my pojo
public List<Message> GetAllByStatus(String status);


}

its implementation is messagedaoimpl:

public class MessageDAOImpl extends GenericDAOImpl <Message, Long> implements MessageDAO {

// mySContainer is an interface which my HibernateUtils implement
  mySContainer sessionManager;

/**
 *
 */
public MessageDAOImpl(){}

/**
 *
 * @param sessionManager
 */
public MessageDAOImpl(HibernateUtils sessionManager){
this.sessionManager = sessionManager;
 }
 //........ plus other methods 
}

here is my HibernatUtils

public class HibernateUtils implements SessionContainer {
private final SessionFactory sessionFactory;
private Session session;

public HibernateUtils() {
    this.sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}

public HibernateUtils(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

/**
 *
 * this is the function that return a session.So i'm free to implements any type of session in here.
 */
public Session requestSession() {
//        if (session != null || session.isOpen()) {
//            return session;
//        } else {
        session = sessionFactory.openSession();

//        }
    return session;
  }
}

So in my understanding while using spring(will provide the conf), i'ld wire sessionFactory to my HiberbernateUtils and then wire its method RequestSession to the Session Property of the GenericDAOImpl (the one from the link provided).

here is my spring config core.xml

<bean id="sessionManager" class="com.project.core.dao.hibernate.HibernateUtils">
    <constructor-arg ref="sessionFactory" />
</bean>   
<bean id="messageDao" class="com.project.core.dao.hibernate.MessageDAOImpl">
    <constructor-arg ref="sessionManager"/>

    </bean>
<bean id="genericDAOimpl" class="com.project.core.dao.GenericDAO">
    <property name="session" ref="mySession"/>
    </bean>
    <bean id="mySession" factory-bean="com.project.core.dao.SessionContainer" factory-method="requestSession"/>

now my test is this

public class MessageDetailsDAOImplTest  extends AbstractDependencyInjectionSpringContextTests{


 HibernateUtils sessionManager = (HibernateUtils) applicationContext.getBean("sessionManager");
MessageDAO messagedao  =(MessageDAO) applicationContext.getBean("messageDao");



static Message[] message = new Message[]
{
    new Message("text",1,"test for dummies 1","1234567890","Pending",new Date()),
    new Message("text",2,"test for dummies 2","334455669990","Delivered",new Date())        
};


public MessageDAOImplTest() {
}

@Override
protected String[] getConfigLocations(){
    return new String[]{"file:src/main/resources/core.xml"};
}

  @Test
  public void testMakePersistent() {
      System.out.println("MakePersistent");
     messagedao.makePersistent(message[0]);
     Session session = sessionManager.RequestSession();
     session.beginTransaction();
     MessageDetails fromdb = ( Message) session.load(Message.class, message[0].getMessageId());
     assertEquals(fromdb.getMessageId(), message[0].getMessageId());
     assertEquals(fromdb.getDateSent(),message.getDateSent());
     assertEquals(fromdb.getGlobalStatus(),message.getGlobalStatus());
     assertEquals(fromdb.getNumberOfPages(),message.getNumberOfPages());

  }

i'm having this error

exception in constructor testMakePersistent(java.lang.NullPointerException at com.project.core.dao.hibernate.MessageDAOImplTest)

with this stack : at com.project.core.dao.hibernate.MessageDAOImplTest.(MessageDAOImplTest.java:28) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at junit.framework.TestSuite.createTest(TestSuite.java:61) at junit.framework.TestSuite.addTestMethod(TestSuite.java:283) at junit.framework.TestSuite.(TestSuite.java:146) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:481) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1031) at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:888) ))

How to actually make this one work.I know this is a lot to stuffs and i'm thanking you for reading it.Please give me a solution.How would you do this? thanks

A: 

It seems to be failing to invoke the MessageDAOImplTest constructor, but since it is empty, I'm guessing the problem actually lies in the initialization of the member variables. Which line is line 28? You can try moving the initialization logic to the constructor body and step through it with a debugger to pinpoint the problem.

By the way, your approach has a problem in that the DAOs are singletons shared among all threads, but Hibernate sessions must not be shared across threads, so you need to store them as a ThreadLocal. If you use Spring for session management, this happens automatically. Maybe this isn't important to you because this is an "experiment", but I thought I'd bring it up.

Rob H
A: 

The first problem I can see, is that class GenericDaoImpl is supposed to be abstract (according to the hibernate link you provided), and you try to instantiate it in your spring config (by declaring bean 'genericDAOImpl').

You can set the session property directly on the 'messageDao' bean (obviously because MessageDAOImpl extends GenericDAOImpl). So I guess your spring config should look more like this:

<bean id="sessionManager" class="com.project.core.dao.hibernate.HibernateUtils">
  <constructor-arg ref="sessionFactory" />
</bean>   
<bean id="messageDao" class="com.project.core.dao.hibernate.MessageDAOImpl">
  <constructor-arg ref="sessionManager"/>
  <property name="session" ref="mySession"/>
</bean>
<bean id="mySession" factory-bean="com.project.core.dao.SessionContainer" factory-method="requestSession"/>

I hope this helps. This was my first answer on SO :-).

thanks dude you made me realize a mistake.thanks i think it's alright now
black sensei
+2  A: 

Greetings... I think you are making it more complicated than it is. :)

If you are using Spring and Hibernate (which you are), you don't really need to create your own HibernateUtils to manage the session. HibernateUtils is almost required if you don't use Spring, or else it seems redundant. It is tedious, it is one extra code you need to maintain, and you probably are not going to get it right. Your HibernateUtils doesn't seem to be implemented correctly, by the way.

Here's how I would do it:-

  1. You need to create a sessionFactory bean:-

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>// .. hbm files, omitted for brevity</value>
        </list>
    </property>
    <property name="hibernateProperties">
        // .. dialect, etc... omitted for brevity
    </property>
    </bean>
    
  2. Wire this sessionFactory into your DAO (, and you need a setter in your DAO too):-

    <bean id="messageDao" class="com.project.core.dao.hibernate.MessageDAOImpl">
    <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    
  3. To acquire the connection in your dao, just do sessionFactory.getCurrentSession(). That's it.

You do the same thing by wiring the sessionFactory into your testcase.

Here's some reference if you wish to know how to integrate Spring with Hibernate: http://static.springsource.org/spring/docs/2.5.x/reference/orm.html

limc