0
votes

I'm new to spring and jsf and I'm trying to redirect my JSF page after submit to spring controller class . I'm able to redirect however when it calls another method inside my controller method , hitting Null Pointer exception . Please advise.

Thanks, Vinoth

Login.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
    </h:head>
    <h:body>

        <center>
            <ui:composition template="/BasicTemplate.xhtml">
                <ui:define name="content">
                    <h:form>
                        <h:panelGrid columns="2" bgcolor="yellow" border="10"
                                     style="height: 127px; width: 481px;  ">
                            <f:facet name="header">
                                <h:outputText value="LOGIN PAGE"></h:outputText>
                            </f:facet>
                            <h:outputText id="user" value="Username"></h:outputText>
                            <h:inputText id="userName" label="userName" value="#{LoginForm.userName}" required="true"
                                         requiredMessage="Username is mandatory" validatorMessage="username is mandatory">
                            </h:inputText>
                            <h:message for="userName" style="color: red;" />
                            <br></br>
                            <h:outputText id="passWord" value="Password"></h:outputText>
                            <h:inputSecret id="pass" value="#{LoginForm.passWord}" required="true"
                                           requiredMessage="Password is mandtory">
                                <f:validateLength minimum="5" maximum="10" />
                            </h:inputSecret>
                            <h:message for="pass" style="color: red;" />
                        </h:panelGrid>
                        <h:commandButton value="Login" action="#{loginController.validatelogin(LoginForm)}"/>
                    </h:form>
                </ui:define>
            </ui:composition>
        </center>
    </h:body>

</html>

below is my controller class

package com.BillingSolution.Login;

import com.BillingSolution.Form.LoginForm;
import javax.faces.bean.ManagedBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller

public class LoginController {

    @Autowired
    private LoginService loginservice;

    @RequestMapping("/loginvalidate")
    public String validatelogin(LoginForm request) {
        String result = loginservice.ValidateLogin(request);
        return result;
    }

    @RequestMapping("/adduser")
    public String adduser(LoginForm param) {
         String result = loginservice.adduser(param);
         return result;
    }

}

Below is my jsf config file

<faces-config version="2.1"
              xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd">
    <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
    <managed-bean>
        <managed-bean-name>LoginForm</managed-bean-name>
        <managed-bean-class>com.BillingSolution.Form.LoginForm</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    <navigation-rule>
        <display-name>/login.xhtml</display-name>
        <from-view-id>/login.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>errorLogin</from-outcome>
            <to-view-id>footer.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>
    <navigation-rule>
        <display-name>/login.xhtml</display-name>
        <from-view-id>/login.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>successLogin</from-outcome>
            <to-view-id>header.xhtml</to-view-id>
            <redirect/>
        </navigation-case>
    </navigation-rule>

</faces-config>

below is the web.xml

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>login.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

Dispatcher-servlet.xml

    <mvc:annotation-driven/>  
    <mvc:default-servlet-handler/>
    <context:annotation-config />
    <context:component-scan base-package="com.BillingSolution" />

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
    <bean id="jspViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="messageSource"
          class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          p:location="/WEB-INF/jdbc.properties" />

    <bean id="dataSource"
          class="com.BillingSolution.MyCustomBasicDataSource.MyCustomBasicDataSource" destroy-method="close"
          p:driverClassName="${jdbc.driverClassName}"
          p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
          p:password="${jdbc.password}" />

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>

        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.jdbc.use_get_generated_keys">true</prop>
            </props>
        </property>
    </bean>
     <!-- Hibernate Transaction Manager -->
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory"/>
      </bean>
      <!-- Activates annotation based transaction management -->
         <tx:annotation-driven transaction-manager="transactionManager"/>
      <!--
       Most controllers will use the ControllerClassNameHandlerMapping above, but
       for the index controller we are using ParameterizableViewController, so we must
       define an explicit mapping for it.
       -->  
        <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
        <property name="mappings">
            <props>
                <prop key="index.htm">indexController</prop>
            </props>
        </property>
        </bean>
         <bean name="indexController"
          class="org.springframework.web.servlet.mvc.ParameterizableViewController"
          p:viewName="index" />

       </beans>

LoginService

package com.BillingSolution.Login;

import com.BillingSolution.Form.LoginForm;

public interface LoginService {

    public String ValidateLogin (LoginForm request);
    public String adduser(LoginForm request);

}

LoginServiceImpl

