Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide support for Portlet API 2.0 and JSF 1.2 [SWF-1379] #565

Closed
spring-operator opened this issue Aug 5, 2010 · 17 comments
Closed

Provide support for Portlet API 2.0 and JSF 1.2 [SWF-1379] #565

spring-operator opened this issue Aug 5, 2010 · 17 comments

Comments

@spring-operator
Copy link
Contributor

Rossen Stoyanchev opened SWF-1379 and commented

JSF portlets are presently considered experimental in Web Flow 2. The upgrade to Spring 3 also meant Portlet API 2.0 is a required dependency. While there are portlet bridge implementations supporting Portlet API 2.0 and JSF 1.2 the JSR-329 they are based on is not yet final.

Furthermore Web Flow and a Portlet Bridge implementation both drive the JSF lifecycle. There is a degree of overlap between the two. Hence we need to determine how a Portlet Bridge fits and whether it is the best option for supporting JSF portlets in Web Flow.

This ticket aims to explore support for JSF portlets within Web Flow with the specific goal of demonstrating that support through the swf-booking-portlet-faces sample.


Affects: 2.1.1

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

The Portlet/JSF booking sample (swf-booking-portlet-faces) now works with Portlet 2.0 API and JSF 1.2 dependencies (both Mojarra and MyFaces were tested).

The support is based on Web Flow's own integration with the Portlet API (and not on the Portlet Bridge for JSF), which has now been extended to ensure JSF requests work with Portlet specific structures such as PortletContext, PortletRequest, and PortletResponse. The dependency on the Portlet Bridge for JSF has been removed.

@spring-operator
Copy link
Contributor Author

Paul Bacsik commented

I checked this out by maven 2.2.0.BUILD-SNAPSHOT with spring 3.0.4.RELEASE, myfaces 1.2.8 and liferay 5.5 but got an Exception on the first rendering of the view:
Caused by: java.lang.NullPointerException
at org.springframework.faces.webflow.JsfViewFactory.getView(JsfViewFactory.java:78)
at org.springframework.webflow.engine.ViewState.doEnter(ViewState.java:206)
at org.springframework.webflow.engine.State.enter(State.java:194)
at org.springframework.webflow.engine.Flow.start(Flow.java:535)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:364)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.start(FlowExecutionImpl.java:222)

@spring-operator
Copy link
Contributor Author

spring-operator commented Sep 14, 2010

Rossen Stoyanchev commented

Check to make sure you're not missing the FlowFacesContextLifecycleListener in you webflow:executor configuration (see the booking-portlet-faces sample for an example). I've made some improvements to simplify the configuration #561. Those should be available after tonight's build.

By the way the nightly build last night failed with a strange compiler error so you haven't really picked up the changes yet. There should be a good snapshot by tomorrow:

http://build.springsource.org/browse/SWF-22XSNAPSHOT

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

A snapshot build is now available that contains the changes for this issue. You'll want to force maven to check for udpated snapshots (mvn -U) when building.

@spring-operator
Copy link
Contributor Author

Paul Bacsik commented

Don't know exactly whether maven is up to date, I downloaded *-50 libs and it works wonderful without any portlet-bridge implementation. Into faces-config I copied this from samples: <view-handler>org.springframework.faces.webflow.application.portlet.PortletFaceletViewHandler</view-handler> and of course the FlowFacesContextLifecycleListener in the mvc config is needed. Thank you for the good job.

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

Thanks for the feedback!

@spring-operator
Copy link
Contributor Author

David Godin commented

Dear experts,
I downloaded the snapshot 52 and I'm now trying to deploy the booking-portlet-faces example, but I get an error at run time (when trying to display the portlet into Liferay 6.0.2).
I'm not a Liferay expert, but I'd like to assess the possibility of migrating my SWF applications into a portal context.
Many thanks in advance for your advices, recommendations, etc...

The error trace is:

