You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2013/04/22 03:49:59 UTC
git commit: DELTASPIKE-347 keep faces-messages per default in case of
a redirect
Updated Branches:
refs/heads/master 85a7fdeed -> 566675190
DELTASPIKE-347 keep faces-messages per default in case of a redirect
(first part - rest depends on DELTASPIKE-289)
Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/56667519
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/56667519
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/56667519
Branch: refs/heads/master
Commit: 56667519077805eae5e1c1958091c50d67dc264e
Parents: 85a7fde
Author: gpetracek <gp...@apache.org>
Authored: Mon Apr 22 03:31:04 2013 +0200
Committer: gpetracek <gp...@apache.org>
Committed: Mon Apr 22 03:48:45 2013 +0200
----------------------------------------------------------------------
.../listener/phase/DeltaSpikePhaseListener.java | 15 +++-
.../jsf/impl/listener/phase/WindowMetaData.java | 19 ++++
.../request/DeltaSpikeExternalContextWrapper.java | 48 ++++++++++
.../request/DeltaSpikeFacesContextWrapper.java | 51 +++++++++++
.../jsf/impl/message/FacesMessageEntry.java | 67 ++++++++++++++
.../apache/deltaspike/jsf/impl/util/JsfUtils.java | 70 +++++++++++++++
6 files changed, 268 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/DeltaSpikePhaseListener.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/DeltaSpikePhaseListener.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/DeltaSpikePhaseListener.java
index efc07ea..c5c0672 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/DeltaSpikePhaseListener.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/DeltaSpikePhaseListener.java
@@ -27,6 +27,7 @@ import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.core.spi.activation.Deactivatable;
import org.apache.deltaspike.core.util.ClassDeactivationUtils;
import org.apache.deltaspike.jsf.impl.security.ViewRootAccessHandler;
+import org.apache.deltaspike.jsf.impl.util.JsfUtils;
import org.apache.deltaspike.jsf.impl.util.SecurityUtils;
import org.apache.deltaspike.jsf.impl.util.ViewControllerUtils;
import org.apache.deltaspike.security.api.authorization.ErrorViewAwareAccessDeniedException;
@@ -103,7 +104,12 @@ public class DeltaSpikePhaseListener implements PhaseListener, Deactivatable
processInitView(phaseEvent);
- if (PhaseId.RENDER_RESPONSE.equals(phaseEvent.getPhaseId()))
+ if (PhaseId.RESTORE_VIEW.equals(phaseEvent.getPhaseId()))
+ {
+ onAfterRestoreView(phaseEvent.getFacesContext());
+
+ }
+ else if (PhaseId.RENDER_RESPONSE.equals(phaseEvent.getPhaseId()))
{
onAfterRenderResponse(phaseEvent.getFacesContext());
}
@@ -112,6 +118,11 @@ public class DeltaSpikePhaseListener implements PhaseListener, Deactivatable
this.jsfRequestLifecyclePhaseListener.afterPhase(phaseEvent);
}
+ private void onAfterRestoreView(FacesContext facesContext)
+ {
+ JsfUtils.tryToRestoreMessages(facesContext);
+ }
+
private void onAfterRenderResponse(FacesContext facesContext)
{
processPostRenderView(facesContext);
@@ -209,7 +220,7 @@ public class DeltaSpikePhaseListener implements PhaseListener, Deactivatable
}
catch (ContextNotActiveException e)
{
- return; //TODO discuss how we handle it
+ //TODO discuss how we handle it
}
}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/WindowMetaData.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/WindowMetaData.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/WindowMetaData.java
index d7f1c83..3360aee 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/WindowMetaData.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/phase/WindowMetaData.java
@@ -19,8 +19,10 @@
package org.apache.deltaspike.jsf.impl.listener.phase;
import org.apache.deltaspike.core.api.scope.WindowScoped;
+import org.apache.deltaspike.jsf.impl.message.FacesMessageEntry;
import java.io.Serializable;
+import java.util.List;
@WindowScoped
public class WindowMetaData implements Serializable
@@ -29,6 +31,13 @@ public class WindowMetaData implements Serializable
private String initializedViewId;
+ /**
+ * used per default instead of Flash#setKeepMessages,
+ * because there are less issues in view of multi-window support esp. before jsf v2.2 and
+ * a custom window-handler might have special requirements.
+ */
+ private List<FacesMessageEntry> facesMessageEntryList;
+
public String getInitializedViewId()
{
return initializedViewId;
@@ -38,4 +47,14 @@ public class WindowMetaData implements Serializable
{
this.initializedViewId = initializedViewId;
}
+
+ public void setFacesMessageEntryList(List<FacesMessageEntry> facesMessageEntryList)
+ {
+ this.facesMessageEntryList = facesMessageEntryList;
+ }
+
+ public List<FacesMessageEntry> getFacesMessageEntryList()
+ {
+ return facesMessageEntryList;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeExternalContextWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeExternalContextWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeExternalContextWrapper.java
new file mode 100644
index 0000000..afa9782
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeExternalContextWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * 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.deltaspike.jsf.impl.listener.request;
+
+import org.apache.deltaspike.core.spi.activation.Deactivatable;
+import org.apache.deltaspike.jsf.impl.util.JsfUtils;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.ExternalContextWrapper;
+import java.io.IOException;
+
+public class DeltaSpikeExternalContextWrapper extends ExternalContextWrapper implements Deactivatable
+{
+ private final ExternalContext wrapped;
+
+ DeltaSpikeExternalContextWrapper(ExternalContext wrapped)
+ {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public void redirect(String url) throws IOException
+ {
+ JsfUtils.saveFacesMessages(this.wrapped);
+ this.wrapped.redirect(url);
+ }
+
+ public ExternalContext getWrapped()
+ {
+ return wrapped;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeFacesContextWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeFacesContextWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeFacesContextWrapper.java
index f1985e1..2c995a5 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeFacesContextWrapper.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeFacesContextWrapper.java
@@ -22,10 +22,16 @@ import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver;
import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.core.util.ClassDeactivationUtils;
import org.apache.deltaspike.jsf.impl.config.view.DefaultErrorViewAwareExceptionHandlerWrapper;
+import org.apache.deltaspike.jsf.impl.message.FacesMessageEntry;
+import javax.faces.application.FacesMessage;
import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextWrapper;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
class DeltaSpikeFacesContextWrapper extends FacesContextWrapper
{
@@ -35,10 +41,22 @@ class DeltaSpikeFacesContextWrapper extends FacesContextWrapper
private boolean defaultErrorViewExceptionHandlerActivated;
+ private ExternalContext wrappedExternalContext;
+
DeltaSpikeFacesContextWrapper(FacesContext wrappedFacesContext)
{
this.wrappedFacesContext = wrappedFacesContext;
+ if (ClassDeactivationUtils.isActivated(DeltaSpikeExternalContextWrapper.class))
+ {
+ this.wrappedExternalContext =
+ new DeltaSpikeExternalContextWrapper(wrappedFacesContext.getExternalContext());
+ }
+ else
+ {
+ this.wrappedExternalContext = wrappedFacesContext.getExternalContext();
+ }
+
setCurrentInstance(this);
}
@@ -99,6 +117,39 @@ class DeltaSpikeFacesContextWrapper extends FacesContextWrapper
}
}
+ /**
+ * Adds the {@link FacesMessage} also to a request scoped list to allow to preserve them later on
+ * (in case of redirects)
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void addMessage(String componentId, FacesMessage facesMessage)
+ {
+ this.wrappedFacesContext.addMessage(componentId, facesMessage);
+
+ //don't store it directly in the window context - it would trigger a too early restore (in some cases)
+ Map<String, Object> requestMap = getExternalContext().getRequestMap();
+
+ @SuppressWarnings({ "unchecked" })
+ List<FacesMessageEntry> facesMessageEntryList =
+ (List<FacesMessageEntry>)requestMap.get(FacesMessageEntry.class.getName());
+
+ if (facesMessageEntryList == null)
+ {
+ facesMessageEntryList = new CopyOnWriteArrayList<FacesMessageEntry>();
+ requestMap.put(FacesMessageEntry.class.getName(), facesMessageEntryList);
+ }
+
+ facesMessageEntryList.add(new FacesMessageEntry(componentId, facesMessage));
+ }
+
+ @Override
+ public ExternalContext getExternalContext()
+ {
+ return this.wrappedExternalContext;
+ }
+
@Override
public FacesContext getWrapped()
{
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/message/FacesMessageEntry.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/message/FacesMessageEntry.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/message/FacesMessageEntry.java
new file mode 100644
index 0000000..b41020e
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/message/FacesMessageEntry.java
@@ -0,0 +1,67 @@
+/*
+ * 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.deltaspike.jsf.impl.message;
+
+import javax.enterprise.inject.Typed;
+import javax.faces.application.FacesMessage;
+import java.io.Serializable;
+
+/**
+ * Entry for {@link FacesMessage} which have to be stored longer than a request
+ */
+@Typed()
+public class FacesMessageEntry implements Serializable
+{
+ private static final long serialVersionUID = 6831499672107426470L;
+ private String componentId;
+ private FacesMessage facesMessage;
+
+ protected FacesMessageEntry()
+ {
+ }
+
+ /**
+ * Constructor for creating the entry for the given component-id and {@link FacesMessage}
+ * @param componentId current component-id
+ * @param facesMessage current faces-message
+ */
+ public FacesMessageEntry(String componentId, FacesMessage facesMessage)
+ {
+ this.componentId = componentId;
+ this.facesMessage = facesMessage;
+ }
+
+ /**
+ * Returns the current component-id
+ * @return component-id of the entry
+ */
+ public String getComponentId()
+ {
+ return componentId;
+ }
+
+ /**
+ * Returns the current {@link FacesMessage}
+ * @return faces-message of the entry
+ */
+ public FacesMessage getFacesMessage()
+ {
+ return facesMessage;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/56667519/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java
index 734ebb0..63a752a 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/JsfUtils.java
@@ -21,14 +21,20 @@ package org.apache.deltaspike.jsf.impl.util;
import org.apache.deltaspike.core.api.config.view.metadata.ViewConfigResolver;
import org.apache.deltaspike.core.api.provider.BeanProvider;
import org.apache.deltaspike.core.api.config.view.navigation.NavigationParameterContext;
+import org.apache.deltaspike.jsf.api.config.JsfModuleConfig;
+import org.apache.deltaspike.jsf.impl.listener.phase.WindowMetaData;
+import org.apache.deltaspike.jsf.impl.message.FacesMessageEntry;
+import javax.enterprise.context.ContextNotActiveException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
public abstract class JsfUtils
{
@@ -144,4 +150,68 @@ public abstract class JsfUtils
{
return BeanProvider.getContextualReference(ViewConfigResolver.class);
}
+
+ public static void saveFacesMessages(ExternalContext externalContext)
+ {
+ JsfModuleConfig jsfModuleConfig = BeanProvider.getContextualReference(JsfModuleConfig.class);
+
+ if (!jsfModuleConfig.isAlwaysKeepMessages())
+ {
+ return;
+ }
+
+ try
+ {
+ WindowMetaData windowMetaData = BeanProvider.getContextualReference(WindowMetaData.class);
+
+ Map<String, Object> requestMap = externalContext.getRequestMap();
+
+ @SuppressWarnings({ "unchecked" })
+ List<FacesMessageEntry> facesMessageEntryList =
+ (List<FacesMessageEntry>)requestMap.get(FacesMessageEntry.class.getName());
+
+ if (facesMessageEntryList == null)
+ {
+ facesMessageEntryList = new CopyOnWriteArrayList<FacesMessageEntry>();
+ }
+ windowMetaData.setFacesMessageEntryList(facesMessageEntryList);
+ }
+ catch (ContextNotActiveException e)
+ {
+ //TODO log it in case of project-stage development
+ //we can't handle it correctly -> delegate to the jsf-api (which has some restrictions esp. before v2.2)
+ FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
+ }
+ }
+
+ public static void tryToRestoreMessages(FacesContext facesContext)
+ {
+ JsfModuleConfig jsfModuleConfig = BeanProvider.getContextualReference(JsfModuleConfig.class);
+
+ if (!jsfModuleConfig.isAlwaysKeepMessages())
+ {
+ return;
+ }
+
+ try
+ {
+ WindowMetaData windowMetaData = BeanProvider.getContextualReference(WindowMetaData.class);
+
+ @SuppressWarnings({ "unchecked" })
+ List<FacesMessageEntry> facesMessageEntryList = windowMetaData.getFacesMessageEntryList();
+
+ if (facesMessageEntryList != null)
+ {
+ for (FacesMessageEntry facesMessageEntry : facesMessageEntryList)
+ {
+ facesContext.addMessage(facesMessageEntry.getComponentId(), facesMessageEntry.getFacesMessage());
+ }
+ facesMessageEntryList.clear();
+ }
+ }
+ catch (ContextNotActiveException e)
+ {
+ //TODO discuss how we handle it
+ }
+ }
}