1

The UsersDAOImpl class is supposed to add a new user when I run the file as a JUnit test, but I keep getting a NullPointerException when I call sessionFactory.getCurrentSession() and I don't know why.

The session factory is put in the beans.xml.

The credentials to the database were removed for obvious reasons.

[beans.XML]

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
        <!-- enable autowiring -->
        <context:component-scan base-package="src"></context:component-scan>
        <!-- enable @Transactional -->
        <tx:annotation-driven />
        <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
            <property name="username" value="{Master}"></property>
            <property name="password" value="{password}"></property>
            <property name="url" value="{url}"></property>
        </bean>
        <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="myDataSource"></property>
            <property name="packagesToScan" value="src"></property>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.format_sql">true</prop>
                </props>
            </property>
        </bean>
        <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="mySessionFactory">
    </property> 
                </bean>
        <bean id="usersDAO" class="dao.UsersDAOImpl">
            <property name="sessionFactory" ref="mySessionFactory">        </property>
        </bean>
     </beans>

[UsersDAOImpl.java]

package dao;

import static org.junit.Assert.*;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import customExceptions.*;
import util.Debug;
import util.HibernateUtil;
import domain.Users;
@Transactional
public class UsersDAOImpl implements UsersDAO {

@Autowired
private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionfactory) {
    this.sessionFactory = sessionfactory;
}

@Test
public void testPush() {
    try {
        push(new Users("username6", "email@gmail.com", "password", "firstName", "lastName", false));
    } catch (UserNameTakenException e) {
        e.printStackTrace();
        fail();
    } catch (InvalidNameException e) {
        e.printStackTrace();
        fail();
    }
}

/**
 * Adds a new user to the database
 * 
 * @param newUser
 *            The user to be added
 * @throws UserNameTakenException
 *             In the case a username is taken
 * @throws InvalidNameException
 *             If a field is left blank, but front end should prevent that
 */
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void push(Users newUser) throws UserNameTakenException, InvalidNameException {
    // For debugging purposes:
    Debug.printMessage(this.getClass(), "push()", "invoked");
    // Check if there are any empty Strings
    if (newUser.getUsername().isEmpty() || newUser.getPassword().isEmpty() || newUser.getFirstName().isEmpty()
            || newUser.getLastName().isEmpty()) {
        throw new InvalidNameException("There is an empty String");
    }




    // Get the session
    //THIS IS WHERE I GET THE EXCEPTION
    Session sess = sessionFactory.getCurrentSession();




    // Check to see if the username is taken
    Users users = getUserByName(newUser.getUsername());
    // If the list is not empty, a user with the name was found
    if (users != null) {
        sess.close();
        throw new UserNameTakenException("The username was found in the database");
    } else {
        // Otherwise, add the new user
        // Debug
        Debug.printMessage(this.getClass(), "push()", "username available.");
        Debug.printErrorMessage(this.getClass(), "push()", "saving " + newUser.getUsername());
        sess.save(newUser);
        sess.close();
    }

}

/**
 * Updates the User's password in the database
 * 
 * @param user
 *            The user to change
 * @param newVal
 *            The new password
 */
@Override
public void updatePassword(Users user, String newVal) {
    Debug.printMessage(this.getClass(), "updatePassword()", "invoked");
    Session sess = HibernateUtil.getSession();
    Transaction trans = sess.beginTransaction();
    user.setPassword(newVal);
    sess.update(user);
    trans.commit();
    sess.close();
}

/**
 * Updates the User's first name in the database
 * 
 * @param user
 *            The user to change
 * @param newVal
 *            The new first name
 */
@Override
public void updateFirstName(Users user, String newVal) {
    // For debugging purposes:
    Debug.printMessage(this.getClass(), "updateFirstName()", "invoked");
    Session sess = HibernateUtil.getSession();
    Transaction trans = sess.beginTransaction();
    user.setFirstName(newVal);
    sess.update(user);
    trans.commit();
    sess.close();
}

/**
 * Updates the User's last name in the database
 * 
 * @param user
 *            The user to change
 * @param newVal
 *            The new last name
 */