DEBUG: org.springframework.web.portlet.DispatcherPortlet - DispatcherPortlet with name 'swfbookingfaces' received render request
DEBUG: org.springframework.web.portlet.DispatcherPortlet - Testing handler map [org.springframework.web.portlet.handler.PortletModeHandlerMapping@18baa54] in DispatcherPortlet with name 'swfbookingfaces'
DEBUG: org.springframework.web.portlet.handler.PortletModeHandlerMapping - Key [view] -> handler [org.springframework.webflow.samples.booking.ViewFlowHandler@155b3c2]
DEBUG: org.springframework.web.portlet.DispatcherPortlet - Testing handler adapter [org.springframework.webflow.mvc.portlet.FlowHandlerAdapter@5b957e]
DEBUG: org.springframework.webflow.executor.FlowExecutorImpl - Launching new execution of flow 'view' with input null
DEBUG: org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl - Getting FlowDefinition with id 'view'
DEBUG: org.springframework.webflow.engine.builder.DefaultFlowHolder - Assembling the flow for the first time
INFO : org.springframework.web.context.support.GenericWebApplicationContext - Refreshing Flow ApplicationContext [view]: startup date [Mon Sep 27 10:20:46 GMT 2010]; parent: PortletApplicationContext for namespace 'swfbookingfaces-portlet'
DEBUG: org.springframework.web.context.support.GenericWebApplicationContext - Bean factory for Flow ApplicationContext [view]: org.springframework.beans.factory.support.DefaultListableBeanFactory@19ba32b: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@30ed6e
DEBUG: org.springframework.web.context.support.GenericWebApplicationContext - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@11b4107]
DEBUG: org.springframework.web.context.support.GenericWebApplicationContext - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@4a6c94]
DEBUG: org.springframework.web.context.support.GenericWebApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@1e835e]
ERROR: org.springframework.web.portlet.DispatcherPortlet - Could not complete request
java.lang.IllegalStateException: No Factories configured for this Application. This happens if the faces-initialization does not work at all - make sure that you properly include all configuration settings necessary for a basic faces application and that all the necessary libs are included. Also check the logging output of your web application and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use some special web-containers which do not support registering context-listeners via TLD files and a context listener is not setup in your web.xml.
A typical config looks like this;
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>

at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:106)
at org.springframework.faces.webflow.FlowLifecycle.newInstance(FlowLifecycle.java:49)
at org.springframework.faces.webflow.JsfViewFactoryCreator.getLifecycle(JsfViewFactoryCreator.java:49)
at org.springframework.faces.webflow.JsfViewFactoryCreator.createViewFactory(JsfViewFactoryCreator.java:40)

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

The most likely cause for the above error missing or invalid configuration in web.xml or faces-config.xml. Given that you're using the sample then the configuration should be okay. I can't reach the build server right now to verify if CI-52 has the changes. I recommend trying downloading version 2.2.0.RC1 that was released last week:

http://www.springsource.com/download/community

I've also seen this error happen when some other exception further up occurred during start up causing JSF to fail to initialize. Later on when the FactoryFinder is used it gives the above error. It could be things like ClassNotFoundException or any other exception. Do check the logs further up during for other previous exceptions.

@spring-operator
Copy link
Contributor Author

David Godin commented

Thanks Rossen for your suggestions.... I downloaded the version 2.2.0.RC1 but I still have the same error, and I couldn't discover any "ClassNotFoundException" in the log...
Remarks/Questions:

  1. As I'm not an ivy expert, I had to modify the classpath in Eclipse in order to use the right jar files (.../spring-webflow-2.2.0.RC1/dist/*RC1.jar). I don't think this can be the cause of my issue.
  2. Do you know a step by step tutorial I could follow in order to build and deploy this sample? It seems my technical background is not good enough to find my way by my-self.

Many thanks in advance,
David

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

If you downloaded spring-webflow-2.2.0.RC1-with-dependencies.zip then:

cd projects/build-spring-webflow
ant jar
cd ../spring-webflow-samples/booking-portlet-faces
ant jar
ls target/artifacts/*.war

  1. instructions for importing into Eclipse in projects/spring-webflow-samples.

So there no other exceptions in the log? Strange. And you haven't changed of the configuration... It's should be something failing during the initialization of JSF. If you have the option to start in a debugger, there is an option to break when exceptions occur.

@spring-operator
Copy link
Contributor Author

Mindaugas Plukas commented

Does this solution cover AJAX processing, in particular does it support RichFaces framework?

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

I can't think of any reason why it shouldn't.

@spring-operator
Copy link
Contributor Author

Mindaugas Plukas commented

Thanks for reply.

After taking a brief look into the code I was not sure what controller AJAX requests will go to.
AJAX requests can not be portlet action requests (since these are processes by the portal and delivers a whole page) but it seemed that all JSF action URLs will be formed as portlet action URLs.
Theoretically, in portal environment AJAX requests could be portlet resource requests or servlet requests. In former case it is not clear how RichFaces support, for example, org.ajax4jsf.Filter or org.springframework.faces.richfaces.RichFacesAjaxHandler should be configured? In latter case should application provide DispatcherServlet and FlowController (operating on the same flow executor as org.springframework.webflow.mvc.portlet.FlowHandlerAdapter)?

Very likely that I missed something. Could you please elaborate this point a little. Thank you.

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

Good points.

The Portlet 2.0 spec has a section on "Serving Fragments through Portlets" (PLT.14). As you pointed out those would have to come in as resource requests. They go through the portal as all other requests but only the target portlet would be invoked to generate partial content. The PortletHandlerMapping should then route the request through to Web Flow's FlowHandlerAdapter, which currently implements handleResource() as follows:

if (request.getResourceID() != null) {
PortletRequestDispatcher rd = this.getPortletContext().getRequestDispatcher(request.getResourceID());
if (rd != null) {
rd.forward(request, response);
}
}

This method may need to be modified to have logic similar to the handleAction/handleResource methods.

Have you been able to confirm what URLs are created by the RichFaces ajax components? I guess we'll just need to have a working sample that sends resource requests via Ajax and see if the handleResource method needs to be updated.

@spring-operator
Copy link
Contributor Author

Mindaugas Plukas commented

We have run a small test based on booking-portlet-faces sample with RichFaces/Ajax4Jsf components added.

As expected, AJAX request URLs (generated by <a4j> tags) were rendered as portlet action URLs (which is wrong as discussed earlier).

Additional problem with RichFaces is that there is no way to set up org.ajax4jsf.Filter, since it is servlet filter, but all SWF requests go through DispatcherPortlet (we added org.ajax4jsf.Filter to web.xml without meaningful mapping just to initialize A4J environment.) Seems that because of this RichFaces AJAX components were not active.

Concerning AJAX requests, SWF - Portlet support should be improved like this:
1.org.springframework.webflow.context.portlet.FlowUrlHandler abstraction should be extended with
method createFlowExecutionResourceUrl() (in addition to createFlowExecutionUrl()). This method would
produce portlet resource URL.
2.Ensure that SWF provided faces ViewHandler (e.g. PortletFaceletViewHandler) effectively use createFlowExecutionResourceUrl()
for rendering JSF AJAX URLs.
3.org.springframework.webflow.mvc.portlet.FlowHandlerAdapter should handle portlet resource request in the same way as action requests.
4.Maybe portlet enviromnet needs AjaxHandler abstraction and logic based on it, as has servlet environment; then it should be added
to org.springframework.webflow.mvc.portlet.FlowHandlerAdapter and related classes.

Concerning RichFaces support
1.Open question how configure org.ajax4jsf.Filter for DispatcherPortlet. (Maybe port/adapt it to portlet filter?)
2.RichFacesAjaxHandler for portlet environment maybe needed (see above).

By the way , JSF portlet with RichFaces and JBoss portlet bridge employs portlet resource URLs for <a4j> requests.
Also in that setup bridge portlet delegates to FacesServlet, and org.ajax4jsf.Filter is mapped on that servlet.

@spring-operator
Copy link
Contributor Author

Rossen Stoyanchev commented

Thanks for the detailed comments. This just needs to be tried out. If you have any sample code that would be useful feel free to attach.

I'm not quite sure how the issue with the a4j tags generating portlet action URLs could be resolved.

As for the org.ajax4jsf.Filter I wonder how this works (or if it works) with the Rich Faces Portlet Bridge for JSF version 2.

@spring-operator
Copy link
Contributor Author

spring-operator commented Oct 29, 2010

Rossen Stoyanchev commented

I've added #601 for the handling of portlet resource requests. I'm still not sure how a ViewHanlder.getActionURL() would know when to return a portlet resource request URL as indicated in #2 above but #601 is certainly needed regardless of that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants