Hi, I'm a software architect and we have a major project coming where I thought our dev team should try new things. So I decided to replace Struts (default option :P) with JSF and Shale. I thought that it would be good when I personally know the limits of JSF and Shale first before I put them into our proposal. For this I've written a small app where the user has to input his personal data in wizard style (dialog) but somehow I cannot go further than the first page >:( No errors or exceptions or something but the first dialog screen keeps opened again and again. I tried to understand what goes on in the Shale's usecases example app (the login and profile creation is also a dialog) and mostly copy/pasted the dialog-config.xml, the jsps and backing beans (I couldn't get the usecases login part to run btw) but with no luck :'(
Then I thought my "lone wolf" time is up and I should go and ask someone smarter ;) Oh, becaause the upcoming project is a monster I decided to use Tiles aswell and MyFaces with Tomahawk extensions. My web.xml looks like this: <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4" id="WebApp_ID"> <display-name>JSFTest</display-name> <!--context-param> <description> Comma separated list of URIs of (additional) faces config files. (e.g. /WEB-INF/my-config.xml) See JSF 1.0 PRD2, 10.3.2 Attention: You do not have to put /WEB-INF/faces-config.xml in here. </description> <param-name>javax.faces.CONFIG_FILES</param-name> <param-value>/WEB-INF/managed-beans.xml,/WEB-INF/navigation.xml</param-value> </context-param--> <context-param> <param-name>org.apache.commons.chain.CONFIG_WEB_RESOURCE</param-name> <param-value>/WEB-INF/chain-config.xml</param-value> </context-param> <!-- context-param> <param-name>org.apache.shale.dialog.CONFIGURATION</param-name> <param-value>/WEB-INF/dialog-config.xml</param-value> </context-param --> <context-param> <description> State saving method: "client" or "server" (= default) See JSF Specification 2.5.3 </description> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <context-param> <description> Only applicable if state saving method is "server" (= default). Defines the amount (default = 20) of the latest views are stored in session. </description> <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name> <param-value>20</param-value> </context-param> <context-param> <description> Only applicable if state saving method is "server" (= default). If true (default) the state will be serialized to a byte stream before it is written to the session. If false the state will not be serialized to a byte stream. </description> <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> <param-value>true</param-value> </context-param> <context-param> <description> Only applicable if state saving method is "server" (= default) and if org.apache.myfaces.SERIALIZE_STATE_IN_SESSION is true (= default) If true (default) the serialized state will be compressed before it is written to the session. If false the state will not be compressed. </description> <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name> <param-value>true</param-value> </context-param> <context-param> <description> This parameter tells MyFaces if javascript code should be allowed in the rendered HTML output. If javascript is allowed, command_link anchors will have javascript code that submits the corresponding form. If javascript is not allowed, the state saving info and nested parameters will be added as url parameters. Default: "true" </description> <param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name> <param-value>false</param-value> </context-param> <context-param> <description> If true, rendered HTML code will be formatted, so that it is "human readable". i.e. additional line separators and whitespace will be written, that do not influence the HTML code. Default: "true" </description> <param-name>org.apache.myfaces.PRETTY_HTML</param-name> <param-value>true</param-value> </context-param> <context-param> <description> If true, a javascript function will be rendered that is able to restore the former vertical scroll on every request. Convenient feature if you have pages with long lists and you do not want the browser page to always jump to the top if you trigger a link or button action that stays on the same page. Default: "false" </description> <param-name>org.apache.myfaces.AUTO_SCROLL</param-name> <param-value>true</param-value> </context-param> <!--context-param> <description> Used for encrypting view state. Only relevant for client side state saving. See MyFaces wiki/web site documentation for instructions on how to configure an application for diffenent encryption strengths. </description> <param-name>org.apache.myfaces.secret</param-name> <param-value>NzY1NDMyMTA=</param-value> </context-param--> <context-param> <description> Validate managed beans and navigation rules. </description> <param-name>org.apache.myfaces.validate</param-name> <param-value>true</param-value> </context-param> <!-- Tiles ViewHandler config file --> <context-param> <description> Tiles configuration definition files and a listener need to be defined. the listener will initialize JspTilesViewHandlerImpl with tiles definitions. </description> <param-name>tiles-definitions</param-name> <param-value>/WEB-INF/tiles-defs.xml</param-value> </context-param> <servlet> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- Shale Application Controller Filter --> <filter> <filter-name>shale</filter-name> <filter-class>org.apache.shale.faces.ShaleApplicationFilter</filter-class> </filter> <!-- Tomahawk extension --> <filter> <filter-name>extensionsFilter</filter-name> <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class> <init-param> <description> Set the size limit for uploaded files. Format: 10 - 10 bytes 10k - 10 KB 10m - 10 MB 1g - 1 GB </description> <param-name>uploadMaxFileSize</param-name> <param-value>100m</param-value> </init-param> <init-param> <description> Set the threshold size - files below this limit are stored in memory, files above this limit are stored on disk. Format: 10 - 10 bytes 10k - 10 KB 10m - 10 MB 1g - 1 GB </description> <param-name>uploadThresholdSize</param-name> <param-value>100k</param-value> </init-param> </filter> <filter-mapping> <filter-name>extensionsFilter</filter-name> <url-pattern>*.jsf</url-pattern> </filter-mapping> <filter-mapping> <filter-name>extensionsFilter</filter-name> <url-pattern>/faces/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>shale</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class> </listener> <listener> <listener-class>org.apache.commons.chain.web.ChainListener</listener-class> </listener> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> And my dialog-config looks like this <!DOCTYPE dialogs PUBLIC "-//Apache Software Foundation//DTD Shale Dialog Configuration 1.0//EN" "http://struts.apache.org/dtds/shale-dialog-config_1_0.dtd"> <dialogs> <dialog name="Edit Person" start="Setup"> <!-- Global transition definitions --> <transition outcome="cancel" target="Cancel"/> <transition outcome="finish" target="Finish"/> <action name="Setup" method="#{personActions.setup}"> <transition outcome="success" target="Page 1"/> </action> <view name="Page 1" viewId="/editPerson.jsp"> <transition outcome="next" target="Page 2"/> </view> <view name="Page 2" viewId="/editPerson1.jsp"> <transition outcome="next" target="Page 3"/> <transition outcome="previous" target="Page 1"/> </view> <view name="Page 3" viewId="/editPerson2.jsp"> <transition outcome="previous" target="Page 2"/> </view> <action name="Cancel" method="#{personActions.cancel}"> <transition outcome="success" target="Exit"/> </action> <action name="Finish" method="#{personActions.finish}"> <transition outcome="name" target="Page 1"/> <transition outcome="success" target="Exit"/> <transition outcome="contact" target="Page 2"/> </action> <end name="Exit" viewId="/listPersons.jsp"/> </dialog> </dialogs> The Page 1 view keeps coming up every time when I click Next editPerson.jsp looks like this <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t" %> <%@ taglib uri="http://struts.apache.org/shale/core" prefix="s" %> <f:view> <h:form id="editPersonForm"> <h:panelGrid columns="2"> <h:outputText value="First name:" /> <h:inputText id="firstName" value="#{personBean.firstName}" /> <h:outputText value="Last name:" /> <h:inputText id="lastName" value="#{personBean.lastName}" /> <h:outputText value="Title" /> <h:inputText id="titleName" value="#{personBean.title}" /> <h:outputText value="Date of birth:" /> <t:inputDate id="dateOfBirth" popupCalendar="false" type="date" value="#{personBean.dateOfBirth}" /> </h:panelGrid> <s:token id="token"/> <h:panelGrid columns="4"> <h:commandButton id="previous" action="previous" disabled="true" value="<<< Previous page"/> <h:commandButton id="next" action="next" value="Next page >>>"/> <h:commandButton id="finish" action="finish" value="Finish"/> <h:commandButton id="cancel" action="cancel" immediate="true" value="Cancel"/> </h:panelGrid> <h:message for="token"/> </h:form> </f:view> and faces-config.xml <faces-config> <application> <view-handler>org.apache.myfaces.tomahawk.application.jsp.JspTilesViewHandlerImpl</view-handler> </application> <application> <locale-config> <default-locale>ee_ET</default-locale> <supported-locale>ee</supported-locale> <supported-locale>en</supported-locale> </locale-config> </application> <navigation-rule> <from-view-id>/listPersons.jsp</from-view-id> <!-- navigation-case> <from-outcome>edit</from-outcome> <to-view-id>/editPerson.jsp</to-view-id> </navigation-case--> <navigation-case> <from-outcome>remove</from-outcome> <to-view-id>/removePerson.jsp</to-view-id> </navigation-case> <!-- navigation-case> <from-outcome>change</from-outcome> <to-view-id>/editPerson.jsp</to-view-id> </navigation-case--> </navigation-rule> <managed-bean> <managed-bean-name>personDataBean</managed-bean-name> <managed-bean-class>jsftest.beans.PersonBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>personActions</managed-bean-name> <managed-bean-class>jsftest.faceforms.PersonBeanActions</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> </faces-config> and the PersonBeanAction's most interesting methods look like this public String setup() { log.info("PersonBeanAction is setting up"); // Configure a state object PersonBean state = new PersonBean(); state.setCreating(true); // Register our state as the data object for this dialog, and continue setValue("#{dialog.data}", state); log.info("set up complete"); return SUCCESS; } public String finish() { // Acquire our state information PersonBean state = (PersonBean) getValue("#{dialog.data}"); boolean okFirstName = true; boolean okLastName = true; boolean okTelNo = true; // Validate required fields if creating if (state.isCreating()) { if ((state.getFirstName() == null) || (state.getFirstName().length() < 1)) { error(messages.getMessage("profile.firstName")); okFirstName = false; } if ((state.getLastName() == null) || (state.getLastName().length() < 1)) { error(messages.getMessage("profile.lastName")); okLastName = false; } if (state.getEmployment().size() > 0) { boolean contactFound = false; for (Iterator it = state.getEmployment().iterator(); it.hasNext();) { Employer emp = (Employer) it.next(); if (emp.getEmails().size() > 0 || emp.getPhoneNos().size() > 0) { contactFound = true; break; } } if (!contactFound) { error(messages.getMessage("profile.contact")); okTelNo = false; } } else { error(messages.getMessage("profile.contact")); okTelNo = false; } } // Return appropriate outcome on validation failures if (!okFirstName || !okLastName) { log.info("PersonBeanAction finished with error (no first or last name)"); return NAME; } else if (!okTelNo) { log.info("PersonBeanAction finished with error (no contacts)"); return CONTACT; } // Return a success outcome log.info("PersonBeanAction finished successfully"); return SUCCESS; } Has anyone have a glue where I screw up? I allready downloaded Shale's source and found out that the "next" transition won't get posted to DialogNavigationHandler class by remotely debugging my app. Why ? S.O.S !!! rgds Sander --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]