WICKET-4487 TextTemplate in RenderHead() on component doesn't Re-Render for every page
Make TextTemplateResourceReference more dynamic by: - re-interpolating the template with the latest state of the variables model - re-registering the resource reference by key Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/78d39365 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/78d39365 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/78d39365 Branch: refs/heads/sandbox/atmosphere Commit: 78d39365726790a42087ed0d77c917fb93f0082f Parents: 925cae5 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Tue Apr 10 14:43:10 2012 +0300 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Tue Apr 10 14:47:11 2012 +0300 ---------------------------------------------------------------------- .../wicket/request/resource/AbstractResource.java | 2 +- .../wicket/request/resource/ResourceReference.java | 2 +- .../request/resource/ResourceStreamResource.java | 46 ++++++++---- .../resource/TextTemplateResourceReference.java | 55 ++++++++------- .../TextTemplateResourceReferenceTest.java | 16 ++++- .../wicket/util/resource/StringResourceStream.java | 5 +- 6 files changed, 76 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java index d0f58b1..2033a72 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java @@ -301,7 +301,7 @@ public abstract class AbstractResource implements IResource WebRequest request = (WebRequest)attributes.getRequest(); Time ifModifiedSince = request.getIfModifiedSinceHeader(); - if (ifModifiedSince != null && lastModified != null) + if (cacheDuration != Duration.NONE && ifModifiedSince != null && lastModified != null) { // [Last-Modified] headers have a maximum precision of one second // so we have to truncate the milliseconds part for a proper compare. http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java index 04521a8..b936115 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java @@ -110,7 +110,7 @@ public abstract class ResourceReference implements IClusterable * ResourceReferenceRegistry to make up the key under which the resource reference gets * stored. */ - public Key getKey() + public final Key getKey() { return data; } http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceStreamResource.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceStreamResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceStreamResource.java index 53dd6cd..08b8a8e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceStreamResource.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceStreamResource.java @@ -22,8 +22,8 @@ import java.io.InputStream; import javax.servlet.http.HttpServletResponse; import org.apache.wicket.Application; -import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.lang.Bytes; +import org.apache.wicket.util.lang.Checks; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.core.util.resource.IResourceStreamWriter; import org.apache.wicket.util.resource.ResourceStreamNotFoundException; @@ -42,7 +42,7 @@ public class ResourceStreamResource extends AbstractResource private static final Logger logger = LoggerFactory.getLogger(ResourceStreamResource.class); - private final IResourceStream stream; + private IResourceStream stream; private String fileName; private ContentDisposition contentDisposition = ContentDisposition.INLINE; private String textEncoding; @@ -56,7 +56,6 @@ public class ResourceStreamResource extends AbstractResource */ public ResourceStreamResource(IResourceStream stream) { - Args.notNull(stream, "stream"); this.stream = stream; } @@ -109,16 +108,38 @@ public class ResourceStreamResource extends AbstractResource return this; } + /** + * Lazy or dynamic initialization of the wrapped IResourceStream(Writer) + * @return the underlying IResourceStream + */ + protected IResourceStream getResourceStream() + { + return stream; + } + + private IResourceStream internalGetResourceStream() + { + final IResourceStream resourceStream = getResourceStream(); + Checks.notNull(resourceStream, "%s#getResourceStream() should not return null!", ResourceStreamResource.class.getName()); + return resourceStream; + } + @Override protected ResourceResponse newResourceResponse(Attributes attributes) { + final IResourceStream resourceStream = internalGetResourceStream(); ResourceResponse data = new ResourceResponse(); - Time lastModifiedTime = stream.lastModifiedTime(); + Time lastModifiedTime = resourceStream.lastModifiedTime(); if (lastModifiedTime != null) { data.setLastModified(lastModifiedTime); } + if (cacheDuration != null) + { + data.setCacheDuration(cacheDuration); + } + // performance check; don't bother to do anything if the resource is still cached by client if (data.dataNeedsToBeWritten(attributes)) { @@ -127,7 +148,7 @@ public class ResourceStreamResource extends AbstractResource { try { - inputStream = stream.getInputStream(); + inputStream = resourceStream.getInputStream(); } catch (ResourceStreamNotFoundException e) { @@ -137,14 +158,14 @@ public class ResourceStreamResource extends AbstractResource } data.setContentDisposition(contentDisposition); - Bytes length = stream.length(); + Bytes length = resourceStream.length(); if (length != null) { data.setContentLength(length.bytes()); } data.setFileName(fileName); - String contentType = stream.getContentType(); + String contentType = resourceStream.getContentType(); if (contentType == null && fileName != null && Application.exists()) { contentType = Application.get().getMimeType(fileName); @@ -152,19 +173,14 @@ public class ResourceStreamResource extends AbstractResource data.setContentType(contentType); data.setTextEncoding(textEncoding); - if (cacheDuration != null) - { - data.setCacheDuration(cacheDuration); - } - - if (stream instanceof IResourceStreamWriter) + if (resourceStream instanceof IResourceStreamWriter) { data.setWriteCallback(new WriteCallback() { @Override public void writeData(Attributes attributes) { - ((IResourceStreamWriter)stream).write(attributes.getResponse()); + ((IResourceStreamWriter)resourceStream).write(attributes.getResponse()); close(); } }); @@ -197,7 +213,7 @@ public class ResourceStreamResource extends AbstractResource { try { - stream.close(); + internalGetResourceStream().close(); } catch (IOException e) { http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-core/src/main/java/org/apache/wicket/resource/TextTemplateResourceReference.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/resource/TextTemplateResourceReference.java b/wicket-core/src/main/java/org/apache/wicket/resource/TextTemplateResourceReference.java index 8bb050e..dbaa81a 100644 --- a/wicket-core/src/main/java/org/apache/wicket/resource/TextTemplateResourceReference.java +++ b/wicket-core/src/main/java/org/apache/wicket/resource/TextTemplateResourceReference.java @@ -23,11 +23,15 @@ import org.apache.wicket.Application; import org.apache.wicket.model.IModel; import org.apache.wicket.request.resource.IResource; import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.request.resource.ResourceReferenceRegistry; import org.apache.wicket.request.resource.ResourceStreamResource; import org.apache.wicket.util.io.IClusterable; +import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.StringResourceStream; import org.apache.wicket.util.template.PackageTextTemplate; import org.apache.wicket.util.template.TextTemplate; +import org.apache.wicket.util.time.Duration; +import org.apache.wicket.util.time.Time; /** * A class which adapts a {@link PackageTextTemplate} to a {@link ResourceReference}. @@ -38,18 +42,12 @@ import org.apache.wicket.util.template.TextTemplate; */ public class TextTemplateResourceReference extends ResourceReference implements IClusterable { -// ********************************************************************************************************************** -// Fields -// ********************************************************************************************************************** private static final long serialVersionUID = 1L; + private final TextTemplate textTemplate; private final IModel<Map<String, Object>> variablesModel; - private IResource resource; - -// ********************************************************************************************************************** -// Constructors -// ********************************************************************************************************************** + private final ResourceStreamResource resource; /** * Creates a resource reference to a {@link PackageTextTemplate}. @@ -142,16 +140,34 @@ public class TextTemplateResourceReference extends ResourceReference implements textTemplate = new PackageTextTemplate(scope, fileName, contentType, encoding); this.variablesModel = variablesModel; + resource = new ResourceStreamResource(null) + { + @Override + protected IResourceStream getResourceStream() + { + IModel<Map<String, Object>> variables = TextTemplateResourceReference.this.variablesModel; + String stringValue = textTemplate.asString(variables.getObject()); + variables.detach(); // We're done with the model so detach it! + + StringResourceStream resourceStream = new StringResourceStream(stringValue, + textTemplate.getContentType()); + resourceStream.setLastModified(Time.now()); + + return resourceStream; + } + }; + resource.setCacheDuration(Duration.NONE); + if (Application.exists()) { - Application.get().getResourceReferenceRegistry().registerResourceReference(this); + // TextTemplateResourceReference should not be cached due to its dynamic nature + // Old entry in the registry would keep wrong 'variablesModel' + ResourceReferenceRegistry resourceReferenceRegistry = Application.get().getResourceReferenceRegistry(); + resourceReferenceRegistry.unregisterResourceReference(getKey()); + resourceReferenceRegistry.registerResourceReference(this); } } -// ********************************************************************************************************************** -// Other Methods -// ********************************************************************************************************************** - /** * Creates a new resource which returns the interpolated value of the text template. * @@ -160,19 +176,6 @@ public class TextTemplateResourceReference extends ResourceReference implements @Override public IResource getResource() { - if (resource != null) - { - return resource; - } - - String stringValue = textTemplate.asString(variablesModel.getObject()); - variablesModel.detach(); // We're done with the model so detach it! - - StringResourceStream resourceStream = new StringResourceStream(stringValue, - textTemplate.getContentType()); - resourceStream.setLastModified(textTemplate.lastModifiedTime()); - - resource = new ResourceStreamResource(resourceStream); return resource; } } http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-core/src/test/java/org/apache/wicket/resource/TextTemplateResourceReferenceTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/resource/TextTemplateResourceReferenceTest.java b/wicket-core/src/test/java/org/apache/wicket/resource/TextTemplateResourceReferenceTest.java index 4520c8f..e16450b 100644 --- a/wicket-core/src/test/java/org/apache/wicket/resource/TextTemplateResourceReferenceTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/resource/TextTemplateResourceReferenceTest.java @@ -41,6 +41,8 @@ public class TextTemplateResourceReferenceTest extends WicketTestCase private static final String TEMPLATE_NAME = "textTemplateResRef.tmpl"; private static final String EXPECTED_VALUE = "value"; + private static final String SECOND_EXPECTED_VALUE = "second-value"; + private static final String VARIABLE_NAME = "variable"; /** * https://issues.apache.org/jira/browse/WICKET-3971 @@ -50,13 +52,20 @@ public class TextTemplateResourceReferenceTest extends WicketTestCase { // the page will render just <script> element with url to the template // this will register it in the application's ResourceReferenceRegistry - Page page = tester.startPage(new TemplateResourceReferencePage()); + TemplateResourceReferencePage page = new TemplateResourceReferencePage(); + tester.startPage(page); // make a separate request to the template resource CharSequence urlForTemplate = page.urlFor(new PackageResourceReference( TextTemplateResourceReferenceTest.class, TEMPLATE_NAME), null); tester.executeUrl(urlForTemplate.toString()); tester.assertContains("TMPL_START\\|" + EXPECTED_VALUE + "\\|TMPL_END"); + + // update the model and re-render (WICKET-4487) + page.variables.put(VARIABLE_NAME, SECOND_EXPECTED_VALUE); + tester.executeUrl(urlForTemplate.toString()); + tester.assertContains("TMPL_START\\|"+SECOND_EXPECTED_VALUE+"\\|TMPL_END"); + } private static class TemplateResourceReferencePage extends WebPage @@ -65,13 +74,14 @@ public class TextTemplateResourceReferenceTest extends WicketTestCase { private static final long serialVersionUID = 1L; + private final Map<String, Object> variables = new HashMap<String, Object>(); + @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); - Map<String, Object> variables = new HashMap<String, Object>(); - variables.put("variable", EXPECTED_VALUE); + variables.put(VARIABLE_NAME, EXPECTED_VALUE); final TextTemplateResourceReference reference = new TextTemplateResourceReference( TextTemplateResourceReferenceTest.class, TEMPLATE_NAME, Model.ofMap(variables)); http://git-wip-us.apache.org/repos/asf/wicket/blob/78d39365/wicket-util/src/main/java/org/apache/wicket/util/resource/StringResourceStream.java ---------------------------------------------------------------------- diff --git a/wicket-util/src/main/java/org/apache/wicket/util/resource/StringResourceStream.java b/wicket-util/src/main/java/org/apache/wicket/util/resource/StringResourceStream.java index a7d12ed..c8720ea 100644 --- a/wicket-util/src/main/java/org/apache/wicket/util/resource/StringResourceStream.java +++ b/wicket-util/src/main/java/org/apache/wicket/util/resource/StringResourceStream.java @@ -39,7 +39,7 @@ public final class StringResourceStream extends AbstractStringResourceStream */ public StringResourceStream(final CharSequence string) { - this.string = string; + this(string, null); } /** @@ -74,9 +74,6 @@ public final class StringResourceStream extends AbstractStringResourceStream return string.toString(); } - /** - * @see org.apache.wicket.util.resource.AbstractResourceStream#asString() - */ @Override public String asString() {
