Skip to content

Instantly share code, notes, and snippets.

@ivaynberg
Last active August 22, 2016 09:57
Show Gist options
  • Select an option

  • Save ivaynberg/6146817 to your computer and use it in GitHub Desktop.

Select an option

Save ivaynberg/6146817 to your computer and use it in GitHub Desktop.
wicket - ajax requests get their own versioned pages
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/AbstractAjaxResponse.java
@@ -127,12 +127,22 @@ public abstract class AbstractAjaxResponse
}
/**
+ * Retrieves the page instance
+ *
+ * @return page instance
+ */
+ protected Page getPage()
+ {
+ return page;
+ }
+
+ /**
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
index 80c056e..45dce99 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/XmlAjaxResponse.java
@@ -67,16 +67,18 @@ public abstract class XmlAjaxResponse extends AbstractAjaxResponse
response.write(encoding);
response.write("\"?>");
response.write(START_ROOT_ELEMENT);
+ response.write("<page-id>" + getPage().getPageId() + "</page-id>");
}
diff --git a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
index 5fb8a18..8194568 100644
--- a/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
+++ b/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js
@@ -306,6 +306,14 @@
* The Ajax.Request class encapsulates a XmlHttpRequest.
*/
Wicket.Ajax = {};
+
+ /**
+ * This is where the page id of the target page is stored
+ * AjaxRequestHandler will set the correct id, and Ajax calls will pass it in during ajax requests.
+ *
+ * This will allow ajax requests to target a page version other then the one created during the non-ajax page render.
+ */
+ Wicket.Ajax.pageId = undefined;
/**
* Ajax call fires a Wicket Ajax request and processes the response.
@@ -497,7 +505,13 @@
// initialize the array for steps (closures that execute each action)
steps: []
};
-
+
+ data = data.concat({name:"wicket-ajax", value: "true"});
+
+ if (Wicket.Ajax.pageId !== undefined) {
+ data = data.concat({name: "wicket-page-id", value: Wicket.Ajax.pageId});
+ }
+
if (Wicket.Focus.lastFocusId) {
headers["Wicket-FocusedElementId"] = Wicket.Focus.lastFocusId;
}
@@ -798,6 +812,9 @@
form.target = iframe.name;
var separator = (attrs.u.indexOf("?")>-1 ? "&" : "?");
form.action = attrs.u + separator + "wicket-ajax=true&wicket-ajax-baseurl=" + Wicket.Form.encode(getAjaxBaseUrl());
+ if (Wicket.Ajax.pageId !== undefined) {
+ form.action+="&wicket-page-id="+Wicket.Ajax.pageId;
+ }
form.method = "post";
form.enctype = "multipart/form-data";
form.encoding = "multipart/form-data";
@@ -935,6 +952,8 @@
this.processEvaluation(context, node);
} else if (node.tagName === "redirect") {
this.processRedirect(context, node);
+ } else if (node.tagName==="page-id") {
+ Wicket.Ajax.pageId=jQuery(node).text();
}
}
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractComponentMapper.java b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractComponentMapper.java
index f3e3770..3950368 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractComponentMapper.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/AbstractComponentMapper.java
@@ -89,25 +91,41 @@ public abstract class AbstractComponentMapper extends AbstractMapper implements
}
else
{
+
+ PageComponentInfo info = null;
+
for (QueryParameter queryParameter : url.getQueryParameters())
{
if (Strings.isEmpty(queryParameter.getValue()))
{
- PageComponentInfo pageComponentInfo = PageComponentInfo.parse(queryParameter.getName());
- if (pageComponentInfo != null)
+ PageComponentInfo parsed = PageComponentInfo.parse(queryParameter.getName());
+ if (parsed != null)
{
- return pageComponentInfo;
+ info = parsed;
+ break;
}
}
}
+
+ if (info != null)
+ {
+ QueryParameter override = url.getQueryParameter(WebRequest.PARAM_PAGE_ID_OVERRIDE);
+ if (override != null)
+ {
+ Integer pageId = StringValue.valueOf(override.getValue()).toOptionalInteger();
+ info.getPageInfo().setPageId(pageId);
+ }
+ }
+
+ return info;
+
}
- return null;
}
/**
* Encodes the {@link PageComponentInfo} instance as the first query string parameter to the
* URL.
- *
+ *
* @param url
* @param info
*/
@@ -128,7 +146,7 @@ public abstract class AbstractComponentMapper extends AbstractMapper implements
/**
* Loads page class with given name.
- *
+ *
* @param name
* @return class
*/
@@ -141,7 +159,7 @@ public abstract class AbstractComponentMapper extends AbstractMapper implements
/**
* {@inheritDoc}
- *
+ *
* Removes the first query parameter only if {@link PageComponentInfo#parse(String)} returns
* non-null instance
*/
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/WebPage.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/WebPage.java
index d1aeea2..5da21a3 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/WebPage.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/WebPage.java
@@ -67,10 +67,17 @@ public class WebPage extends Page
private static final long serialVersionUID = 1L;
/**
+ * Indicates whether or not an ajax-only version of this page exists. Upon first ajax request
+ * that dirties the page we increment the version so that non-ajax components have a consistent
+ * version to work off. See {@link #dirty(boolean)}
+ */
+ private static final int FLAG_AJAX_VERSION_EXISTS = FLAG_RESERVED1;
+
+ /**
* Constructor.
@@ -316,10 +323,23 @@ public class WebPage extends Page
public final void dirty(boolean isInitialization)
{
Request request = getRequest();
- if (isInitialization == false && request instanceof WebRequest &&
- ((WebRequest)request).isAjax())
+ if (isInitialization == false)
{
- return;
+ if (request instanceof WebRequest)
+ {
+ WebRequest webreq = (WebRequest)request;
+ if (webreq.isAjax())
+ {
+ if (getFlag(FLAG_AJAX_VERSION_EXISTS))
+ {
+ // an ajax-safe version of this page alerady exists, no further versioning
+ // is needed during other ajax requests
+ return;
+ }
+ setFlag(FLAG_AJAX_VERSION_EXISTS, true);
+ }
+
+ }
}
super.dirty(isInitialization);
}
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/http/WebRequest.java b/wicket-request/src/main/java/org/apache/wicket/request/http/WebRequest.java
index 03f984b..e64b96e 100644
--- a/wicket-request/src/main/java/org/apache/wicket/request/http/WebRequest.java
+++ b/wicket-request/src/main/java/org/apache/wicket/request/http/WebRequest.java
@@ -40,6 +40,13 @@ public abstract class WebRequest extends Request
public static final String PARAM_AJAX = "wicket-ajax";
/** marker for Ajax requests */
public static final String HEADER_AJAX = "Wicket-Ajax";
+
+ /**
+ * page id override - specifies page id that should be used instead of the one encoded into
+ * listener interface url
+ */
+ public static final String PARAM_PAGE_ID_OVERRIDE = "wicket-page-id";
+
/** marker for Ajax-relative url */
public static final String PARAM_AJAX_BASE_URL = "wicket-ajax-baseurl";
/** marker for Ajax-relative url */
diff --git a/wicket-request/src/main/java/org/apache/wicket/request/mapper/info/PageInfo.java b/wicket-request/src/main/java/org/apache/wicket/request/mapper/info/PageInfo.java
index 89ab035..8cacc59 100644
--- a/wicket-request/src/main/java/org/apache/wicket/request/mapper/info/PageInfo.java
+++ b/wicket-request/src/main/java/org/apache/wicket/request/mapper/info/PageInfo.java
@@ -28,7 +28,7 @@ import org.apache.wicket.util.string.Strings;
*/
public class PageInfo
{
- private final Integer pageId;
+ private Integer pageId;
/**
* Construct.
@@ -49,6 +49,16 @@ public class PageInfo
}
/**
+ * Sets page id
+ *
+ * @param pageId
+ */
+ public void setPageId(Integer pageId)
+ {
+ this.pageId = pageId;
+ }
+
+ /**
* @return page id
*/
public Integer getPageId()
@poeriajafari
Copy link

poeriajafari commented Aug 22, 2016

Hi there,

I came on this page while looking for an answer why an AJAX Request sometimes uses a wrong ID for an page. I have an checkbox inside my page (inside an popup acctually) which also happens to be calling AJAX so during this the event handler will add it again to the target. Now what I saw was that in the requestCycle it has a copy of the page with one version of the checkBox id, which is prefixed with a specific integer because it's at DataRowView like I.E: Id=Row:2:checkBox. But the popup showing in the browser has actually a newer version of the ID. like Row:7:checkBox. Which ofcourse doesn't map and we get an WicketRunTime Exeption. I also saw the same problem happing in other AjaxComponents when clicking fast ona Ajax component for instance. But I cant really figure out how the page versioning happens and how to adept to this. We use Wicket 6.11. I saw that you gist is kind of related to this, am I right. Can you help me to get on the right track how to fix this? I am trying to read more about the pageIds and how they get stored and read also within an AJAX request. I guess this is my bug at the moment. Can you please hint en tell me what this GIST is acctually about?

By the way I also tried setting the setOutputMarkupPlaceHolder on true instead just setOutMarkupID. Thought that would fix it by always outputting the id as placeholder. But that definitely didn't work! Hope this will also help others with this kind of problem

@poeriajafari
Copy link

Would it help using a AjaxCheckBox instead of an normal checkBox just saw that we use an normal checkBox while adding an AjaxFormSubmitBehavior to the normal checkbox?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment