views:

841

answers:

2

Hi,

I have an issue with navigation in my simple jsf system.

I have MainBean that has two methods: public String register() and public String login().

I have played with faces-config.xml for several hours and I feel like I miss something very important because I think like I have tried all simple solutions so far :).

I have added the MySQL connector (jdbc) to Tomcat's lib folder and I am able to register the table to MySQL database. It even allows my users to log in to the page.

The only problem is that I can't use navigation in any other page than login.xhtml. Seems like navigation is only active on this one. I tried to use <from-view-id>* but is no joy. I am sure that there is a simple fix for that and someone will come up with correct solution soon. Let's skip all the MySQL part and try to fix the navigation issue please.

Here is the faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    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_1_2.xsd"
    version="1.2">
  <application>
    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>    
  </application>
 <managed-bean>
  <managed-bean-name>mainBean</managed-bean-name>
  <managed-bean-class>dk.itu.beans.MainBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>
 <managed-bean>
  <managed-bean-name>registerBean</managed-bean-name>
  <managed-bean-class>dk.itu.beans.RegisterBean</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>
 <navigation-rule>
  <from-view-id>/login.xhtml</from-view-id>
  <navigation-case>
   <from-outcome>success</from-outcome>
   <to-view-id>/welcome.xhtml</to-view-id>
  </navigation-case>
        <navigation-case>
      <from-outcome>failure</from-outcome>
      <to-view-id>/login_failed.xhtml</to-view-id>
    </navigation-case>
        <navigation-case>
      <from-outcome>sign</from-outcome>
      <to-view-id>/register.xhtml</to-view-id>
    </navigation-case>
 </navigation-rule>
  <navigation-rule>
  <from-view-id>/login_failed.xhtml</from-view-id>
  <navigation-case>
  <from-outcome>back</from-outcome>
      <to-view-id>/login.xhtml</to-view-id>
  </navigation-case>
  </navigation-rule>
</faces-config>

Here the last navigation-rule from login_failed.xhtml does not work at all.

Here is login.xhtml (which is the main - starting view):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<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"&gt;
<body>
<ui:composition template="/template.xhtml">
  <ui:define name="body">
    <h:form id="helloForm">
    <h:panelGrid columns="2">
   <h:outputText value="Username2:" />
   <h:inputText id="username" value="#{mainBean.username}" />
   <h:outputText value="Password:" />
   <h:inputSecret id="password" value="#{mainBean.password}" />
  </h:panelGrid>
  <h:commandButton value="Log in" action="#{mainBean.login}" />
  <h:commandButton value="Sign up" action="sign" />
 </h:form>
  </ui:define>  
</ui:composition>
</body>
</html>
login_failed.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<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"&gt;
<body>
<ui:composition template="/template.xhtml">
  <ui:define name="body">
<f:view>
 <h:outputText value="Unknown username or password." />
 <h:commandButton value="Sign up" action="sign" />
 <h:commandButton value="Log in" action="back" />
</f:view>
</ui:define>  
</ui:composition>
</body>
</html>

Here I tried many options. I used action="#{mainBean.register})" method that returns "sign" string and none of these worked. There is one more file (not specified in faces-config.xml file, because did not work either - but going from login.xhtml by button works fine. I tried to manage navigation from login_failed.xhtml first, then I will apply the same rule for registration to come back to login page when customer registers his nick name).

Here is register.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<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"&gt;
<body>
<ui:composition template="/template.xhtml">
  <ui:define name="body">
    <h:form id="helloForm">
    <h:panelGrid columns="2">
       <h:outputText value="User Name:"/>
      <h:inputText type="text" id="userName" value=""/>
   <h:outputText value="Password:"/>
      <h:inputSecret type="text" id="userPassword" value=""/>
      <h:outputText value="Member Level:"/>
      <h:selectOneRadio value="">
                              <f:selectItem itemLabel="Platinium" itemValue="Platinum" />
                              <f:selectItem itemLabel="Gold" itemValue="Gold" />
                              <f:selectItem itemLabel="Normal" itemValue="Normal" />
                          </h:selectOneRadio>
      <h:outputText value="Full Name:"/>
      <h:inputText type="text" id="userFull" value=""/>
      <h:outputText value="Address:"/>
      <h:inputTextarea type="text" id="userAddress" value=""/>
      <h:outputText value="Zip Code:"/>
      <h:inputText type="text" id="userZip" value=""/>
      <h:outputText value="City:"/>
      <h:inputText type="text" id="userCity" value=""/>
   <h:commandButton value="Sign Up" action="#{mainBean.register}" />
    </h:panelGrid>
    </h:form>
  </ui:define>  
</ui:composition>
</body>
</html>

Basicaly mainBean.register now calls the database and returns string, but obviously it doesn't navigate to any view (but gives an entry to database).

I believe it is simple fix for most of the experienced web developers and any help will be greatly appreciated.

I use eclipse, tomcat 6 and Widows Vista if that helps :)

Thank you in advance. Kindest regards.

+2  A: 

In general I can recommend trying to get something simple working prior to moving on to the advanced stuff like templating. A few pointers:

  • Use redirect in the navigation rule on the login page. This way you don't need any special hoopla to get the back button working.
  • Its generally a bad idea to create the session bean prior to the login being validated. A common solution is to use a request scoped identity bean on the login page, then inject this into a LoginAction which validates the credentials and creates the user session.

I have a rather complete Facelets/JSF2 sample online that demonstrates this behaviour:

Feel free apply the copy-paste design pattern to your code as much as you like.

Lars Tackmann
A: 

UICommand components ought to be placed inside an UIForm element. In login_failed.xhtml you're forgotten use a h:form. Add it and it will work.

BalusC