Attached is the current draft of chapter 8 on the JSR 301 spec (portlet
bridge). It describes things developers of Faces extensions should be
aware of to cohabitate with a bridge/run in a portlet environment. The short answer to your question is no, the bridge won't help you here. Portlet 1.0 didn't define support for filters or wrapping request/response objects. Hence initialization done in filters in the servlet environment should be rewritten/migrated to FacesContextFactory. -Mike- Rashmi wrote: Hallo, can myfaces portlet bridge can be used in someway to overcome the porblem?Regards, Rashmi Scott O'Bryan wrote:Ok. I'll need to add a few utilities to the common utilities and add a common configurator jar to the project. But it should be easy enough to do in my copious amounts of free time. I'm currently in the middle of restructuring the bridge projects (which is almost done as well) so let me get that done and I'll check in the configurators so people can take a look at possibly using them. Scott Matthias Wessendorf wrote:Another option is I've been tinkering with separating the configurator system similar to what Trinidad uses in order to put into an Apache commons project. The code is complete (albeit untested) but the configurators are a way to duplicate *most* filter logic in a JSF environment without the use of filters. It works for both portlet and servlet environements. If you want me to try and get that checked in to the commons, maybe Orchestra can use it?yeah, I think that others may benefit from the Trinidad configurator "framework" as well. I think that Orchestra definitely is a valid use case for that. Looks like (from what I remember on old discussions) Tobago also has interest in that. -MScott Simon Kitching wrote:BTW, you might try adding these elements to the OrchestraServletFilter filter-mapping clause: <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> Regards, Simon ---- Simon Kitching <[EMAIL PROTECTED]> schrieb:Hi Rashmi, Again, exact line numbers from the latest snapshot would be useful. In an email you sent to me directly you said that with the latest snapshot the exception was at line 83 of ConversationManager. But with the latest code, that line is in the middle of a javadoc comment, so perhaps you got the libraries mixed up? The latest snapshot is always here: http://people.apache.org/repo/m2-snapshot-repository/org/apache/myfaces/orchestra/myfaces-orchestra-core/1.1-SNAPSHOT/ As the comments in JsfFrameworkAdapter say: This class requires the JsfFrameworkAdapterFilter to be configured to run on every JSF request. And JsfFrameworkAdapterFilter says: Note that the conversation.jsf.OrchestraServletFilter class executes this class as a "subfilter", so defining this filter is not required if that filter is already defined. So as long as you have OrchestraServletFilter defined there is no need to configure anything else. And I certainly hope you have the OrchestraServletFilter defined; that is mandatory. As someone mentioned earlier that filters run at unusual times during portlet processing, that might be the cause of the problem. Neither Mario nor I use portlets so you'll need to look into that yourself although we are both happy to help with advice. I think that getting Orchestra and portlets working together will not be too difficult; it looks like is just the initialisation of basic structures that is not happening in a portlet environment. But getting the correct line at which the NullPointerException is actually happening would be a very good start... Regards, Simon ---- Rashmi <[EMAIL PROTECTED]> schrieb:Hallo Mario, We tried using the latest snapshot of Orchestra. Unfortunately still facing the same exception as before. After having tried debugging the application, I see that it fails in class SpringConversationScope - protected Object getBean(String beanName, ObjectFactory objectFactory) {...} method. It displays the conversation name correctly, but fails in next step: ConversationManager manager = ConversationManager.getInstance(); Is it possible through spring IOC I can try instantiating or something? It clearly states in the Orchestra API, that the BasicFrameworkAdapter has been implemented for plain Servlet environment and JsfFrameworkAdapter for JSF environment. In the configuration i.e web.xml I tried explicity setting the filter to JsfFrameworkAdapter but again failed. May be we will end up writing a portlet friendly adapter. Please throw some light on how to get started or any other workaround to overcome the problem. Regards, Rashmi Mario Ivankovits wrote:Hi!currently we're prototyping a portlet application (liferay 4.33) with orchestra , JPA (Hibernate) and myFaces 1.1.5.Unhappily I have zero experience with portlets. If you could provide a simple webapp to test this thing it would greatly help, though, I know how much work it is to setup one. However, if possible somehow, please try the latest snapshot of Orchestra as we've changed how the FrameworkAdapter will be initialized. At least it gives us correct line numbers in the exception. The FrameworkAdapter brings me to the thing which might be needed to be fixed for the portlet environment, not sure though. If you have a look at the source of this class you'll see that there are just a handful of methods which needs to be implement, probably in a portlet friendly way. Could you please check if you have access to a FacesContext close before the method raising an exception? If so, you can stick with the JsfFrameworkAdapter and just need to find a way how to initialize it properly. If not, you have to create your own portlet friendly FrameworkAdapter wich allows you to get access to the session/request stuff required by Orchestra. Ciao, Mario |
8
Faces Extensions in the Bridge Environment
It
is common for Faces applications to run in an extended Faces
environment. I.e. one where the applications relies on
function
not provided in the base (reference) implementation but rather is
provided by an implementation using one of the many extensions
mechanisms Faces defines.
As the portlet bridge also is in part built as a Faces
extension consideration needs to be given by these other Faces
extension developers to ensure proper execution in a portlet
environment..
Unfortunately, the Faces extensions implemented by the bridge aren't limited to those that are configured via the service provider mechanism. The bridge also extends the ViewHandler and StateManager[6.2 and 6.3]. The ViewHandler and StateManager are configured in its faces-config.xml that its in the META-INF directory of its jar file. As Faces doesn't define a set precedence order when like configuration exists in other faces-config.xml files that are also in a jar's META-INF directory, one can't control or determine whether or where in the ViewHandler or StateManager chains the bridge's implementation will be called. To avoid obscuring other extensions, the bridge delegates where ever possible and then augments the result. When this is not feasible, the bridge ensures it at least duplicates the behavior defined by the RI for this function. Other extensions are expected to be implemented in a similar manner to avoid obscuring necessary bridge behavior. I.e. they either delegate to ensure the bridge gets a chance to execute or they implement the bridge's function directly. Sections 8.5 and 8.6 discusses this in detail.
If an extension subsystem needs to perform per request initialization, it is recommended it provide its own implementation of FacesContextFactory and perform this initialization in the appropriate activation calling sequence.
Commonly such initialization involves wrapping either the request or response objects to support extended semantics on these objects. In the Servlet environment extensions have two options, they can wrap the request or response object before delegating the creation of the FacesContext/ExternalContext or they can wrap later and replace the request/response object managed by the ExternalContext using the setRequest or setResponse calls. Because the portlet API doesn't directly support such wrapping, extensions must only use the later mechanism when wrapping a portlet request or response. I.e. so that the bridge can properly dispatch Faces requests it must be constructed with the original portlet request and response objects.
Some Faces extensions use servlet filters to manage they per request initializations/processing. Because filters aren't supported in the portlet environment, this will not work. Instead its recommended the extension use the "provide a FacesContextFactory" technique discussed in this section.
When the bridge can be assumed to be deployed in the application, the utility method javax.portlet.faces.BridgeUtil.isPortletRequest() may be used instead.
8.1 Configuration
Because its the bridge's implementation that abstracts the details of running in a portlet environment its important that the bridge extensions execute as close as possible to the base layer as possible. This is why the bridge's FacesContextFactory is configured as a service provider. To run correctly all other application extensions that aren't defined in the application's faces-config.xml should be configured in the META-INF/faces-config.xml in their jar file. They should not be registered as a service provider.Unfortunately, the Faces extensions implemented by the bridge aren't limited to those that are configured via the service provider mechanism. The bridge also extends the ViewHandler and StateManager[6.2 and 6.3]. The ViewHandler and StateManager are configured in its faces-config.xml that its in the META-INF directory of its jar file. As Faces doesn't define a set precedence order when like configuration exists in other faces-config.xml files that are also in a jar's META-INF directory, one can't control or determine whether or where in the ViewHandler or StateManager chains the bridge's implementation will be called. To avoid obscuring other extensions, the bridge delegates where ever possible and then augments the result. When this is not feasible, the bridge ensures it at least duplicates the behavior defined by the RI for this function. Other extensions are expected to be implemented in a similar manner to avoid obscuring necessary bridge behavior. I.e. they either delegate to ensure the bridge gets a chance to execute or they implement the bridge's function directly. Sections 8.5 and 8.6 discusses this in detail.
8.2 Initializing Extensions
If an extension subsystem needs to perform one time intialization, it is recommended it rely on providing a ServletContext listener as defined in the Servlet specification.If an extension subsystem needs to perform per request initialization, it is recommended it provide its own implementation of FacesContextFactory and perform this initialization in the appropriate activation calling sequence.
Commonly such initialization involves wrapping either the request or response objects to support extended semantics on these objects. In the Servlet environment extensions have two options, they can wrap the request or response object before delegating the creation of the FacesContext/ExternalContext or they can wrap later and replace the request/response object managed by the ExternalContext using the setRequest or setResponse calls. Because the portlet API doesn't directly support such wrapping, extensions must only use the later mechanism when wrapping a portlet request or response. I.e. so that the bridge can properly dispatch Faces requests it must be constructed with the original portlet request and response objects.
Some Faces extensions use servlet filters to manage they per request initializations/processing. Because filters aren't supported in the portlet environment, this will not work. Instead its recommended the extension use the "provide a FacesContextFactory" technique discussed in this section.
8.3 Portlet Considerations
There may be times when an extension needs to determine if its running in a portlet vs. a servlet environment. Generally the check needs to be made without regard to whether the bridge and/or portlet container are actually deployed in the environment. The simpliest technique relying on instanceof javax.servlet.ServletRequest(Response) is insufficient because some portlet containers may have extended the underlying servlet request/response object in implementing PortletRequest/PortletResponse. Instead the extension should look for the existence of the bridge's request attribute which holds the current portlet phase. The attribute name is javax.portlet.faces.portletPhase. If this attribute exists it is a portlet request.boolean isPortletRequest =
externalContext.getRequestMap().containsKey("javax.portlet.faces.portletPhase");
externalContext.getRequestMap().containsKey("javax.portlet.faces.portletPhase");
When the bridge can be assumed to be deployed in the application, the utility method javax.portlet.faces.BridgeUtil.isPortletRequest() may be used instead.
8.4 General Considerations
Extensions should:- avoid interacting directly with container specific objects. Instead rely on the ExternalContext abstraction.
- when interacting directly with container specific objects, provide support for both the Servlet and Portlet containers.
- avoid completely overridding any method. Where its necessary to do so, the extension must provide equivalent function as specified in this specification.
8.5 Cohabitating with the Bridge's ViewHandler
Because of limitations in the Faces configuration environment there is no way to order extensions that are defined (exclusively) in the faces-config.xml. This applies to the Faces ViewHandler. This means when running in an environment where other subsystems also introduce a ViewHandler, one can't predict whether the bridge's ViewHandler will take precedence or not. The bridge is designed to cohabitate with these other ViewHandlers regardless of the actual precedence order. However the same may not be true of these other ViewHandlers. To work correctly in a portlet environment with the bridge, other ViewHandler extensions are expected to:- Not run any (servlet) non-portlet container specific code when executing a portlet request.
- If the extension's ViewHandler.createView() returns its own UIViewRoot whose Class.getName isn't javax.faces.component.UIViewRoot then the extension should have its UIViewRoot implement the same semantics for portlet namespacing as described in section 6.6. I.e. the implementation class of its UIViewRoot should be annotated to indicate it implements the portlet namespacing semantics and also provide such an implementation.
- If the extension's ViewHandler.renderView() handles its own form of rendering then the extension should ensure the same style of response interleaving as provided by the default renderView and the bridge.
8.6 Cohabitating with the Bridge's StateManager
Because of limitations in the Faces configuration environment there is no way to order extensions that are defined (exclusively) in the faces-config.xml. This applies to the Faces StateManager. This means when running in an environment where other subsystems also introduce a StateManager one can't predict whether the bridge's StateManager will take precedence or not. The bridge is designed to cohabitate with these other StateManagers regardless of the actual precedence order. However the same may not be true of these other StateManagers. To work correctly in a portlet environment with the bridge, other StateManager extensions are expected to:- Not generate any output directly within the writeState(FacesContext context, Object state). I.e. the extension should rely/override other methods that are called when writeState is executed to generate any output. If this is not feasible, the extension developer should document the issue to inform portlet application developers that when using the extension in a bridge environment they need to move the StateManager configuration from the bridge jar's faces-config.xml and put it into the applications (WEB-INF) faces-config.xml. This ensures the bridge's StateManager runs before the extensions and hence isn't obscured by it.
- Delegate writeState(FacesContext context, Object state) to the next StateManager in the chain. Note: a common practice when implementing a StateManager (in earlier Faces versions) was to extend javax.faces.application.StateManager and to delegate calls to this super class. To work properly with the bridge such implementations need to change to delegate to the next StateManager in the chain. This is most easily done by reimplementing the StateManager as an extension of javax.faces.application.StateManagerWrapper.