简体   繁体   中英

Writing Hibernate queries in JSP gives java.lang.NullPointerException

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>WebSLCM</display-name>
  <welcome-file-list>
    <welcome-file>/WEB-INF/resources/jsp/index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/resources/jsp/404.jsp</location>
  </error-page>
</web-app>

dispatcher-servlet.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" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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.xsd 
             http://www.springframework.org/schema/mvc
             http://www.springframework.org/schema/mvc/spring-mvc.xsd
             http://www.springframework.org/schema/tx 
             http://www.springframework.org/schema/tx/spring-tx.xsd
             http://www.springframework.org/schema/aop 
             http://www.springframework.org/schema/aop/spring-aop.xsd">

    <mvc:annotation-driven />
    <!-- <mvc:default-servlet-handler/> -->
    <mvc:resources mapping="/resources/**" location="WEB-INF/resources/" />
    <context:component-scan base-package="com.slv.controller" />

    <!-- JDBC Properties -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/webslcm" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- Accounts -->
    <bean id="accountsDaoImpl" class="com.slv.daoimpl.AccountsDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Hibernate Session properties -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.slv.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <!-- ViewResolver Spring Will redirecting -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/resources/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

Jsp Page:

<%!
    @Autowired
    public AccountsDaoImpl accountsDaoImpl;
%>
<% 
    List<Object[]> list =  accountsDaoImpl.getSQLObjectValues("SELECT examId, examName FROM examtypes", session);
%>

When i run the above code in JSP, im getting java.lang.NullPointerException Exception.

Not able resolve it, did i missed anything important? What changes should i make to my code to get worked?

AccountsDaoImpl.java

public class AccountsDaoImpl implements AccountsDao{

@Autowired
    public SessionFactory sessionFactory;

public SessionFactory getSessionFactory() {
    return sessionFactory;
}

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

@Override
    public List<Object[]> getSQLObjectValues(String sqlQuery, HttpSession session2) {
        Session session=sessionFactory.openSession(); // Here im getting the below exception 
        session.beginTransaction();
        try{
            Query query = session.createSQLQuery(sqlQuery);
            List<Object[]> list=query.list();
            return list;
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            session.close();sessionFactory.close();
        }
        return null;
    }
}

Exception:

java.lang.NullPointerException
    at com.slv.daoimpl.AccountsDaoImpl.getSQLObjectValues(AccountsDaoImpl.java:384)
    at org.apache.jsp.WEB_002dINF.resources.jsp.reUsableReport_jsp._jspService(reUsableReport_jsp.java:179)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
    at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:168)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1244)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1027)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

You are not using the Spring context to generate the bean for you, basically ignoring all your Spring configuration. You could look the bean up from the application content in the JSP, but writing application code in JSP is always a bad idea! That's why I won't give a more detailed answer, don't shoot yourself in the foot on purpose. Autowire the bean in a servlet, and invoke it through a request in the JSP.

Autowiring in a servlet

You can use the SpringBeanAutowiringSupport utility class, to inject your spring beans:

public class MyServlet implements HttpServlet {

    @Autowired
    private MyBean myBean;

    public void init(ServletConfig config) {
        super.init(config);
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this);
    }
}

To enable auto-wiring in JSP, you must enable it by the help of SpringBeanAutowiringSupport by overriding jspInit() function.

So, the modified jsp Page as follows:

<%@ page import="org.springframework.beans.factory.annotation.Autowired"%>
<%@ page import="org.springframework.web.context.support.SpringBeanAutowiringSupport"%>

<%!
    public void jspInit() {
      SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,getServletConfig().getServletContext());
    } 

    @Autowired
    public AccountsDaoImpl accountsDaoImpl;
%>
<% 
    List<Object[]> list =  accountsDaoImpl.getSQLObjectValues("SELECT examId, examName FROM examtypes", session);
%>

dispatcher-servlet.xml:

You also have to add bean for AutowiredAnnotationBeanPostProcessor : <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

So, Modified version:

 <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" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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.xsd 
             http://www.springframework.org/schema/mvc
             http://www.springframework.org/schema/mvc/spring-mvc.xsd
             http://www.springframework.org/schema/tx 
             http://www.springframework.org/schema/tx/spring-tx.xsd
             http://www.springframework.org/schema/aop 
             http://www.springframework.org/schema/aop/spring-aop.xsd">

    <mvc:annotation-driven />
    <mvc:resources mapping="/resources/**" location="WEB-INF/resources/" />
   <context:component-scan base-package="com.slv.controller" />
  <!--   Write Hibernate queries in JSP -->
   <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> 

    <!-- JDBC Properties -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/webslcm" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- Accounts -->
    <bean id="accountsDaoImpl" class="com.slv.daoimpl.AccountsDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Hibernate Session properties -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.slv.model" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>

    <!-- ViewResolver Spring Will redirecting -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/resources/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

web.xml:

You have to add context-param and listener: org.springframework.web.context.ContextLoaderListener in web.xml

Modified:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>WebSLCM</display-name>
  <welcome-file-list>
    <welcome-file>/WEB-INF/resources/jsp/index.jsp</welcome-file>
  </welcome-file-list>
    <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>    

<!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

  <servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/resources/jsp/404.jsp</location>
  </error-page>
</web-app>

I think it would be best to make the sql call in the service layer and populate a form backing object in the controller and then send the list of objects back to the JSP to be displayed. Is there a reason why the SQL calls need to be made in the JSP?

You can't do this

AccountsDaoImpl accountsDaoImpl = new AccountsDaoImpl();

You need to get accountsDaoImpl from a Spring context to have

@Autowired
public SessionFactory sessionFactory;

is auto wired by Spring.

I think you should use setter of the sessionfactory.

protected HibernateTemplate template = null;

/**
 * Sets Hibernate session factory and creates a 
 * <code>HibernateTemplate</code> from it.
 */
public void setSessionFactory(SessionFactory sessionFactory) {
    template = new HibernateTemplate(sessionFactory);
}

I see that you have mixed annotation driven and non-annotation driven styles. Try:

  1. Removing the accountsDaoImpl bean definition from your spring config xml

  2. Either removing the setter method setSessionFactory from your AccountsDaoImpl or moving the Autowired annotation from the sessionFactory instance variable to the the setSessionFactory method. I think either will do but you have both which is contributing to your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM