7 Replies Latest reply on Oct 13, 2011 1:25 AM by andrey.sisoyev

    RF 4 and SWF

    andyn

      Hey,

       

      i've integrated RF 4 and SWF in my web project and it work's fine, but I couldn't start transitions of spring web flow by using a4j:ajax and a4j:function. It works for a4j:commandButton, but not for non-action tags! So SWF get's an ajax request but could not detect any event by using a4j:ajax and a4j:function! How could I call a web flow transition by using a4j:ajax? In RF 3.3 I used a4j:support, but in RF 4.0 this tag doesn't exist anymore!

        • 1. RF 4 and SWF
          andyn

          here is my configuration:

           

          pom.xml

          <?xml version="1.0" encoding="UTF-8"?>

          <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

           

              ...

           

              <properties>

                 

                  ...

                 

                  <spring.version>3.0.5.RELEASE</spring.version>

                  <org.richfaces.bom.version>4.0.0.Final</org.richfaces.bom.version>

                  <spring.webflow.version>2.3.0.RELEASE</spring.webflow.version>

                 

                  ...

                 

              </properties>

           

              <!-- ====== JBoss RichFaces bom ========== -->

              <dependencyManagement>

                  <dependencies>

                      <dependency>

                          <groupId>org.richfaces</groupId>

                          <artifactId>richfaces-bom</artifactId>

                          <version>${org.richfaces.bom.version}</version>

                          <scope>import</scope>

                          <type>pom</type>

                      </dependency>

                  </dependencies>

              </dependencyManagement>

           

              <dependencies>

                 

                  ...

                 

                  <!-- ====== Spring Libraries and Dependencies on Spring ========== -->

                  <dependency>

                      <groupId>org.springframework</groupId>

                      <artifactId>spring-context</artifactId>

                      <version>${spring.version}</version>

                      <scope>runtime</scope>

                  </dependency>

                 

                  <!-- ====== JBoss RichFaces libraries ========== -->

                  <dependency>

                      <groupId>org.richfaces.ui</groupId>

                      <artifactId>richfaces-components-ui</artifactId>

                  </dependency>

                  <dependency>

                      <groupId>org.richfaces.core</groupId>

                      <artifactId>richfaces-core-impl</artifactId>

                  </dependency>

                  <dependency>

                      <groupId>org.richfaces.cdk</groupId>

                      <artifactId>annotations</artifactId>

                      <version>${org.richfaces.bom.version}</version>

                      <scope>provided</scope>

                  </dependency>

                 

                  <!-- ====== RichFaces Libraries and Dependencies on RichFaces ========== -->

                  <dependency>

                      <groupId>com.sun.faces</groupId>

                      <artifactId>jsf-api</artifactId>

                  </dependency>

                  <dependency>

                      <groupId>com.sun.faces</groupId>

                      <artifactId>jsf-impl</artifactId>

                  </dependency>

                  <dependency>

                      <groupId>javax.el</groupId>

                      <artifactId>el-api</artifactId>

                      <scope>provided</scope>

                  </dependency>

                  <dependency>

                      <groupId>javax.servlet</groupId>

                      <artifactId>servlet-api</artifactId>

                      <scope>provided</scope>

                  </dependency>

                  <dependency>

                      <groupId>javax.servlet.jsp</groupId>

                      <artifactId>jsp-api</artifactId>

                      <scope>provided</scope>

                  </dependency>

                  <dependency>

                      <groupId>javax.servlet</groupId>

                      <artifactId>jstl</artifactId>

                  </dependency>

                  <dependency>

                      <groupId>net.sourceforge.cssparser</groupId>

                      <artifactId>cssparser</artifactId>

                  </dependency>

                  

                  <!-- ====== Spring Web Flow Libraries and Dependencies ========== -->

                  <dependency>

                      <groupId>org.springframework.webflow</groupId>

                      <artifactId>spring-binding</artifactId>

                      <version>${spring.webflow.version}</version>

                  </dependency>

                  <dependency>

                      <groupId>org.springframework.webflow</groupId>

                      <artifactId>spring-js</artifactId>

                      <version>${spring.webflow.version}</version>

                  </dependency>

                  <dependency>

                      <groupId>org.springframework.webflow</groupId>

                      <artifactId>spring-webflow</artifactId>

                      <version>${spring.webflow.version}</version>

                  </dependency>

                  <dependency>

                      <groupId>org.springframework.webflow</groupId>

                      <artifactId>spring-faces</artifactId>

                      <version>${spring.webflow.version}</version>

                  </dependency>

              </dependencies>

             

              ...

             

          </project>

           

          web.xml

          <?xml version="1.0" encoding="UTF-8"?>

           

          <!DOCTYPE web-app

              PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

              "http://java.sun.com/dtd/web-app_2_3.dtd">

           

          <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_2_5.xsd"

                   version="2.5">

           

            ...

           

            <!-- Initializing JavaServer Faces, *NOT* used at runtime due to Spring Web Flow -->

            <!-- FacesServlet -->

            <servlet>

              <servlet-name>Faces Servlet</servlet-name>

              <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

              <!-- The servlet is loaded on startup to be reachable for requests. -->

              <load-on-startup>1</load-on-startup>

            </servlet>

           

            <!-- Mapping for FacesServlet -->

            <servlet-mapping>

              <servlet-name>Faces Servlet</servlet-name>

              <url-pattern>*.faces</url-pattern>

            </servlet-mapping>

           

           

            <!-- Initializing JBoss RichFaces -->

            <!-- Plugging the "Blue Sky" skin into the project -->

            <context-param>

              <param-name>org.richfaces.skin</param-name>

              <param-value>blueSky</param-value>

            </context-param>

           

            <!-- Making the RichFaces skin spread to standard HTML controls -->

            <context-param>

              <param-name>org.richfaces.enableControlSkinning</param-name>

              <param-value>false</param-value>

            </context-param>

           

           

            <!-- Initializing Spring Web Flow -->

            <!-- The front controller of this Spring Web application, responsible for handling all application requests -->

            <servlet>

              <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>

              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

              <init-param>

                <param-name>contextConfigLocation</param-name>

                <param-value>/WEB-INF/config/web-application-config.xml</param-value>

              </init-param>

              <load-on-startup>1</load-on-startup>

            </servlet>

           

            <!-- Map all /spring requests to the Dispatcher Servlet for handling -->

            <servlet-mapping>

              <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>

              <url-pattern>/swf/*</url-pattern>

            </servlet-mapping>

          </web-app>

           

          web-application-config.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:mvc="http://www.springframework.org/schema/mvc"

                 xmlns:context="http://www.springframework.org/schema/context"

                 xmlns:faces="http://www.springframework.org/schema/faces"

                 xsi:schemaLocation="http://www.springframework.org/schema/beans

                                     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

                                     http://www.springframework.org/schema/context

                                     http://www.springframework.org/schema/context/spring-context-3.1.xsd">

           

            <!-- This activates post-processors for annotation-based config -->

            <context:annotation-config/>

            <context:component-scan base-package="de"/>

           

            <!-- Imports the configurations of the different infrastructure systems of the application -->

            <import resource="webmvc-config.xml" />

            <import resource="webflow-config.xml" />

           

          </beans>

           

          webmvc-config.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"

                 xsi:schemaLocation="http://www.springframework.org/schema/beans

                                     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

           

            <!-- Maps logical view names to JSF-Files (e.g. 'search' to '/search.jsp' -->

            <bean id="jsfViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">

              <property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>

              <property name="prefix" value="/" />

              <property name="suffix" value=".jsp" />

            </bean>

           

            <!-- Maps request URIs to controllers -->

            <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

              <property name="mappings">

                <value>

                  /*-flow=flowController

                  /resource/**=resourceHandler

                  /javax.faces.resource/**=jsfResourceHandler

                  /rfRes/**=jsfResourceHandler

                </value>

              </property>

              <property name="defaultHandler">

                <!-- Selects view names to render based on the request URI: e.g. /main selects "main" -->

                <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

              </property>

            </bean>

           

            <bean id="messageSource" class="de.gui.MyResourceBundleMessageSource" />

           

            <bean id="localeResolver" class="de.gui.MySessionLocaleResolver" />

           

            <!-- Handler for requested resources -->

            <bean id="resourceHandler" class="de.gui.MyResourceServlet"/>

           

            <bean id="jsfResourceHandler" class="org.springframework.faces.webflow.JsfResourceRequestHandler"/>

           

          </beans>

           

           

          webflow-config.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:webflow="http://www.springframework.org/schema/webflow-config"

                 xmlns:faces="http://www.springframework.org/schema/faces"

                 xsi:schemaLocation="http://www.springframework.org/schema/beans

                                     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

                                     http://www.springframework.org/schema/webflow-config

                                     http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd

                                     http://www.springframework.org/schema/faces

                                     http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">

           

            <!-- Executes flows: the central entry point into the Spring Web Flow system -->

            <webflow:flow-executor id="flowExecutor">

              <webflow:flow-execution-listeners>

                <webflow:listener ref="facesContextListener"/>

              </webflow:flow-execution-listeners>

            </webflow:flow-executor>

           

            <!-- The registry of executable flow definitions -->

            <webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF/flows">

              <webflow:flow-location-pattern value="*-flow.xml" />

            </webflow:flow-registry>

           

            <!-- Handles requests mapped to the Spring Web Flow system -->

            <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">

              <property name="flowExecutor" ref="flowExecutor"/>

              <!-- Integrates the ability to use RichFaces Ajax components -->

              <property name="ajaxHandler">

                <bean class="org.springframework.faces.webflow.JsfAjaxHandler"/>

              </property>

            </bean>

           

            <!-- Configures the Spring Web Flow JSF integration -->

            <faces:flow-builder-services id="facesFlowBuilderServices" />

           

            <!-- A listener maintain one FacesContext instance per Web Flow request. -->

            <bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />

           

            <bean id="MyWebflowExceptionHandler" class="de.gui.MyWebflowExceptionHandler" />

           

          </beans>

           

           

          MyResourceBundleMessageSource

          public class MyResourceBundleMessageSource extends ResourceBundleMessageSource

          {

              public static final String BUNDLE_KEY_DELIMITER = "$";

              public static final String MESSAGE_DELIMITER = "#~#";

              private boolean isInitialized = false;

           

              @Override

              protected ResourceBundle doGetBundle(final String bundlename, final Locale targetLocale)

              {

                  return ResourceBundle.getBundle(bundlename, targetLocale, new ResourceBundle.Control()

                  {

                      @Override

                      public ResourceBundle newBundle(final String baseName,

                                                      final Locale locale,

                                                      final String format,

                                                      final ClassLoader loader,

                                                      final boolean reload) throws IOException

                      {

                          return new MyResourceBundle(baseName, locale.getLanguage());

                      }

                  });

              }

           

              @Override

              protected String resolveCodeWithoutArguments(final String code, final Locale locale)

              {

                  if (!isInitialized)

                  {

                      setBasenames(TexteUtil.getAllLanguageFiles());

                      isInitialized = true;

                  }

                  String result = null;

                  ResourceBundle bundle = null;

                  String basename = "";

                  String key = code;

                  if (code.contains(MESSAGE_DELIMITER))

                  {

                      String[] codes = code.split(MESSAGE_DELIMITER);

                      result = "";

                      for (int i = 0; i < codes.length; i++)

                      {

                          result += " " + resolveCodeWithoutArguments(codes[i], locale);

                      }

                  }

                  else

                  {

                      if (code.contains(BUNDLE_KEY_DELIMITER))

                      {

                          basename = code.substring(0, code.indexOf(BUNDLE_KEY_DELIMITER));

                          key = code.substring(code.indexOf(BUNDLE_KEY_DELIMITER) + 1);

                          bundle = getResourceBundle(basename, locale);

                      }

                      if (bundle != null)

                      {

                          try

                          {

                              result = bundle.getString(key);

                          }

                          catch (MissingResourceException ex)

                          {

                              // Assume key not found

                              // -> do NOT throw the exception to allow for checking parent message source.

                              result = null;

                          }

                      }

                      if ((bundle == null) || (result == null))

                      {

                          result = super.resolveCodeWithoutArguments(key, locale);

                      }

                  }

                  return result;

              }

           

              @Override

              protected MessageFormat resolveCode(final String code, final Locale locale)

              {

                  if (!isInitialized)

                  {

                      setBasenames(TexteUtil.getAllLanguageFiles());

                      isInitialized = true;

                  }

                  MessageFormat result = null;

                  ResourceBundle bundle = null;

                  String basename = "";

                  String key = code;

                  if (code.contains(MESSAGE_DELIMITER))

                  {

                      String[] codes = code.split(MESSAGE_DELIMITER);

                      result = new MessageFormat("");

                      for (int i = 0; i < codes.length; i++)

                      {

                          result = new MessageFormat(result.toPattern() + " " + resolveCode(codes[i], locale).toPattern());

                      }

                  }

                  else

                  {

                      if (code.contains(BUNDLE_KEY_DELIMITER))

                      {

                          basename = code.substring(0, code.indexOf(BUNDLE_KEY_DELIMITER));

                          key = code.substring(code.indexOf(BUNDLE_KEY_DELIMITER) + 1);

                          bundle = getResourceBundle(basename, locale);

                      }

                      if (bundle != null)

                      {

                          result = getMessageFormat(bundle, key, locale);

                      }

                      if ((bundle == null) || (result == null))

                      {

                          result = super.resolveCode(key, locale);

                      }

                  }

                  return result;

              }

           

              private static class MyResourceBundle extends ResourceBundle

              {

                  private final Properties props;

           

                  MyResourceBundle(final String baseName, final String locale) throws IOException

                  {

                      props = TexteUtil.getLanguageSupport(locale, baseName);

                  }

           

                  @Override

                  protected Object handleGetObject(final String key)

                  {

                      return props.getProperty(key);

                  }

           

                  @Override

                  public Enumeration<String> getKeys()

                  {

                      Vector<String> keys = new Vector<String>();

                      Enumeration<Object> keysEnum = props.keys();

                      while (keysEnum.hasMoreElements())

                      {

                          keys.add(keysEnum.nextElement().toString());

                      }

                      return keys.elements();

                  }

              }

          }

           

           

          MySessionLocaleResolver

          public class MySessionLocaleResolver extends SessionLocaleResolver
          {

              public static final String LOCALE_SESSION_ATTRIBUTE_NAME = WebUtil.SELECTED_LANGUAGE;

              public static final Locale DEFAULT_LOCALE = new Locale("en");

           

              public MySessionLocaleResolver()

              {

                  this.setDefaultLocale(DEFAULT_LOCALE);

              }

           

              @Override

              public Locale resolveLocale(final HttpServletRequest request)

              {

                  Object localeObject = WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);

                  if (localeObject == null)

                  {

                      return determineDefaultLocale(request);

                  }

                  Locale locale = new Locale(localeObject.toString());

                  if (locale == null)

                  {

                      return determineDefaultLocale(request);

                  }

                  return locale;

              }

           

              @Override

              public void setLocale(final HttpServletRequest request, final HttpServletResponse response, final Locale locale)

              {

                  WebUtils.setSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME, locale);

              }

          }

           

          MyResourceServlet

          public class MyResourceServlet extends ResourceHttpRequestHandler

          {

              public MyResourceServlet()

              {

                  super();

                  Vector<Resource> resources = new Vector<Resource>();

                  resources.add(new DefaultResourceLoader().getResource("../../"));

                  this.setLocations(resources);

              }

          }

           

           

          MyWebflowExceptionHandler

          public class MyWebflowExceptionHandler implements FlowExecutionExceptionHandler

          {

              @Override

              public boolean canHandle(final FlowExecutionException exception)

              {

                  return true;

              }

           

           

              @Override

              public void handle(final FlowExecutionException exception, final RequestControlContext context)

              {

                  exception.printStackTrace();

                  try

                  {

                      String exceptionMessage = exception.getCause().getCause().getMessage();

                      context.getMessageContext().addMessage(new MessageBuilder().error().code(exceptionMessage).build());

                  }

                  catch (Exception e)

                  {

                      context.getMessageContext().addMessage(new MessageBuilder().error().code("Allgemein"

                              + MyResourceBundleMessageSource.BUNDLE_KEY_DELIMITER + "ERR_UNKNOWN").build());

                  }

                  context.getExternalContext().requestFlowExecutionRedirect();

              }

          }

           

           

           

           

           

          test-flow.xml

          <?xml version="1.0" encoding="UTF-8"?>

          <flow xmlns="http://www.springframework.org/schema/webflow"

                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                xsi:schemaLocation="http://www.springframework.org/schema/webflow

                                    http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

            <on-start>

              <set name="conversationScope.pageName" value="'Test'"/>

              ...

            </on-start>

           

            <decision-state id="FlowStart">

              ...

            </decision-state>

           

            <view-state id="Test" view="/WEB-INF/view/Test.xhtml" model="flowScope.testBean">

              <on-entry>

                ...

              </on-entry>

              <transition on="SAVE" to="Test">

                <evaluate expression="..."/>

              </transition>

              ...

              <transition on="AJAX_TEST">

                <evaluate expression="..." result="flowScope.testVec"/>

                ...

              </transition>

            </view-state>

           

            <end-state id="FlowError" view="/error.jsp"/>

           

            <exception-handler bean="MyWebflowExceptionHandler"/>

           

          </flow>

           

           

           

           

           

          Test.xhtml

          <!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:f="http://java.sun.com/jsf/core"

                xmlns:h="http://java.sun.com/jsf/html"

                xmlns:ui="http://java.sun.com/jsf/facelets"

                xmlns:a4j="http://richfaces.org/a4j"

                xmlns:rich="http://richfaces.org/rich">

           

              <h:head>

                  <meta NAME="Author" content="..."/>

                  <TITLE>

                      <h:outputText value="#{resourceBundle....}" />

                  </TITLE>

                  ...

              </h:head>

           

              <h:body>

                  <h:form id="form1">

                 

                  ...

                 

                      <a4j:outputPanel id="showTest">

                          <h:commandButton action="SAVE" value="..." rendered="..." disabled="..." styleClass="..." />

                         

                          <h:panelGroup>

                              <h:selectOneMenu id="selectTest" ...>

                                  <f:selectItems value="..." ... />

                                  <a4j:ajax event="valueChange" render="showTest" execute="someFunction" />

                                  <a4j:jsFunction id="someFunction" name="someFunction" action="AJAX_TEST" ajaxsingle="true" />

                              </h:selectOneMenu>

                          </h:panelGroup>

                         

                          ...

                         

                      </a4j:outputPanel>

                  </h:form>

              </h:body>

          </HTML>

          • 2. Re: RF 4 and SWF
            andyn

            Could nobody help me to solve this problem?

            • 3. Re: RF 4 and SWF
              lfryc

              Hi Andy,

               

              Please take a look at https://issues.jboss.org/browse/RFPL-1430 and http://community.jboss.org/message/600290#600290 for information related to SWF integration.

              • 4. Re: RF 4 and SWF
                andyn

                Hey Lukáš,

                 

                thanks a lot for your reply! I've already read these links and I've used this information to make my config work. So it works for me perfectly to send an ajax-request, if I use an a4j:commandButton or an a4j:commandLink. But if I use a4j:functions or the like to send an ajax-request, Spring Web Flow gets a request, but couldn't detect an (ajax)event and so no transition is triggerd! So I'm not able to use "non-action"-Components like a drop-down-box to trigger a transition in swf.

                And if you take a look at the example on https://issues.jboss.org/browse/RFPL-1430, there is never used a "non-action"-Component, but always a a4j:commandButton or a4j:commandLink, and that works for me also.

                • 5. Re: RF 4 and SWF
                  derkd

                  I also have this same question? Can non-action components be used to load for example an selectOneMenu list? (partial page rendering)? And how?

                  • 6. Re: RF 4 and SWF
                    andrey.sisoyev

                    Any progress here?

                    • 7. Re: RF 4 and SWF
                      andrey.sisoyev

                      this works (when migrating from RF3 to RF4):

                       

                      <h:selectOneMenu id="authType"

                          value="#{formBean.data['authType']}" styleClass="medium">

                          <f:selectItems value="#{formBean.selectItems['authTypes']}" />

                          <a4j:support id="authTypeChangeListener" action="authTypeChanged"

                              event="onchange" />

                      </h:selectOneMenu>

                       

                      \/ \/ \/ \/ \/ \/ \/ \/ \/ \/

                       

                      <a4j:jsFunction name="authTypeChangeTransitionTrigger" action="authTypeChanged" render="authTypeRegion" />

                      <h:selectOneMenu id="authType"

                          value="#{formBean.data['authType']}" styleClass="medium"

                          onchange="authTypeChangeTransitionTrigger()">

                          <f:selectItems value="#{formBean.selectItems['authTypes']}" />

                      </h:selectOneMenu>