You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by st...@apache.org on 2013/04/23 19:28:09 UTC
git commit: DELTASPIKE-289 windowId detection code with JavaScript
and intermediate page
Updated Branches:
refs/heads/master 566675190 -> aded57f8f
DELTASPIKE-289 windowId detection code with JavaScript and intermediate page
partly ported over from MyFaces CODI, partly rewritten.
Passing the windowId via hidden input field
Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/aded57f8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/aded57f8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/aded57f8
Branch: refs/heads/master
Commit: aded57f8faa5c23934839ac6b44e1376ea99c07b
Parents: 5666751
Author: Mark Struberg <st...@apache.org>
Authored: Tue Apr 23 19:09:28 2013 +0200
Committer: Mark Struberg <st...@apache.org>
Committed: Tue Apr 23 19:09:28 2013 +0200
----------------------------------------------------------------------
.../component/window/WindowIdHolderComponent.java | 158 +++++++++++++++
.../WindowIdHolderComponentHtmlRenderer.java | 85 ++++++++
.../jsf/impl/scope/window/DefaultClientWindow.java | 61 ++++--
.../impl/scope/window/WindowIdHolderComponent.java | 154 --------------
.../scope/window/WindowIdRenderKitFactory.java | 101 ---------
.../scope/window/WindowIdRenderKitWrapper.java | 92 ---------
.../main/resources/META-INF/deltaspike.taglib.xml | 15 ++
.../src/main/resources/META-INF/faces-config.xml | 2 +-
.../META-INF/resources/js/windowhandler.js | 59 ++++--
.../src/main/resources/static/windowhandler.html | 30 ++-
.../impl/scope/window/WindowScopedContextTest.java | 99 +++++++++
.../window/beans/WindowScopedBackingBean.java | 50 +++++
.../resources/windowScopedContextTest/page.xhtml | 47 +++++
13 files changed, 554 insertions(+), 399 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponent.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponent.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponent.java
new file mode 100644
index 0000000..4ec76c5
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponent.java
@@ -0,0 +1,158 @@
+/*
+ * 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.component.window;
+
+import javax.faces.component.FacesComponent;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * UI Component holder for the windowId in case of post-backs.
+ * We store this component as direct child in the ViewRoot
+ * and evaluate it's value on postbacks.
+ */
+@FacesComponent(WindowIdHolderComponent.COMPONENT_TYPE)
+public class WindowIdHolderComponent extends UIOutput
+{
+ public static final String COMPONENT_TYPE = "org.apache.deltaspike.WindowIdHolder";
+
+ private static final Logger logger = Logger.getLogger(WindowIdHolderComponent.class.getName());
+
+ private String windowId;
+
+ /**
+ * Default constructor might be invoked by the jsf implementation
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public WindowIdHolderComponent()
+ {
+ }
+
+ /**
+ * Constructor which creates the holder for the given window-id
+ * @param windowId current window-id
+ */
+ public WindowIdHolderComponent(String windowId)
+ {
+ this.windowId = windowId;
+ }
+
+ /**
+ * Needed for server-side window-handler and client-side window handler for supporting postbacks
+ */
+ public static void addWindowIdHolderComponent(FacesContext facesContext, String windowId)
+ {
+ if (windowId == null || windowId.length() == 0)
+ {
+ return;
+ }
+
+ UIViewRoot uiViewRoot = facesContext.getViewRoot();
+
+ if (uiViewRoot == null)
+ {
+ return;
+ }
+
+ WindowIdHolderComponent existingWindowIdHolder = getWindowIdHolderComponent(uiViewRoot);
+ if (existingWindowIdHolder != null)
+ {
+ if (!windowId.equals(existingWindowIdHolder.getWindowId()))
+ {
+ logger.log(Level.FINE, "updating WindowIdHolderComponent from %1 to %2",
+ new Object[]{existingWindowIdHolder.getId(), windowId});
+
+ existingWindowIdHolder.changeWindowId(windowId);
+ }
+ return;
+ }
+ else
+ {
+ // add as first child
+ uiViewRoot.getChildren().add(0, new WindowIdHolderComponent(windowId));
+ }
+ }
+
+ public static WindowIdHolderComponent getWindowIdHolderComponent(UIViewRoot uiViewRoot)
+ {
+ List<UIComponent> uiComponents = uiViewRoot.getChildren();
+
+ // performance improvement - don't change - see EXTCDI-256 :
+ for (int i = 0, size = uiComponents.size(); i < size; i++)
+ {
+ UIComponent uiComponent = uiComponents.get(i);
+ if (uiComponent instanceof WindowIdHolderComponent)
+ {
+ //in this case we have the same view-root
+ return (WindowIdHolderComponent) uiComponent;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Object saveState(FacesContext facesContext)
+ {
+ Object[] values = new Object[2];
+ values[0] = super.saveState(facesContext);
+ values[1] = windowId;
+ return values;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void restoreState(FacesContext facesContext, Object state)
+ {
+ if (state == null)
+ {
+ return;
+ }
+
+ Object[] values = (Object[]) state;
+ super.restoreState(facesContext, values[0]);
+
+ windowId = (String) values[1];
+ }
+
+ /**
+ * @return the current windowId
+ */
+ public String getWindowId()
+ {
+ return windowId;
+ }
+
+ void changeWindowId(String windowId)
+ {
+ this.windowId = windowId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponentHtmlRenderer.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponentHtmlRenderer.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponentHtmlRenderer.java
new file mode 100644
index 0000000..ff31933
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/component/window/WindowIdHolderComponentHtmlRenderer.java
@@ -0,0 +1,85 @@
+/*
+ * 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.component.window;
+
+import javax.faces.application.ResourceDependencies;
+import javax.faces.application.ResourceDependency;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.FacesRenderer;
+import javax.faces.render.Renderer;
+import java.io.IOException;
+
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.core.spi.scope.window.WindowContext;
+
+
+/**
+ * HtmlRenderer for our dsWindowId hidden field.
+ * This gets used for post requests.
+ */
+@FacesRenderer(componentFamily = WindowIdHolderComponent.COMPONENT_FAMILY,
+ rendererType = WindowIdHolderComponent.COMPONENT_TYPE)
+@ResourceDependencies( {
+ @ResourceDependency(library = "js", name = "windowhandler.js", target = "head"),
+ @ResourceDependency(library = "javax.faces", name = "jsf.js", target = "head") } )
+public class WindowIdHolderComponentHtmlRenderer extends Renderer
+{
+ private volatile WindowContext windowContext;
+
+
+ /**
+ * Write a simple hidden field into the form.
+ * This might change in the future...
+ * @param context
+ * @param component
+ * @throws IOException
+ */
+ @Override
+ public void encodeBegin(FacesContext context, UIComponent component) throws IOException
+ {
+ super.encodeBegin(context, component);
+
+ String windowId = getWindowContext().getCurrentWindowId();
+
+ ResponseWriter writer = context.getResponseWriter();
+ writer.startElement("script", component);
+ writer.writeAttribute("type", "text/javascript", null);
+ writer.write("window.deltaspikeJsWindowId=" + windowId + ";");
+
+ writer.endElement("script");
+ }
+
+ private WindowContext getWindowContext()
+ {
+ if (windowContext == null)
+ {
+ synchronized (this)
+ {
+ if (windowContext == null)
+ {
+ windowContext = BeanProvider.getContextualReference(WindowContext.class);
+ }
+ }
+ }
+
+ return windowContext;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
index 3ea9478..3118502 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
@@ -20,7 +20,6 @@ package org.apache.deltaspike.jsf.impl.scope.window;
import javax.enterprise.context.ApplicationScoped;
import javax.faces.FacesException;
-import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
@@ -29,6 +28,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Map;
+import java.util.Random;
import java.util.logging.Logger;
import org.apache.deltaspike.core.spi.scope.window.WindowContext;
@@ -51,8 +52,26 @@ import static org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig.Clie
@ApplicationScoped
public class DefaultClientWindow implements ClientWindow
{
+
+ /**
+ * Value which can be used as "window-id" by external clients which aren't aware of windows.
+ * It deactivates e.g. the redirect for the initial request.
+ */
+ public static final String AUTOMATED_ENTRY_POINT_PARAMETER_KEY = "automatedEntryPoint";
+
+ /**
+ * The parameter for the windowId for GET requests
+ */
+ public static final String DELTASPIKE_WINDOW_ID_PARAM = "windowId";
+
+ /**
+ * The parameter for the windowId for POST requests
+ */
+ public static final String DELTASPIKE_WINDOW_ID_POST_PARAM = "dsPostWindowId";
+
private static final Logger logger = Logger.getLogger(DefaultClientWindow.class.getName());
+
private static final String WINDOW_ID_COOKIE_PREFIX = "dsWindowId-";
private static final String DELTASPIKE_REQUEST_TOKEN = "dsRid";
@@ -60,6 +79,7 @@ public class DefaultClientWindow implements ClientWindow
private static final String WINDOW_ID_REPLACE_PATTERN = "$$windowIdValue$$";
private static final String NOSCRIPT_URL_REPLACE_PATTERN = "$$noscriptUrl$$";
+
/**
* Use this parameter to force a 'direct' request from the clients without any windowId detection
* We keep this name for backward compat with CODI.
@@ -106,10 +126,19 @@ public class DefaultClientWindow implements ClientWindow
}
String windowId = getVerifiedWindowIdFromCookie(externalContext);
- if (windowId == null)
+
+ boolean newWindowIdRequested = false;
+ if (AUTOMATED_ENTRY_POINT_PARAMETER_KEY.equals(windowId))
+ {
+ // this is a marker for generating a new windowId
+ windowId = generateNewWindowId();
+ newWindowIdRequested = true;
+ }
+
+ if (windowId == null || newWindowIdRequested)
{
// GET request without windowId - send windowhandlerfilter.html to get the windowId
- sendWindowHandlerHtml(externalContext, null);
+ sendWindowHandlerHtml(externalContext, windowId);
facesContext.responseComplete();
}
@@ -118,23 +147,23 @@ public class DefaultClientWindow implements ClientWindow
}
/**
+ * Create a unique windowId
+ * @return
+ */
+ private String generateNewWindowId()
+ {
+ //X TODO proper mechanism
+ return "" + (new Random()).nextInt() % 10000;
+ }
+
+ /**
* Extract the windowId for http POST
*/
private String getPostBackWindowId(FacesContext facesContext)
{
- UIViewRoot uiViewRoot = facesContext.getViewRoot();
-
- if (uiViewRoot != null)
- {
- WindowIdHolderComponent existingWindowIdHolder
- = WindowIdHolderComponent.getWindowIdHolderComponent(uiViewRoot);
- if (existingWindowIdHolder != null)
- {
- return existingWindowIdHolder.getWindowId();
- }
- }
-
- return null;
+ Map<String, String> requestParams = facesContext.getExternalContext().getRequestParameterMap();
+ String windowId = requestParams.get(DELTASPIKE_WINDOW_ID_POST_PARAM);
+ return windowId;
}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
deleted file mode 100644
index e4f7326..0000000
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.scope.window;
-
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIOutput;
-import javax.faces.component.UIViewRoot;
-import javax.faces.context.FacesContext;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-
-/**
- * UI Component holder for the windowId in case of post-backs.
- * We store this component as direct child in the ViewRoot
- * and evaluate it's value on postbacks.
- */
-public class WindowIdHolderComponent extends UIOutput
-{
- private static final Logger logger = Logger.getLogger(WindowIdHolderComponent.class.getName());
-
- private String windowId;
-
- /**
- * Default constructor might be invoked by the jsf implementation
- */
- @SuppressWarnings("UnusedDeclaration")
- public WindowIdHolderComponent()
- {
- }
-
- /**
- * Constructor which creates the holder for the given window-id
- * @param windowId current window-id
- */
- public WindowIdHolderComponent(String windowId)
- {
- this.windowId = windowId;
- }
-
- /**
- * Needed for server-side window-handler and client-side window handler for supporting postbacks
- */
- public static void addWindowIdHolderComponent(FacesContext facesContext, String windowId)
- {
- if (windowId == null || windowId.length() == 0)
- {
- return;
- }
-
- UIViewRoot uiViewRoot = facesContext.getViewRoot();
-
- if (uiViewRoot == null)
- {
- return;
- }
-
- WindowIdHolderComponent existingWindowIdHolder = getWindowIdHolderComponent(uiViewRoot);
- if (existingWindowIdHolder != null)
- {
- if (!windowId.equals(existingWindowIdHolder.getWindowId()))
- {
- logger.log(Level.FINE, "updating WindowIdHolderComponent from %1 to %2",
- new Object[]{existingWindowIdHolder.getId(), windowId});
-
- existingWindowIdHolder.changeWindowId(windowId);
- }
- return;
- }
- else
- {
- // add as first child
- uiViewRoot.getChildren().add(0, new WindowIdHolderComponent(windowId));
- }
- }
-
- public static WindowIdHolderComponent getWindowIdHolderComponent(UIViewRoot uiViewRoot)
- {
- List<UIComponent> uiComponents = uiViewRoot.getChildren();
-
- // performance improvement - don't change - see EXTCDI-256 :
- for (int i = 0, size = uiComponents.size(); i < size; i++)
- {
- UIComponent uiComponent = uiComponents.get(i);
- if (uiComponent instanceof WindowIdHolderComponent)
- {
- //in this case we have the same view-root
- return (WindowIdHolderComponent) uiComponent;
- }
- }
-
- return null;
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Object saveState(FacesContext facesContext)
- {
- Object[] values = new Object[2];
- values[0] = super.saveState(facesContext);
- values[1] = windowId;
- return values;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void restoreState(FacesContext facesContext, Object state)
- {
- if (state == null)
- {
- return;
- }
-
- Object[] values = (Object[]) state;
- super.restoreState(facesContext, values[0]);
-
- windowId = (String) values[1];
- }
-
- /**
- * @return the current windowId
- */
- public String getWindowId()
- {
- return windowId;
- }
-
- void changeWindowId(String windowId)
- {
- this.windowId = windowId;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
deleted file mode 100644
index 883ddb0..0000000
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.scope.window;
-
-import javax.faces.context.FacesContext;
-import javax.faces.render.RenderKit;
-import javax.faces.render.RenderKitFactory;
-import java.util.Iterator;
-
-import org.apache.deltaspike.core.spi.activation.Deactivatable;
-import org.apache.deltaspike.core.util.ClassDeactivationUtils;
-
-
-/**
- * Registers the @{link WindowIdRenderKit}
- */
-public class WindowIdRenderKitFactory extends RenderKitFactory implements Deactivatable
-{
- private final RenderKitFactory wrapped;
-
- private final boolean deactivated;
-
- /**
- * Constructor for wrapping the given {@link javax.faces.render.RenderKitFactory}
- * @param wrapped render-kit-factory which will be wrapped
- */
- public WindowIdRenderKitFactory(RenderKitFactory wrapped)
- {
- this.wrapped = wrapped;
- this.deactivated = !isActivated();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addRenderKit(String s, RenderKit renderKit)
- {
- wrapped.addRenderKit(s, renderKit);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public RenderKit getRenderKit(FacesContext facesContext, String s)
- {
- RenderKit renderKit = wrapped.getRenderKit(facesContext, s);
-
- if (renderKit == null)
- {
- return null;
- }
-
- if (deactivated)
- {
- return renderKit;
- }
-
- return new WindowIdRenderKitWrapper(renderKit);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator<String> getRenderKitIds()
- {
- return wrapped.getRenderKitIds();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public RenderKitFactory getWrapped()
- {
- return wrapped;
- }
-
- public boolean isActivated()
- {
- return ClassDeactivationUtils.isActivated(getClass());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
deleted file mode 100644
index bb939d5..0000000
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.scope.window;
-
-import javax.faces.context.FacesContext;
-import javax.faces.context.ResponseWriter;
-import javax.faces.render.RenderKit;
-import javax.faces.render.RenderKitWrapper;
-import java.io.Writer;
-
-import org.apache.deltaspike.core.api.provider.BeanProvider;
-import org.apache.deltaspike.core.spi.scope.window.WindowContext;
-
-/**
- * Wraps the RenderKit and adds the
- * {@link WindowIdHolderComponent} to the view tree
- */
-public class WindowIdRenderKitWrapper extends RenderKitWrapper
-{
- private final RenderKit wrapped;
-
- /**
- * This will get initialized lazily to prevent boot order issues
- * with the JSF and CDI containers.
- */
- private volatile WindowContext windowContext;
-
-
- //needed if the renderkit gets proxied - see EXTCDI-215
- protected WindowIdRenderKitWrapper()
- {
- this.wrapped = null;
- }
-
- public WindowIdRenderKitWrapper(RenderKit wrapped)
- {
- this.wrapped = wrapped;
- }
-
- @Override
- public RenderKit getWrapped()
- {
- return wrapped;
- }
-
- /**
- * Adds a {@link WindowIdHolderComponent} with the
- * current windowId to the component tree.
- */
- public ResponseWriter createResponseWriter(Writer writer, String s, String s1)
- {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- String windowId = getWindowContext().getCurrentWindowId();
-
- WindowIdHolderComponent.addWindowIdHolderComponent(facesContext, windowId);
-
- return wrapped.createResponseWriter(writer, s, s1);
- }
-
-
- private WindowContext getWindowContext()
- {
- if (windowContext == null)
- {
- synchronized (this)
- {
- if (windowContext == null)
- {
- windowContext = BeanProvider.getContextualReference(WindowContext.class);
- }
- }
- }
-
- return windowContext;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/resources/META-INF/deltaspike.taglib.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/deltaspike.taglib.xml b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/deltaspike.taglib.xml
new file mode 100644
index 0000000..947063f
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/deltaspike.taglib.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
+ version="2.0">
+ <namespace>http://deltaspike.apache.org/jsf</namespace>
+
+ <tag>
+ <tag-name>windowId</tag-name>
+ <component>
+ <component-type>org.apache.deltaspike.WindowIdHolder</component-type>
+ <renderer-type>org.apache.deltaspike.WindowIdHolder</renderer-type>
+ </component>
+ </tag>
+</facelet-taglib>
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
index 8b7b43a..de8ef13 100644
--- a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
+++ b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
@@ -37,6 +37,6 @@
<factory>
<lifecycle-factory>org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeLifecycleFactoryWrapper</lifecycle-factory>
<faces-context-factory>org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory</faces-context-factory>
- <render-kit-factory>org.apache.deltaspike.jsf.impl.scope.window.WindowIdRenderKitFactory</render-kit-factory>
</factory>
+
</faces-config>
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/resources/META-INF/resources/js/windowhandler.js
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/resources/js/windowhandler.js b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/resources/js/windowhandler.js
index b563b31..c7f6bca 100644
--- a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/resources/js/windowhandler.js
+++ b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/resources/js/windowhandler.js
@@ -73,28 +73,43 @@ function equalsIgnoreCase(source, destination) {
}
/** This method will be called onWindowLoad and after AJAX success */
-function applyOnClick() {
- var links = document.getElementsByTagName("a");
- for (var i = 0; i < links.length; i++) {
- if (!links[i].onclick) {
- links[i].onclick = function() {storeWindowTree(); return true;};
- } else {
- // prevent double decoration
- if (!("" + links[i].onclick).match(".*storeWindowTree().*")) {
- //the function wrapper is important otherwise the
- //last onclick handler would be assigned to oldonclick
- (function storeEvent() {
- var oldonclick = links[i].onclick;
- links[i].onclick = function(evt) {
- //ie handling added
- evt = evt || window.event;
+function applyWindowId() {
+ if (isHtml5()) { // onClick handling
+ var links = document.getElementsByTagName("a");
+ for (var i = 0; i < links.length; i++) {
+ if (!links[i].onclick) {
+ links[i].onclick = function() {storeWindowTree(); return true;};
+ } else {
+ // prevent double decoration
+ if (!("" + links[i].onclick).match(".*storeWindowTree().*")) {
+ //the function wrapper is important otherwise the
+ //last onclick handler would be assigned to oldonclick
+ (function storeEvent() {
+ var oldonclick = links[i].onclick;
+ links[i].onclick = function(evt) {
+ //ie handling added
+ evt = evt || window.event;
- return storeWindowTree() && oldonclick(evt);
- };
- })();
+ return storeWindowTree() && oldonclick(evt);
+ };
+ })();
+ }
}
}
}
+ var forms = document.getElementsByTagName("form");
+ for (var i = 0; i < forms.length; i++) {
+ var form = forms[i];
+ var windowIdHolder = form.elements["dsPostWindowId"];
+ if (!windowIdHolder) {
+ windowIdHolder = document.createElement("INPUT");
+ windowIdHolder.name = "dsPostWindowId";
+ windowIdHolder.type = "hidden";
+ form.appendChild(windowIdHolder);
+ }
+
+ windowIdHolder.value = window.deltaspikeJsWindowId;
+ }
}
function getUrlParameter(name) {
@@ -159,7 +174,7 @@ function eraseRequestCookie() {
var ajaxOnClick = function ajaxDecorateClick(event) {
if (event.status=="success") {
- applyOnClick();
+ applyWindowId();
}
}
@@ -171,10 +186,8 @@ window.onload = function(evt) {
} finally {
eraseRequestCookie(); // manually erase the old dsRid cookie because Firefox doesn't do it properly
assertWindowId();
- if (isHtml5()) {
- applyOnClick();
- jsf.ajax.addOnEvent(ajaxOnClick);
- }
+ applyWindowId();
+ jsf.ajax.addOnEvent(ajaxOnClick);
}
}
})();
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/main/resources/static/windowhandler.html
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/static/windowhandler.html b/deltaspike/modules/jsf/impl/src/main/resources/static/windowhandler.html
index c096722..30e622a 100644
--- a/deltaspike/modules/jsf/impl/src/main/resources/static/windowhandler.html
+++ b/deltaspike/modules/jsf/impl/src/main/resources/static/windowhandler.html
@@ -135,29 +135,35 @@ function setUrlParam(baseUrl, paramName, paramValue) {
replaceContent();
window.onload = function() {
+ // uncomment the following line to debug the intermediate page
+ // if (!confirm('reload?')) { return true; }
+
loadCss(true);
// this will be replaced in the phase listener
- var windowId = '$$windowIdValue$$';
- if (windowId == 'uninitializedWindowId') {
- windowId = window.name
- }
+ var windowId = window.name;
+ var urlId = windowId;
if (!windowId || windowId.length < 1) {
- // request a new windowId
- windowId = 'automatedEntryPoint';
+ var newWindowId = '$$windowIdValue$$';
+ if (newWindowId != 'uninitializedWindowId') {
+ window.name = newWindowId; // set the window.name with our windowId
+ windowId = newWindowId;
+ urlId = windowId;
+ }
+ else {
+ windowId = 'automatedEntryPoint';
+ urlId = null;
+ }
}
- window.name = windowId;
-
- // uncomment the following line to debug the intermediate page
- // if (!confirm('reload?')) { return true; }
-
// 3 seconds expiry time
var expdt = new Date();
expdt.setTime(expdt.getTime()+(3*1000));
var expires = "; expires="+expdt.toGMTString();
- var requestToken = Math.floor(Math.random()*1001);
+ var requestToken = Math.floor(Math.random()*999);
var newUrl = setUrlParam(window.location.href, "dsRid", requestToken);
+
+ // we still add hte windowId page param to support lazy windowId dropping for some clients
newUrl = setUrlParam(newUrl, "windowId", windowId);
document.cookie = 'dsWindowId-' + requestToken + '=' + windowId + expires+"; path=/";
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/WindowScopedContextTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/WindowScopedContextTest.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/WindowScopedContextTest.java
new file mode 100644
index 0000000..6f84fe8
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/WindowScopedContextTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.test.jsf.impl.scope.window;
+
+
+import java.net.URL;
+
+import org.apache.deltaspike.test.category.WebProfileCategory;
+import org.apache.deltaspike.test.jsf.impl.scope.window.beans.WindowScopedBackingBean;
+import org.apache.deltaspike.test.jsf.impl.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.arquillian.warp.WarpTest;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+
+/**
+ * Test for the DeltaSpike JsfMessage Producer
+ */
+@WarpTest
+@RunWith(Arquillian.class)
+@Category(WebProfileCategory.class)
+public class WindowScopedContextTest
+{
+ @Drone
+ private WebDriver driver;
+
+ @ArquillianResource
+ private URL contextPath;
+
+ @Deployment
+ public static WebArchive deploy()
+ {
+ return ShrinkWrap
+ .create(WebArchive.class, "windowScopedContextTest.war")
+ .addPackage(WindowScopedBackingBean.class.getPackage())
+ .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreAndJsfArchive())
+ .addAsLibraries(ArchiveUtils.getDeltaSpikeSecurityArchive())
+ .addAsWebInfResource("default/WEB-INF/web.xml", "web.xml")
+ .addAsWebResource("META-INF/resources/js/windowhandler.js", "resources/js/windowhandler.js")
+ .addAsWebResource("windowScopedContextTest/page.xhtml", "page.xhtml")
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+
+ @Test
+ @RunAsClient
+ public void testWindowId() throws Exception
+ {
+ System.out.println("contextpath= " + contextPath);
+ //X Thread.sleep(600000L);
+
+ driver.get(new URL(contextPath, "page.xhtml").toString());
+
+ //X comment this in if you like to debug the server
+ //X I've already reported ARQGRA-213 for it
+ //X
+
+ WebElement inputField = driver.findElement(By.id("test:valueInput"));
+ inputField.sendKeys("23");
+
+ WebElement button = driver.findElement(By.id("test:saveButton"));
+ button.click();
+
+ Assert.assertTrue(ExpectedConditions.textToBePresentInElement(By.id("test:valueOutput"), "23").apply(driver));
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/beans/WindowScopedBackingBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/beans/WindowScopedBackingBean.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/beans/WindowScopedBackingBean.java
new file mode 100644
index 0000000..8a58d48
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/scope/window/beans/WindowScopedBackingBean.java
@@ -0,0 +1,50 @@
+/*
+* 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.test.jsf.impl.scope.window.beans;
+
+import javax.inject.Named;
+import java.io.Serializable;
+
+import org.apache.deltaspike.core.api.scope.WindowScoped;
+
+/**
+ * WindowScoped sample backing bean.
+ */
+@WindowScoped
+@Named("windowScopedBean")
+public class WindowScopedBackingBean implements Serializable
+{
+ private int i = 0;
+
+ public int getI()
+ {
+ return i;
+ }
+
+ public void setI(int i)
+ {
+ this.i = i;
+ }
+
+ public String someAction()
+ {
+ // stay on the page.
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/aded57f8/deltaspike/modules/jsf/impl/src/test/resources/windowScopedContextTest/page.xhtml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/test/resources/windowScopedContextTest/page.xhtml b/deltaspike/modules/jsf/impl/src/test/resources/windowScopedContextTest/page.xhtml
new file mode 100644
index 0000000..c0a64c4
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/test/resources/windowScopedContextTest/page.xhtml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:ds="http://deltaspike.apache.org/jsf">
+
+<h:head>
+
+</h:head>
+
+<h:body>
+<ds:windowId/>
+<div>
+ <h:form id="test">
+ <h:outputLabel for="valueInput" value="WindowScoped value:"/>
+ <h:inputText id="valueInput" value="#{windowScopedBean.i}"/>
+ <br/>
+ <h:outputLabel for="valueOutput" value="backing bean value:"/>
+ <h:outputText id="valueOutput" value="#{windowScopedBean.i}"/>
+ <br/>
+ <h:commandButton id="saveButton" action="#{windowScopedBean.someAction}" value="save"/>
+ </h:form>
+</div>
+</h:body>
+</html>