You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2013/04/16 12:45:55 UTC
svn commit: r1468357 - in /myfaces/tobago/trunk:
tobago-core/src/main/faces-config/
tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/
tobago-core/src/main/java/org/apache/myfaces/tobago/util/
tobago-example/tobago-example-demo/src/main...
Author: weber
Date: Tue Apr 16 10:45:54 2013
New Revision: 1468357
URL: http://svn.apache.org/r1468357
Log:
TOBAGO-1248 - Navigate to a new view with partialReload (AJAX) - (Support of CODE_RELOAD_REQUIRED)
Added:
myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java
myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java
Modified:
myfaces/tobago/trunk/tobago-core/src/main/faces-config/faces-config.xml
myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxResponseRenderer.java
myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/reference/PartialReloadController.java
myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/50-partial/partial.xhtml
Modified: myfaces/tobago/trunk/tobago-core/src/main/faces-config/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/faces-config/faces-config.xml?rev=1468357&r1=1468356&r2=1468357&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/faces-config/faces-config.xml (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/faces-config/faces-config.xml Tue Apr 16 10:45:54 2013
@@ -25,6 +25,11 @@
<application>
<default-render-kit-id>tobago</default-render-kit-id>
</application>
+
+ <lifecycle>
+ <phase-listener>org.apache.myfaces.tobago.internal.ajax.AjaxNavigationListener</phase-listener>
+ </lifecycle>
+
<component>
<component-type>javax.faces.NamingContainer</component-type>
<component-class>org.apache.myfaces.tobago.component.UINamingContainer</component-class>
Added: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java?rev=1468357&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java (added)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java Tue Apr 16 10:45:54 2013
@@ -0,0 +1,44 @@
+/*
+ * 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.myfaces.tobago.internal.ajax;
+
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+public class AjaxNavigationListener implements PhaseListener {
+
+ public void afterPhase(PhaseEvent phaseEvent) {
+ if (phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW) {
+ AjaxNavigationState.storeIncomingView(phaseEvent.getFacesContext());
+ }
+ }
+
+ public void beforePhase(PhaseEvent phaseEvent) {
+ if (phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW) {
+ AjaxNavigationState.handleNavigation(phaseEvent.getFacesContext());
+ }
+ }
+
+ public PhaseId getPhaseId() {
+ return PhaseId.ANY_PHASE;
+ }
+
+}
Added: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java?rev=1468357&view=auto
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java (added)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java Tue Apr 16 10:45:54 2013
@@ -0,0 +1,154 @@
+/*
+ * 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.myfaces.tobago.internal.ajax;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class AjaxNavigationState {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AjaxNavigationState.class);
+
+ private static final String SESSION_KEY = "tobago-AjaxNavigationState";
+
+ private static final String VIEW_ROOT_KEY = "tobago-AjaxNavigationState-VIEW_ROOT_KEY";
+
+ private UIViewRoot viewRoot;
+
+ private Measure clientWidth;
+
+ private Measure clientHeight;
+
+ private Map<String, List<FacesMessage>> messages;
+
+ private AjaxNavigationState(FacesContext facesContext) {
+ ExternalContext externalContext = facesContext.getExternalContext();
+ externalContext.getSessionMap().put(SESSION_KEY, this);
+ viewRoot = facesContext.getViewRoot();
+ // TODO: Save page dimension
+// AbstractUIPage page = ComponentUtils.findPage((UIViewRoot) externalContext.getRequestMap().get(VIEW_ROOT_KEY));
+// clientWidth = page.getCurrentWidth();
+// clientHeight = page.getCurrentHeight();
+ messages = new HashMap<String, List<FacesMessage>>();
+ Iterator<String> iterator = facesContext.getClientIdsWithMessages();
+ while (iterator.hasNext()) {
+ addFacesMessages(facesContext, iterator.next());
+ }
+ addFacesMessages(facesContext, null);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Saved viewRoot.getViewId() = \"{}\"", viewRoot.getViewId());
+ LOG.trace("Saved clientWidth = \"{}\"", clientWidth);
+ LOG.trace("Saved clientHeight = \"{}\"", clientHeight);
+ for (Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+ for (FacesMessage message : entry.getValue()) {
+ LOG.trace("Saved message \"{}\" : \"{}\"", entry.getKey(), message);
+ }
+ }
+ }
+ }
+
+ private void addFacesMessages(FacesContext facesContext, String clientId) {
+ Iterator<FacesMessage> facesMessages = facesContext.getMessages(clientId);
+ while (facesMessages.hasNext()) {
+ addFacesMessage(clientId, facesMessages.next());
+ }
+ }
+
+ private void addFacesMessage(String clientId, FacesMessage facesMessage) {
+ List<FacesMessage> facesMessages = messages.get(clientId);
+ if (facesMessages == null) {
+ facesMessages = new ArrayList<FacesMessage>();
+ messages.put(clientId, facesMessages);
+ }
+ facesMessages.add(facesMessage);
+ }
+
+ private void restoreView(FacesContext facesContext) {
+ facesContext.setViewRoot(viewRoot);
+ Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+ requestMap.put("tobago-page-clientDimension-width", clientWidth);
+ requestMap.put("tobago-page-clientDimension-height", clientHeight);
+ for (Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+ for (FacesMessage facesMessage : entry.getValue()) {
+ facesContext.addMessage(entry.getKey(), facesMessage);
+ }
+ }
+ facesContext.renderResponse();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Restored viewRoot.getViewId() = \"{}\"", viewRoot.getViewId());
+ LOG.trace("Restored clientWidth = \"{}\"", clientWidth);
+ LOG.trace("Restored clientHeight = \"{}\"", clientHeight);
+ for (Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+ for (FacesMessage message : entry.getValue()) {
+ LOG.trace("Restored message \"{}\" : \"{}\"", entry.getKey(), message);
+ }
+ }
+ }
+
+ }
+
+ public static void storeIncomingView(FacesContext facesContext) {
+ UIViewRoot viewRoot = facesContext.getViewRoot();
+ LOG.trace("incoming viewId = \"{}\"", viewRoot.getViewId());
+ facesContext.getExternalContext().getRequestMap().put(AjaxNavigationState.VIEW_ROOT_KEY, viewRoot);
+ }
+
+ public static boolean isNavigation(FacesContext facesContext) {
+
+ final UIViewRoot viewRoot = facesContext.getViewRoot();
+ LOG.trace("current viewId = \"{}\"", viewRoot.getViewId());
+
+ ExternalContext externalContext = facesContext.getExternalContext();
+ Map<String, Object> requestMap = externalContext.getRequestMap();
+ UIViewRoot incomingViewRoot = (UIViewRoot) requestMap.get(VIEW_ROOT_KEY);
+ if (viewRoot != incomingViewRoot) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("requesting full page reload because of navigation to {} from {}",
+ viewRoot.getViewId(), incomingViewRoot.getViewId());
+ }
+ externalContext.getSessionMap().put(SESSION_KEY, new AjaxNavigationState(facesContext));
+ return true;
+ }
+ return false;
+ }
+
+ public static void handleNavigation(FacesContext facesContext) {
+ Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
+ AjaxNavigationState navigationState = (AjaxNavigationState) sessionMap.remove(AjaxNavigationState.SESSION_KEY);
+ if (navigationState != null) {
+ navigationState.restoreView(facesContext);
+ LOG.trace("force render requested navigation view");
+ }
+ }
+}
Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxResponseRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxResponseRenderer.java?rev=1468357&r1=1468356&r2=1468357&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxResponseRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxResponseRenderer.java Tue Apr 16 10:45:54 2013
@@ -19,6 +19,9 @@
package org.apache.myfaces.tobago.internal.ajax;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import org.apache.myfaces.tobago.component.Attributes;
import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
import org.apache.myfaces.tobago.internal.util.ResponseUtils;
@@ -26,8 +29,6 @@ import org.apache.myfaces.tobago.interna
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.apache.myfaces.tobago.util.EncodeAjaxCallback;
import org.apache.myfaces.tobago.util.RequestUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.faces.FactoryFinder;
import javax.faces.application.StateManager;
@@ -64,44 +65,9 @@ public class AjaxResponseRenderer {
public void renderResponse(FacesContext facesContext) throws IOException {
final UIViewRoot viewRoot = facesContext.getViewRoot();
- RenderKitFactory renderFactory = (RenderKitFactory)
- FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
- RenderKit renderKit = renderFactory.getRenderKit(
- facesContext, viewRoot.getRenderKitId());
-
- LOG.error("TODO: Reimplement AJAX stuff for JSF 2.0");
-/* XXX: reimplement it for JSF 2.0? Works only, when the TobagoLifecycle is active...
- UIViewRoot incomingViewRoot = (UIViewRoot)
- facesContext.getExternalContext().getRequestMap().get(TobagoLifecycle.VIEW_ROOT_KEY);
- if (viewRoot != incomingViewRoot) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("requesting full page reload because of navigation to {} from {}",
- viewRoot.getViewId(), incomingViewRoot.getViewId());
- }
- Map sessionMap = facesContext.getExternalContext().getSessionMap();
- //noinspection unchecked
- sessionMap.put(TobagoLifecycle.VIEW_ROOT_KEY, viewRoot);
- List<Object[]> messageHolders = new ArrayList<Object[]>();
- Iterator clientIds = facesContext.getClientIdsWithMessages();
- while (clientIds.hasNext()) {
- String clientId = (String) clientIds.next();
- Iterator messages = facesContext.getMessages(clientId);
- while (messages.hasNext()) {
- Object[] messageHolder = new Object[2];
- messageHolder[0] = clientId;
- messageHolder[1] = messages.next();
- messageHolders.add(messageHolder);
- }
- }
- if (!messageHolders.isEmpty()) {
- //noinspection unchecked
- sessionMap.put(TobagoLifecycle.FACES_MESSAGES_KEY, messageHolders);
- }
- writeResponse(facesContext, renderKit, true);
- } else {
-*/
- writeResponse(facesContext, renderKit, false);
-// }
+ RenderKitFactory renderFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ RenderKit renderKit = renderFactory.getRenderKit(facesContext, viewRoot.getRenderKitId());
+ writeResponse(facesContext, renderKit, AjaxNavigationState.isNavigation(facesContext));
}
private void renderComponent(FacesContext facesContext, RenderKit renderKit, String clientId, UIComponent component)
@@ -111,9 +77,8 @@ public class AjaxResponseRenderer {
facesContext.setResponseWriter(jsonWriter);
- if (LOG.isDebugEnabled()) {
- LOG.debug("write ajax response for {}", component);
- }
+ LOG.debug("write ajax response for {}", component);
+
writer.write("{\n \"ajaxId\": \"");
writer.write(clientId);
writer.write("\",\n");
Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java?rev=1468357&r1=1468356&r2=1468357&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java Tue Apr 16 10:45:54 2013
@@ -181,13 +181,17 @@ public class ComponentUtils {
}
public static AbstractUIPage findPage(UIComponent component) {
- while (component != null) {
- if (component instanceof AbstractUIPage) {
- return (AbstractUIPage) component;
+ if (component instanceof UIViewRoot) {
+ return findPageBreadthFirst(component);
+ } else {
+ while (component != null) {
+ if (component instanceof AbstractUIPage) {
+ return (AbstractUIPage) component;
+ }
+ component = component.getParent();
}
- component = component.getParent();
+ return null;
}
- return null;
}
public static AbstractUIPage findPage(FacesContext facesContext) {
Modified: myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/reference/PartialReloadController.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/reference/PartialReloadController.java?rev=1468357&r1=1468356&r2=1468357&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/reference/PartialReloadController.java (original)
+++ myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/reference/PartialReloadController.java Tue Apr 16 10:45:54 2013
@@ -24,6 +24,8 @@ import org.apache.myfaces.tobago.example
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import java.util.Date;
@@ -73,7 +75,16 @@ public class PartialReloadController {
// in case of both the select control is not processed during lifecycle
// we need to get the value from the request params
- navigateAction = (String) facesContext.getExternalContext().getRequestParameterMap().get("page:navSelect");
+// navigateAction = (String) facesContext.getExternalContext().getRequestParameterMap().get("page:navSelect");
+
+ AjaxUtils.removeAjaxComponent(facesContext, "page:navTest");
+
+ if (navigationState == null) {
+ ELContext elContext = facesContext.getELContext();
+ ValueExpression expression = facesContext.getApplication().getExpressionFactory()
+ .createValueExpression(elContext, "#{navigationState}", NavigationState.class);
+ navigationState = (NavigationState) expression.getValue(elContext);
+ }
LOG.info("navigateAction = \"" + navigateAction + "\"");
if (navigateAction == null) {
Modified: myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/50-partial/partial.xhtml
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/50-partial/partial.xhtml?rev=1468357&r1=1468356&r2=1468357&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/50-partial/partial.xhtml (original)
+++ myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/content/50-partial/partial.xhtml Tue Apr 16 10:45:54 2013
@@ -115,13 +115,13 @@
<tc:gridLayoutConstraint columnSpan="2"/>
</tc:button>
- <tc:panel>
+ <tc:panel id="navTest">
<tc:gridLayoutConstraint columnSpan="2"/>
<tx:selectOneChoice fieldId="navSelect" value="#{partialReloadController.navigateAction}" label="On Change">
<f:facet name="change">
<!-- XXX value="fixme" should be empty, but it doesn't work with an empty string -->
- <tc:command action="#{partialReloadController.navigateAction}" renderedPartially="fixme"/>
+ <tc:command action="#{partialReloadController.navigateAction}" renderedPartially="navTest"/>
</f:facet>
<f:selectItem itemLabel="Select action" itemValue=""/>
<f:selectItem itemLabel="Reload left" itemValue="left"/>