You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by Apache Wiki <wi...@apache.org> on 2011/08/24 00:09:08 UTC

[Myfaces Wiki] Update of "NestedFacesContext" by LeonardoUribe

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Myfaces Wiki" for change notification.

The "NestedFacesContext" page has been changed by LeonardoUribe:
http://wiki.apache.org/myfaces/NestedFacesContext?action=diff&rev1=2&rev2=3

- === Nested FacesContext ===
+ See the update page on:
  
- If you create a custom FacesContext e.g. like described here [[AccessFacesContextFromServlet]] you might face a problem that e.g. messages added to your custom FacesContext won't show up in h:messages.
+ https://cwiki.apache.org/confluence/display/MYFACES/Resulting+Nested+FacesContext
  
- The FacesServlet creates its own new FacesContext which will be used for all subsequent JSF operations.
- 
- One reason why this is good is, that the FacesServlet can't be sure that your custom FacesContext use the correct ServletRequest/ServletResponse objects.
- 
- An example when your custom FacesContext is not good is when you use requestDispatcher.forward.
- Like my setup:
-  * A custom filter which creates a custom FacesContext
-  * A custom servlet which forwards to the FacesServlet (getServletContext().getRequestDispatcher(jsfPath).forward(req, res);)
-  * The FacesServlet which creates a FacesContext too
- 
- If the FacesServlet uses our own custom FacesContext you will see that JSF did not use the jsfPath for further operations, but the original url - which is false.
- 
- So, I found to let the FacesServlet create a new FacesContext is fine and the easiest solution, but I still wanted it to show any messages added to the custom FacesContext.
- 
- I ended with the following FacesContextFactory (adjust the package names as needed):
- 
- Configuration in faces-config.xml:
- {{{
- 	<factory>
- 		<faces-context-factory>org.apache....StateCopyFacesContextFactory</faces-context-factory>
- 	</factory>
- }}}
- 
- Source:
- {{{
- /*
-  * Licensed to the Apache Software Foundation (ASF) under one
-  * or more contributor license agreements.  See the NOTICE file
-  * distributed with this work for additional information
-  * regarding copyright ownership.  The ASF licenses this file
-  * to you under the Apache License, Version 2.0 (the
-  * "License"); you may not use this file except in compliance
-  * with the License.  You may obtain a copy of the License at
-  *
-  *   http://www.apache.org/licenses/LICENSE-2.0
-  *
-  * Unless required by applicable law or agreed to in writing,
-  * software distributed under the License is distributed on an
-  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  * KIND, either express or implied.  See the License for the
-  * specific language governing permissions and limitations
-  * under the License.
- */
- package org.apache.....;
- 
- import javax.faces.context.FacesContextFactory;
- import javax.faces.context.FacesContext;
- import javax.faces.lifecycle.Lifecycle;
- import javax.faces.FacesException;
- import javax.faces.application.FacesMessage;
- import java.util.Iterator;
- 
- /**
-  * FacesContextFactory which first checks if a FacesContext is already there
-  */
- public class StateCopyFacesContextFactory extends FacesContextFactory
- {
- 	private final FacesContextFactory original;
- 
- 	public StateCopyFacesContextFactory(FacesContextFactory original)
- 	{
- 		this.original = original;
- 	}
- 
- 	@Override
- 	public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle) throws FacesException
- 	{
- 		FacesContext previousContext = FacesContext.getCurrentInstance();
- 
- 		FacesContext newContext = original.getFacesContext(context, request, response, lifecycle);
- 
- 		if (previousContext != null)
- 		{
- 			// transfer the default locale (might have been changed)
- 			newContext.getApplication().setDefaultLocale(previousContext.getApplication().getDefaultLocale());
- 
- 			// transfer all already collected messages
- 			Iterator iterClientIds = previousContext.getClientIdsWithMessages();
- 			while (iterClientIds.hasNext())
- 			{
- 				String clientId = (String) iterClientIds.next();
- 				Iterator iterMessages = previousContext.getMessages(clientId);
- 				while (iterMessages.hasNext())
- 				{
- 					FacesMessage message = (FacesMessage) iterMessages.next();
- 
- 					newContext.addMessage(clientId, message);
- 				}
- 			}
- 		}
- 
- 		return newContext;
- 	}
- }
- }}}
- 
- Notice: This solution do not deal with resetting to the previousContext on newContext.release(). One can enhance it. For me it was sufficient that way as after the JSF request there is nothing further I will do with the FacesContext ... and the problem might be, that then one might copy some state back ... too complicated.
-