@Override
public void updateLastName(Users user, String newVal) {
    // For debugging purposes:
    Debug.printMessage(this.getClass(), "updateLastName()", "invoked");
    Session sess = HibernateUtil.getSession();
    Transaction trans = sess.beginTransaction();
    user.setLastName(newVal);
    sess.update(user);
    trans.commit();
    sess.close();
}

/**
 * Returns the user with the given username
 * 
 * @param username
 *            The username to find
 */
@Override
public Users getUserByName(String username) {
    // For debugging purposes:
    Debug.printMessage(this.getClass(), "getUserByName()", "invoked");
    Session sess = HibernateUtil.getSession();
    Users user = (Users) sess.get(Users.class, username);
    sess.close();
    return user;
}

/**
 * Returns a list of all users from A_USERS
 */
@Override
public List<Users> getAllUsers() {
    // For debugging purposes:
    Debug.printMessage(this.getClass(), "getAllUsers()", "invoked");
    Session sess = HibernateUtil.getSession();
    Query query = sess.getNamedQuery("getAllUsers");
    List<Users> users = query.list();
    sess.close();
    return users;
 }
}

Also, I apologize if this is formatted incorrectly. This is my first time posting a question.

The Stack Trace

java.lang.NullPointerException
at dao.UsersDAOImpl.push(UsersDAOImpl.java:65)
at dao.UsersDAOImpl.testPush(UsersDAOImpl.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

null

  • suppose you share the full stack-trace of the exception. It may be helpful. – Rajith Pemabandu Jul 28 '17 at 01:06
  • suppose your refer this [example](https://www.mkyong.com/spring/maven-spring-hibernate-annotation-mysql-example/) where `sessionFactory` is used with setter injection. – Rajith Pemabandu Jul 28 '17 at 01:16
  • Also I don't see `@Repository` in your Dao classes. refer [this](http://www.studytrails.com/frameworks/spring/spring-hibernate-session-factory-annotation/) also – Rajith Pemabandu Jul 28 '17 at 01:24
  • 1
    Why do you have a `@Test` method in your class? That should be in a separate test class that uses the Spring test library to load the context. You are not doing any of those and of course it will be null. Basically you are ignoring your configuration. – M. Deinum Jul 28 '17 at 05:45

2 Answers2

0

The sessionFactory field is null.

As for why, I can only guess. You're both auto-wiring the sessionFactory field but also injecting it as a property via its configuration in the applicationContext.xml. Do one or the other, not both, and see what happens.

RichW
  • 2,004
  • 2
  • 15
  • 24
-1

A session is opened whenever getCurrentSession() is called for the first time and closed when the transaction ends. This creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.

We can use getCurrentSession() method when our transaction runs long time. To use this method we need to configure one property in hibernate.cfg.xml file. The property is

   <propertyname="hibernate.current_session_context_class">thread</property>

Values for the current_session_context_class will be, thread(local transaction) managed jta(global transaction)

  1. thread - session bound to a thread, for single thread execution if you call a getCurrentSession() then it will return you a same session object.

  2. managed - this provided for managing session from some external entity, something like intercepter. maintaining session in a ThreadLocal same as a "thread" type, but having a different methods like bind(), unbind(), hasbind() to be used by external entity to maintain session in a context.

  3. jta - session will be bound to a transaction, as we says a transaction then we need application server for using this context class.

     public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
        if ( currentSessionContext == null ) {
           throw new HibernateException( "No CurrentSessionContext configured!" );
        }
        return currentSessionContext.currentSession();  }
    

Or Try This

Session session = sessionFactory.getCurrentSession();

if (session.isOpen()) {
    session.close();
}

TransactionSynchronizationManager.unbindResource(sessionFactory);
TransactionSynchronizationManager.clearSynchronization();
Tehmina
  • 205
  • 2
  • 8
  • When using Spring do'n't mess around with the `hibernate.current_session_context_class`. Especially don't set it to `thread` as that will break proper integration with Spring and declarative transaction management. – M. Deinum Jul 28 '17 at 05:45