Announcement Announcement Module
Collapse
No announcement yet.
JSF and WebFlow Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Seems it works without integration library

    I removed jsf integration library and went with Servlet context all the way and it works.... At least I was able to do.

    Code:
    <%@ taglib uri="http&#58;//java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http&#58;//java.sun.com/jsf/core" prefix="f" %>            
    <f&#58;loadBundle basename="ApplicationResources" var="Message"/>
    
    <f&#58;view>
    <h&#58;outputText value="#&#123;Message&#91;'contactus.title'&#93;&#125;"/>
    </f&#58;view>
    I'll have to test more and I am looking for input as to if facescontext and servletcontext are behaving properly. I would think that it should be saving facescontext in portletcontext not servletcontext????

    Code:
    /*
     * Created on Apr 22, 2005
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     */
    package org.springframework.web.servlet.view;
    
    import java.util.Map;
    
    import javax.faces.FactoryFinder;
    import javax.faces.component.UIViewRoot;
    import javax.faces.context.FacesContext;
    import javax.faces.context.FacesContextFactory;
    import javax.faces.lifecycle.Lifecycle;
    import javax.faces.lifecycle.LifecycleFactory;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    
    /**
     * @author jztb88
     *
     * TODO To change the template for this generated type comment go to
     * Window - Preferences - Java - Code Style - Code Templates
     */
    public class JsfPortletView extends InternalResourceView &#123;
    
    	/**
    	 * Render the internal resource given the specified model.
    	 * This includes setting the model as request attributes.
    	 */
    	protected void renderMergedOutputModel&#40;
    			Map model, HttpServletRequest request, HttpServletResponse response&#41; throws Exception &#123;
    
    		// Expose the model object as request attributes.
    		exposeModelAsRequestAttributes&#40;model, request&#41;;
    
    		// Expose helpers as request attributes, if any.
    		exposeHelpers&#40;request&#41;;
    
    		FacesContext facesContext = getFacesContext&#40;request, response&#41;;
    
    		// you could just render the page here but since we are still in filter, it might be
    		// a better idea to forward to the actual page
    		// facesContext.getApplication&#40;&#41;.getViewHandler&#40;&#41;.renderView&#40;facesContext, facesContext.getViewRoot&#40;&#41; &#41;;
    
    		// Forward to the resource &#40;typically a JSP&#41;.
    		// Note&#58; The JSP is supposed to determine the content type itself.
    		RequestDispatcher rd = request.getRequestDispatcher&#40;facesContext.getViewRoot&#40;&#41;.getViewId&#40;&#41; &#41;;
    
    		if &#40;rd == null&#41; &#123;
    			throw new ServletException&#40;
    					"Could not get RequestDispatcher for &#91;" + getUrl&#40;&#41; + "&#93;&#58; check that this file exists within your WAR"&#41;;
    		&#125;
    
    		// If already included or response already committed, perform include, else forward.
    		if &#40;useInclude&#40;request, response&#41;&#41; &#123;
    			rd.include&#40;request, response&#41;;
    			if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
    				logger.debug&#40;"Included resource &#91;" + getUrl&#40;&#41; + "&#93; in InternalResourceView '" + getBeanName&#40;&#41; + "'"&#41;;
    			&#125;
    		&#125;
    		else &#123;
    			rd.forward&#40;request, response&#41;;
    			if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
    				logger.debug&#40;"Forwarded to resource &#91;" + getUrl&#40;&#41; + "&#93; in InternalResourceView '" + getBeanName&#40;&#41; + "'"&#41;;
    			&#125;
    		&#125;
    	&#125;
        //	 You need an inner class to be able to call FacesContext.setCurrentInstance
        //	 since it's a protected method
    	private abstract static class InnerFacesContext extends FacesContext 
    	&#123;
    	  protected static void setFacesContextAsCurrentInstance&#40;FacesContext facesContext&#41; &#123;
    	    FacesContext.setCurrentInstance&#40;facesContext&#41;;
    	  &#125;
    	&#125;
    
    	private FacesContext getFacesContext&#40;HttpServletRequest request, HttpServletResponse response&#41; throws Exception &#123;
    		  // Try to get it first 
    		  FacesContext facesContext = FacesContext.getCurrentInstance&#40;&#41;;
    		  if &#40;facesContext != null&#41; return facesContext;
    
    		  FacesContextFactory contextFactory = &#40;FacesContextFactory&#41;FactoryFinder.getFactory&#40;FactoryFinder.FACES_CONTEXT_FACTORY&#41;;
    		  LifecycleFactory lifecycleFactory = &#40;LifecycleFactory&#41;FactoryFinder.getFactory&#40;FactoryFinder.LIFECYCLE_FACTORY&#41;; 
    		  Lifecycle lifecycle = lifecycleFactory.getLifecycle&#40;LifecycleFactory.DEFAULT_LIFECYCLE&#41;;
    
    		  //PortletContext portletContext = &#40;&#40;PortletApplicationContext&#41; getApplicationContext&#40;&#41;&#41;.getPortletContext&#40;&#41;;
    		  // Doesn't set this instance as the current instance of FacesContext.getCurrentInstance 
    		  facesContext = contextFactory.getFacesContext&#40;request.getSession&#40;&#41;.getServletContext&#40;&#41;, request, response, lifecycle&#41;;
    
    		  // Set using our inner class
    		  InnerFacesContext.setFacesContextAsCurrentInstance&#40;facesContext&#41;;
    		  
    		  // Determine the path for the request dispatcher.
    	      String dispatcherPath = prepareForRendering&#40;request, response&#41;;
    
    		  // set a new viewRoot, otherwise context.getViewRoot returns null
    		  UIViewRoot view = facesContext.getApplication&#40;&#41;.getViewHandler&#40;&#41;.createView&#40;facesContext, dispatcherPath&#41;;
    		  facesContext.setViewRoot&#40;view&#41;;
    
    		  return facesContext;
    		&#125;
    
    	
    
    &#125;

    Comment


    • #17
      Of course now I don't need a portlet specific jsf view...

      Of course now I don't need a portlet specific jsf view...

      Comment


      • #18
        Ok I tried a more more complex example... Here is result

        I tried hello world application from here:

        http://www.exadel.com/tutorial/jsf/j...kickstart.html

        It displayed correctly but looking at soure it seems it set the form action to be the jsp page rather than <portlet:actionURL/>

        looking for input here. I don't know if integration library would have handled this or if there is a way to do this in the bridge... Let me know.

        Comment


        • #19
          Hi,

          Apache MyFaces (http://myfaces.apache.org/) is a Open Source Implementation of the JavaServer Faces Framework. It has support for Portlet JSR-168.

          I believe that an interesting way to support JSF could be to integrate MyFaces in Spring MVC.

          Comment


          • #20
            As you said MyFaces is just an implementation

            As you said MyFaces is just an implementation. I don't see why it would be any easier than integrating Sun's JSF. The last thing I was trying to understand is about flowId. It seems that a component tree is saved in context for each view in JSF application. In the standard way this view is associated with the name of a jsp. I think with webflow it would be instead some combination of flowId and viewId. That way if you ever navigate to the same flow-view combination JSF can locate the view component tree. Does that sound right? I wish a JSF expert would join this thread...

            Comment


            • #21
              Integrating SWF and JSF

              Originally posted by kdonald
              JSF integration is a high priority for us, definitely.

              Neither Erwin or I are JSF experts, so we're certainly looking to work with some experts as part of this -- just like we did with Jose and Caesar on the Portlet integration.

              Keith
              A colleague pointed me at this thread, and it is of definite interest to me. I would also hope that folks here consider me a "JSF Expert"

              When I was at TSSJS in Las Vegas last month, I met with Keith and several of the other Spring developers, and saw a demo of SWF during one of the sessions. I was definitely intrigued, because (in parallel) I had been working on a next generation web application framework that (unlike nearly all current ones) is built on top off JSF, instead of being agnostic to it. That work has been accepted as a Struts subproject called "Shale" -- see the following Wiki page for details:

              http://wiki.apache.org/struts/StrutsShale

              One of the features on my "must have" list for Shale was good support for what I had called "dialogs" in the initial proposal, and I had done a fairly primitive implementation of dialog management (really, focused more on the problem of saving and restoring state across HTTP requests than on the state transition problem).

              Once I saw the SWF demo, and how elegant it was to put flow definitions together, it became clear that this was a much better architecture -- and the queston was what to do next.

              At a strategic level, there are two approaches I can see for how you could integrate SWF and JSF together:

              * Use JSF simply as a view technology (just forward
              to "/foo.faces" instead of "/foo.jsp" and you'll enable
              the JSF component rendering capabilities.

              * Integrate with JSF's navigation management (at least
              when you are within a flow), naturally using JSF pages
              to do the actual rendering (as above), but also leveraging
              the ability of a JSF action handler (the method that gets
              invoked when, say, a submit button is pressed) to return
              a logical outcome that could drive the state transition
              mechanism of SWF, instead of driving normal page
              navigation.

              To explore these ideas further, I've implemented a very simple version of what SWF in Shale, in the "org.apache.shale.dialog" package (the package javadocs for this package in the core library has background info). This would be sufficient if your needs are pretty simple, or if you did not choose to integrate Spring into your Shale based applicaton (athough that works pretty nicely as well -- I use the managed beans integration of Spring 1.1.5 or later in my demo app).

              What seems needed in the future, however, is a full blown integration of SWF and JSF that accomplishes both approaches described above. It also seems to make sense, as you've done with other integrations, that the code for this actually live in Spring (where, of course, any Shale user who wants to leverage it can get it for free as an alternative to the simple dialog support already present).

              If the SWF developers are interested, I volunteer to help create such an integration layer, and will contribute it to the Spring codebase. If that is of interest, it would probably be appropriate to conduct the detailed design discussions on the Spring developer mailing list, right?

              Craig McClanahan

              Comment


              • #22
                Craig,

                Great to hear from you! Yes, I agree first-class SWF/JSF integration is what we need, and we're keen to host it and work with you on developing the integration. Yes, the dev list is the best place for such discussions.

                You outline here sounds like a great start. Perhaps we can take one of our existing SWF sample apps and build out the JSF integration that way--in our samples/webflow directory in CVS are 5 different sample apps that each illustrate different features of SWF. Phonebook already demonstrates Portlet integration, Birthdate demos Struts integration--we could tack JSF on top of one of those or another, for example "sell item" (a wizard flow.) Or we could create a new app just to showcase JSF+SWF.

                How do you see Shale fitting into the JSF+SWF equation. Will you need Shale to use SWF+JSF? When would you use all 3?

                When I get back from onsite (next week) I'd be in a good position to review an initial stab at integration and start diving deeper into JSF. Between now and then I'll certainly have the evenings to participate in some design discusions on the dev lists.

                Cheers,

                Keith

                Comment


                • #23
                  Excellent!

                  Really looking forward to JSF - SWF integration. That way I'll finally have to take a deeper look at JSF! :-)

                  Anyway, the second approach Craig suggest below seems to be the correct course of action.

                  Erwin

                  Comment


                  • #24
                    Wow, nice to have you both here ;-)

                    In the meantime, we have designed a possible solution: in contrast to garpinc2's solution that integrates JSF into spring using a special view extension, our solution builds on the extensible and adaptive JSF model.
                    We envision a web application as a JSF application: pages linked with links between them. To introduce within the JSF application a more structured webflow, we propose to put a special page within the JSF application. Links are possible to this page and from this page, nicyly interconnecting the JSF and the webflow worlds.
                    We suggest to use a special JSF navigation handler that delegates all SWF specific tasks to a web flow execution manager.
                    Using JSF as the top-level component and web flow as a part of the controller logic has several benefits. First one can use the whole range of features provided by JSF (i.e. components, method binding, value binding just to mention the basic ones). Second it's possible to describe unguided transitions between pages using the simple JSF navigation rules. Third, it's possible to combine JSF actions and web flow action states together.

                    JSF pages are considered to be created using graphical editors. A JSF web flow integration should allow reusing such pages and providing the possibility to combine the two flow architectures.

                    Delegating the control to the right part (JSF or web flow) can be separated in three phases:
                    * The JSF view is rendered for the first time, i.e. the flow starts
                    * The flow is executed
                    * The flow is terminated in this request-response iteration.

                    To solve the first one and still to be conformant to JSF rules, one could save web flow views at a separate location. Using a prefix for transition action strings or, as already mentioned above, generating some dummy pages would work as well (in general, we just need some kind of flag).

                    The second case is recognized by the three hidden fields that are embedded into HTML and used by web flow to save the flow's state.

                    The last case can be recognized using a FlowExecutionListener (since the three fields are transmitted in the last request, navigation control is delegated to web flow). After returning from the FlowExecutionManager JSF's original navigation handler will take over control and the appropriate view will be displayed (i.e. a flow has to end with an action state).

                    In principle, this is exactly what Craig has proposed.

                    Adding a web flow component to JSF would save to add the hidden input fields explicitly.

                    We already have a prototype proofing the navigation handler approach.

                    Andi

                    Comment


                    • #25
                      If the solution is not implemented by extending view..

                      If the solution is not implemented by extending view will the spring features of implementing the view in whatever technology you want be still true? I'm looking forward to hear Craig's implentation ideas...

                      Comment


                      • #26
                        Wouldn't an irc channel be more efficient than dev list?

                        Wouldn't an irc channel be more efficient than dev list? In a way that discussions could be archived on the site for community review?

                        Comment


                        • #27
                          No, not really. This problem has to be solved by filters or clever mappings (any better ideas?). Our approach assumes JSF as standard view technology (Although, the only thing you need are the three hidden fields that are embedded in the markup. This way it should be possible to access a flow through different view technologies. It should be even possible to have different view techs within a single flow. However, we consider this as unimportant. But different flows built with different view technologies is indeed an interesting point.)

                          counter questions
                          *How would you allow to use JSF flows?
                          *How can both flow models be integrated in one web application?
                          *Does it support the use of JSF features (i.e. bindings, validators, converters)?
                          *Can you still use available JSF/web flow design tools?
                          *Beside the integration of different view technologies, do you see any important advantages that favor your approach over the other?

                          Andi

                          Comment


                          • #28
                            Well these are my thoughts...

                            counter questions
                            *How would you allow to use JSF flows?
                            I thought the extended view idea was the best way because it fit into the current architecture. I never liked the idea of the Faces servlet because it doesn't give any leverage to decide what to do based on the request. Using the spring controler to proxy to jsf view gives spring full control of what to do as a result of the request either proxying to faces stuff or any other technology. In the meantime spring interceptors can be applied. This is particularly important with portlet development since filters are not yet supported.

                            *How can both flow models be integrated in one web application?
                            The view resolvers handle this not the flow as far as I understand.

                            According to doc "When mixing different view technologies in a web application, you can use the ResourceBundleViewResolver" the alternative method is "Spring supports more than just one view resolver"

                            *Does it support the use of JSF features (i.e. bindings, validators, converters)?
                            My thought was if the view is a faces implementation it must have access to facesContext somehow. If the post is back to the same view with the component then I don't see why all those features wouldn't be supported.

                            *Can you still use available JSF/web flow design tools?
                            Nothing would have changed wrt architecture so I also don't see why that would change.

                            *Beside the integration of different view technologies, do you see any important advantages that favor your approach over the other?
                            I wouldn't consider me the expert here. I'm glad we've got some real experts involved. I'm not proposing any solution, I just realized I had a need and tried to get some idea what was involved. I think between Keith and Craig a far superior solution will be developed than I could have done. I just hope my business need to support JSF in portlets with this architecture will be realized.

                            Comment


                            • #29
                              I did not want to join Spring forum until my own project supports Spring, but seeing this discussion related to JSF, I could not help posting a message.

                              Thinking about dialogs, I think of them from a desktop programmer point of view. In a desktop OS dialog is a window with one or several panels. If it is a notebook, than a user can select a page explicitly, if it is a simple dialog, then panels can be defined in a resource, and switched from the code simply by selecting visible panel ID.

                              Thus, a dialog is is not a usual flow of pages. I think, a dialog is an object which can have state and can visulalise itself depending on the state. Think portlets.

                              Trying to integrate my own component into JSF, I used the idea of stateful visual component, along with David Geary's tip of how to compose JSF page from subpages. So, I have "master" page ("dialog window frame") which includes "panels":

                              Code:
                              <html>
                                <%@ taglib uri="http&#58;//java.sun.com/jsf/html" prefix="h" %>
                                <%@ taglib uri="http&#58;//java.sun.com/jsf/core" prefix="f" %>
                                <f&#58;view>
                                  <jsp&#58;include page="step1.jsp" />
                                  <jsp&#58;include page="step2.jsp" /> 
                                  <jsp&#58;include page="step3.jsp" /> 
                                </f&#58;view>
                              </html>
                              Originally posted by bura
                              To introduce within the JSF application a more structured webflow, we propose to put a special page within the JSF application. Links are possible to this page and from this page, nicyly interconnecting the JSF and the webflow worlds.
                              Yep, kinda like this. The master page is the only location where client sends requests (for that dialog, or for the flow if you wish). Client either submits input to master page using POST, or loads master page using GET. In the latter case master page builds itself and shows the panel that corresponds to current state. Each panel looks something like this:

                              Code:
                              <html>
                                <%@ taglib uri="http&#58;//java.sun.com/jsf/html" prefix="h" %>
                                <%@ taglib uri="http&#58;//java.sun.com/jsf/core" prefix="f" %>
                                <f&#58;subview id="step1" rendered="#&#123;wizardBean.step1&#125;">
                                  <h&#58;form id="page_step1" >
                                  <h&#58;messages />
                                  <h&#58;panelGrid columns="2" border="1" cellspacing="0">
                              
                                    <h&#58;outputText value="User Name&#58;"/>
                                    <h&#58;inputText id="userNameEdit" value="#&#123;wizardBean.userName&#125;"/>
                              
                                    <h&#58;outputText value="Password&#58;"/>
                                    <h&#58;inputText id="userPasswordEdit" value="#&#123;wizardBean.userPassword&#125;"/>
                              
                                    <h&#58;commandButton action="#&#123;wizardBean.cancel&#125;" value="Cancel"/>
                                    <h&#58;commandButton action="#&#123;wizardBean.Next&#125;" value="Next"/>
                              
                                  </h&#58;panelGrid>
                                  </h&#58;form>
                                </f&#58;subview>
                              </jsp&#58;root>
                              The important thing about code above is "rendered" attribute. Maybe I did not look well enough, but I could not create a full-blown expression like this rendered="#{wizardBean.currentStep.equals(1)} So, I am using a bunch of boolean methods, as many as many panels. Kinda ugly, but it works. Notice, that each included JSP contains subview.

                              The backing bean is simple and is not interesting, so it is not shown here. The faces-config.xml is actually more important:

                              Code:
                                <navigation-rule>
                                  <from-view-id>/signup.jsp</from-view-id>
                                  <navigation-case>
                                      <from-outcome>reload</from-outcome>
                                      <to-view-id>/signup.jsp</to-view-id>
                                      redirect/>
                                  </navigation-case>
                                </navigation-rule>
                              
                                <managed-bean>
                                  <description>
                                    Signup Wizard bean
                                  </description>
                                  <managed-bean-name>wizardBean</managed-bean-name>
                                  <managed-bean-class>com.superinterface.loginwizard.jsf.WizardBean</managed-bean-class>
                                  <managed-bean-scope>session</managed-bean-scope>
                                </managed-bean>
                              The navigation rule above along with composition of main page provides the functionality, that makes this dialog a control. This a very important concept. For a control, flow does not go from one page to another. Instead, the control is addressed by a single URL, and generates different pages ("panels") depending on its current state. Again, think portlets. Portlet is a control, dialog is a control, wizard is a multi-panel control.

                              First you navigate to master page signup.jsp (using GET), it includes subviews. Each subview checks the current dialog state. If state corresponds to a subview, the page it is included into master page. Then the master page is shown, now it contains panel which is synchronized with dialog state. When you click a button, an event triggers the method in the backing bean.

                              Backing bean updates the model and changes state if needed. Then it returns back, and JSF executes navigation rule. What it does? It goes back to itself, to the same master page. Then JSF loads master page again. State was changed, so a different subview is included according to "rendered" rule.
                              Originally posted by bura
                              [JSF] doesn't handle multiple submits or browsers back, forward and refresh buttons.
                              Notice <redirect/> tag in the navigation rule above, this helps to fight with POSTDATA problems and provides clean refresh. Current JSF version does not have a replacement for <controller nocache="true"/> that Struts has, but I was promised that non-cachable pages will be possible in the next version ;-)

                              This is basically it. The only part left is to define state transitions and to create panels.

                              Comment


                              • #30
                                comparing features and approaches is ok :-)

                                Comment

                                Working...
                                X