package com.BillingSolution.Login;

import com.BillingSolution.Form.LoginForm;
import com.BillingSolution.User.LoginDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private LoginDAO logindao;

    @Transactional
    @Override
    public String ValidateLogin(LoginForm request) {
        String userName = request.getUserName();
        String passWord = request.getPassWord();
        System.out.println("=======================================" + userName);
        String result = logindao.loginvalidation(userName, passWord);
        return result;
    }

    @Transactional
    @Override
    public String adduser(LoginForm request) {
        String userName = request.getUserName();
        String passWord = request.getPassWord();
        System.out.println("=======================================" + userName);
        String result = logindao.adduser(userName, passWord);
        return result;
    }
}

applicationContext.xml

<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?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:p="http://www.springframework.org/schema/p"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

  <!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
     <bean id="loginservice" class="com.BillingSolution.Login.LoginServiceImpl"></bean>

ERROR :

<Aug 28, 2014 12:01:57 AM SGT> <Warning>     <javax.enterprise.resource.webcontainer.jsf.lifecycle> <BEA-000000> <#  {loginController.validatelogin(LoginForm)}: javax.el.PropertyNotFoundException:  //C:/Users/Vinoth/Documents/NetBeansProjects/BillingSolution/build/web/login.xhtml @33,110    action="#{loginController.validatelogin(LoginForm)}": Target Unreachable, identifier  'loginController' resolved to null
  javax.faces.FacesException: #{loginController.validatelogin(LoginForm)}:  javax.el.PropertyNotFoundException:  //C:/Users/Vinoth/Documents/NetBeansProjects/BillingSolution/build/web/login.xhtml @33,110  action="#{loginController.validatelogin(LoginForm)}": Target Unreachable, identifier  'loginController' resolved to null
    at    com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at  com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    Truncated. see log file for complete stacktrace
Caused By: javax.faces.el.EvaluationException: javax.el.PropertyNotFoundException: //C:/Users/Vinoth/Documents/NetBeansProjects/BillingSolution/build/web/login.xhtml @33,110 action="#{loginController.validatelogin(LoginForm)}": Target Unreachable, identifier 'loginController' resolved to null
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:95)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
Truncated. see log file for complete stacktrace
   Caused By: javax.el.PropertyNotFoundException: //C:/Users/Vinoth/Documents/NetBeansProjects/BillingSolution/build/web/login.xhtml @33,110 action="#{loginController.validatelogin(LoginForm)}": Target Unreachable, identifier 'loginController' resolved to null
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:107)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
at  com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
Truncated. see log file for complete stacktrace
1
Looks like you loginservice is not autowired. Add the loginservice implementation and the context.xmlJens
@Jens , this code works fine if I use JSP using this "<form name="LoginForm" action="loginvalidate" method="post">"Vinoth
Look here for an example spring jsf integration.Jens
I bother how all of this can even work without the Spring EL resolver...Xtreme Biker

1 Answers

0
votes

In your project, JSF is not aware of Spring managed beans. To do that, you will have to configure the JSF ELResolver that delegates to the Spring root WebApplicationContext, resolving name references to Spring-defined beans.

Configure this resolver in your faces-config.xml file as follows:

   <application>
     ...
     <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
   </application>

All your JSF expressions can then implicitly refer to the names of Spring-managed service layer beans, for example in property values of JSF-managed beans:

<managed-bean>
     <managed-bean-name>myJsfManagedBean</managed-bean-name>
     <managed-bean-class>example.MyJsfManagedBean</managed-bean-class>
     <managed-bean-scope>session</managed-bean-scope>
     <managed-property>
       <property-name>mySpringManagedBusinessObject</property-name>
       <value>#{mySpringManagedBusinessObject}</value>
     </managed-property>
   </managed-bean>
with "mySpringManagedBusinessObject" defined as Spring bean in applicationContext.xml:
   <bean id="mySpringManagedBusinessObject" class="example.MySpringManagedBusinessObject">
     ...
   </bean>

The above is from the Spring javadocs itself.

After this, you can remove the @ManagedBean annotation from your LoginController since Spring will manage it and create its bean injecting the LoginService into it correctly.

You can then refer to the LoginController in your .xhtml using its default bean name as follows:

<h:commandButton value="Login" action="#{loginController.validatelogin(LoginForm)}"/>

On a side note, there are many violations of naming conventions in your project. You should consider refactoring to the standard conventions.