Results 1 to 2 of 2

Thread: Websphere 8/8.5 + Webflow + Mojarra JSF 2.x isMyfacesPresent bug

  1. #1
    Join Date
    Mar 2011
    Posts
    8

    Default Websphere 8/8.5 + Webflow + Mojarra JSF 2.x isMyfacesPresent bug

    I just finished a battle to use webflow (2.3.1) with Mojarra JSF 2.1.x in Websphere 8 and Websphere 8.5 (testing against both), and thought I would pass along the workaround for anyone else in the same scenario.

    To begin, we had simple Mojarra JSF 2 + webflow app which was working great in Websphere 7, so long as we configured the class-loader to PARENT_LAST. By simple, I mean the app configuration was originally based on the Spring faces booking app and contains one flow with 2 view states, each page only has buttons used to navigate from page to page. Upon attempting to deploy the same app to Websphere 8 and 8.5, the behavior is that the first page would return a redirect in a loop. Using the 2.1.14 version of Mojarra got me past the invalid redirect, but would cause the initial flow to be restarted on every event. A little digging showed that FlowViewStateManager.restoreTreeStructure(...) was returning null.

    I had javax.faces.PARTIAL_STATE_SAVING set to 'true' in the web.xml, but some further debugging showed that JsfRuntimeInformation.isPartialStateSavingSupporte d() was returning false. The root culprit turned out to be this line in JsfRuntimeInformation:

    Code:
    private static final boolean myFacesPresent = ClassUtils.isPresent("org.apache.myfaces.webapp.MyFacesServlet",
    			JsfUtils.class.getClassLoader());
    In Websphere 8 and 8.5, it seems that myfaces is always on the classpath, no matter what you do (thanks, Websphere). Since JsfRuntimeInformation will return 'false' from isPartialStateSavingSupported() if myfaces is present, then a conflict is created where the JSF components think partial state saving is supported, while webflow thinks it is not; thus, wacky hijinks ensue.

    My short-term workaround was to provide my own copy of JsfRuntimeInformation which avoids the MFacesServlet class lookup and always returns 'false' for the isMyfacesPresent(); I'll post back if I come up with a more robust solution that will work in Websphere 8/8.5 (hopefully, the webflow committers will find something better). The summary is that it seems that just checking for particular MyFaces classes on the classpath is not going to work in Websphere 8 +, since they will always be there.

    (Note that the results are the same, whether you select "DEFAULT", "SunRI1.2", or "MyFaces2.0"; myfaces is always on the classpath)
    Last edited by matt.deboer; Nov 12th, 2012 at 03:07 PM.

  2. #2
    Join Date
    Mar 2011
    Posts
    8

    Default

    The following modification to JsfRuntimeInformation seems to work correctly on websphere 7, 8 & 8.5 (and I imagine should work correctly on other platforms as well, though I've only tested on these). It test the implementation of the underlying faces ApplicationFactory to determine whether MyFaces is the implementer.


    Code:
    ...
    private static final boolean myFacesPresent;
    
    	static {
    		if (ReflectionUtils.findMethod(FacesContext.class, "isPostback") != null) {
    			jsfVersion = JSF_20;
    		} else if (ReflectionUtils.findMethod(FacesContext.class, "getELContext") != null) {
    			jsfVersion = JSF_12;
    		} else {
    			jsfVersion = JSF_11;
    		}
    		
    		/*
    		 * MyFaces is "present" if the ApplicationFactory implementation is provided by MyFaces 
    		 */
    		ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
    		boolean isMyFacesPresent = false;
    		while (appFactory != null) {
    			if (appFactory.getClass().getCanonicalName().startsWith("org.apache.myfaces")) {
    				isMyFacesPresent = true;
    				break;
    			} else {
    				/*
    				 * A third-party library may have wrapped the factory; once we get down to the base 
    				 * implementation, null should be returned from getWrapped() 
    				 */
    				appFactory = appFactory.getWrapped();
    			}
    		}
    		myFacesPresent =  isMyFacesPresent;
    	}
    ...

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •