Wow, you're fast :P

Sven


Am 07.12.2017 um 09:29 schrieb Maxim Solodovnik:
Hello Sven,

Is this correct import?
import com.google.common.base.Supplier;

On Thu, Dec 7, 2017 at 3:24 PM,  <svenme...@apache.org> wrote:
Repository: wicket
Updated Branches:
   refs/heads/sandbox/component-renderer [created] 6e6c273fd


render independently from web or tester


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/6e6c273f
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/6e6c273f
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/6e6c273f

Branch: refs/heads/sandbox/component-renderer
Commit: 6e6c273fd32325a447cc32c751d5ce0c083e7ed1
Parents: 693dad3
Author: Sven Meier <svenme...@apache.org>
Authored: Thu Dec 7 09:24:12 2017 +0100
Committer: Sven Meier <svenme...@apache.org>
Committed: Thu Dec 7 09:24:12 2017 +0100

----------------------------------------------------------------------
  .../core/util/string/ComponentRenderer.java     | 324 ++++++++++++++++++-
  .../ComponentRendererInstanceTest.java          |  52 +++
  2 files changed, 369 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/6e6c273f/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
 
b/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
index 0cf63bf..e971bc2 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/core/util/string/ComponentRenderer.java
@@ -16,35 +16,341 @@
   */
  package org.apache.wicket.core.util.string;

+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
  import org.apache.wicket.Application;
  import org.apache.wicket.Component;
  import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.Page;
+import org.apache.wicket.RuntimeConfigurationType;
+import org.apache.wicket.Session;
  import org.apache.wicket.ThreadContext;
  import org.apache.wicket.core.request.handler.PageProvider;
  import org.apache.wicket.markup.IMarkupCacheKeyProvider;
  import org.apache.wicket.markup.IMarkupResourceStreamProvider;
  import org.apache.wicket.markup.MarkupNotFoundException;
  import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.mock.MockApplication;
+import org.apache.wicket.mock.MockWebRequest;
  import org.apache.wicket.protocol.http.BufferedWebResponse;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.protocol.http.mock.MockServletContext;
+import org.apache.wicket.request.Request;
  import org.apache.wicket.request.Response;
+import org.apache.wicket.request.Url;
  import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.WebRequest;
+import org.apache.wicket.serialize.ISerializer;
+import org.apache.wicket.session.ISessionStore;
  import org.apache.wicket.util.resource.IResourceStream;
  import org.apache.wicket.util.resource.StringResourceStream;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

+import com.google.common.base.Supplier;
+
  /**
   * A helper class for rendering components and pages.
- *
- * <p><strong>Note</strong>: {@link #renderComponent(Component)} does 
<strong>not</strong>
- * support rendering {@link org.apache.wicket.markup.html.panel.Fragment} 
instances!</p>
+ * <p>
+ * With the static methods of this class components and pages can be rendered
+ * on a thread already processing an {@link Application}.
+ * <p>
+ * If you want to render independently from any web request processing (e.g. 
generating an email
+ * body on a worker thread), you can create an instance of this class.<br/>
+ * You may use an existing application, create a fresh one or just use the 
defaults of
+ * {@link #ComponentRenderer()} for a mocked application with sensible 
defaults.
+ * <p>
+ * Note: For performance instances can and should be reused, be sure to call 
{@link #destroy()}
+ * when they are no longer needed.
   */
  public class ComponentRenderer
  {
         private static final Logger LOGGER = 
LoggerFactory.getLogger(ComponentRenderer.class);

+       private WebApplication application;
+
+       /**
+        * A renderer using a default mocked application, which
+        * <ul>
+        * <li>never shares anything in a session</li>
+        * <li>never serializes anything</li>
+        * </ul>
+        */
+       public ComponentRenderer()
+       {
+               this(new MockApplication()
+               {
+                       @Override
+                       public RuntimeConfigurationType getConfigurationType()
+                       {
+                               return RuntimeConfigurationType.DEPLOYMENT;
+                       }
+
+                       @Override
+                       protected void init()
+                       {
+                               super.init();
+
+                               setSessionStoreProvider(() -> new 
NeverSessionStore());
+                               getFrameworkSettings().setSerializer(new 
NeverSerializer());
+                       }
+               });
+       }
+
+       /**
+        * A renderer using the given application.
+        * <p>
+        * If the application was not yet initialized - e.g. it is not reused 
from an already running web
+        * container - it will be initialized.
+        */
+       public ComponentRenderer(WebApplication application)
+       {
+               this.application = application;
+
+               if (application.getName() == null) {
+                       // not yet initialized
+
+                       inThreadContext(new Runnable()
+                       {
+                               @Override
+                               public void run()
+                               {
+                                       application.setServletContext(new 
MockServletContext(application, null));
+                                       application.setName("ComponentRenderer[" + 
System.identityHashCode(ComponentRenderer.this) + "]");
+                                       application.initApplication();
+                               }
+                       });
+               }
+       }
+
+       /**
+        * Destroy this renderer.
+        */
+       public void destroy()
+       {
+               inThreadContext(new Runnable()
+               {
+                       @Override
+                       public void run()
+                       {
+                               application.internalDestroy();
+                       }
+               });
+       }
+
+       /**
+        *
+        * Collects the html generated by the rendering a component.
+        *
+        * @param component
+        *            supplier of the component
+        * @return the html rendered by the panel
+        */
+       public CharSequence renderComponent(final Supplier<Component> component)
+       {
+               return renderPage(new Supplier<Page>()
+               {
+                       @Override
+                       public Page get()
+                       {
+                               return new RenderPage(component.get());
+                       }
+               });
+       }
+
+       /**
+        * Collects the html generated by the rendered a component.
+        *
+        * @param page
+        *            supplier of the page
+        * @return the html rendered by the panel
+        */
+       public CharSequence renderPage(final Supplier<? extends Page> page)
+       {
+               return inThreadContext(new Supplier<CharSequence>()
+               {
+                       @Override
+                       public CharSequence get()
+                       {
+                               WebRequest request = newWebRequest();
+
+                               BufferedWebResponse response = new 
BufferedWebResponse(null);
+
+                               RequestCycle cycle = 
application.createRequestCycle(request, response);
+
+                               ThreadContext.setRequestCycle(cycle);
+
+                               page.get().renderPage();
+
+                               return response.getText();
+                       }
+               });
+       }
+
+       /**
+        * Run the given runnable inside a valid {@link ThreadContext}.
+        *
+        * @param runnable
+        *            runnable
+        */
+       private void inThreadContext(Runnable runnable) {
+               inThreadContext(() -> {
+                       runnable.run();
+                       return null;
+               });
+       }
+
+       /**
+        * Get the result from the given supplier inside a valid {@link 
ThreadContext}.
+        *
+        * @param supplier
+        *            supplier
+        * @return result of {@link Supplier#get()}
+        */
+       private <T> T inThreadContext(Supplier<T> supplier)
+       {
+               ThreadContext oldContext = ThreadContext.detach();
+
+               try
+               {
+                       ThreadContext.setApplication(application);
+
+                       return supplier.get();
+               }
+               finally
+               {
+
+                       ThreadContext.restore(oldContext);
+               }
+       }
+
+       /**
+        * Create a new request, by default a {@link MockWebRequest}.
+        */
+       protected WebRequest newWebRequest()
+       {
+               return new MockWebRequest(Url.parse("/"));
+       }
+
+       /**
+        * Never serialize.
+        */
+       private static final class NeverSerializer implements ISerializer
+       {
+               @Override
+               public byte[] serialize(Object object)
+               {
+                       return null;
+               }
+
+               @Override
+               public Object deserialize(byte[] data)
+               {
+                       return null;
+               }
+       }
+
+       /**
+        * Never share anything.
+        */
+       private static class NeverSessionStore implements ISessionStore
+       {
+
+               @Override
+               public Serializable getAttribute(Request request, String name)
+               {
+                       return null;
+               }
+
+               @Override
+               public List<String> getAttributeNames(Request request)
+               {
+                       return null;
+               }
+
+               @Override
+               public void setAttribute(Request request, String name, 
Serializable value)
+               {
+               }
+
+               @Override
+               public void removeAttribute(Request request, String name)
+               {
+               }
+
+               @Override
+               public void invalidate(Request request)
+               {
+               }
+
+               @Override
+               public String getSessionId(Request request, boolean create)
+               {
+                       return null;
+               }
+
+               @Override
+               public Session lookup(Request request)
+               {
+                       return null;
+               }
+
+               @Override
+               public void bind(Request request, Session newSession)
+               {
+               }
+
+               @Override
+               public void flushSession(Request request, Session session)
+               {
+               }
+
+               @Override
+               public void destroy()
+               {
+               }
+
+               @Override
+               public void registerUnboundListener(UnboundListener listener)
+               {
+               }
+
+               @Override
+               public void unregisterUnboundListener(UnboundListener listener)
+               {
+               }
+
+               @Override
+               public Set<UnboundListener> getUnboundListener()
+               {
+                       return null;
+               }
+
+               @Override
+               public void registerBindListener(BindListener listener)
+               {
+               }
+
+               @Override
+               public void unregisterBindListener(BindListener listener)
+               {
+               }
+
+
+               @Override
+
+               public Set<BindListener> getBindListeners()
+               {
+                       return null;
+               }
+       }
+
         /**
          * Collects the html generated by the rendering of a page.
+        * <p>
+        * Important note: Must be called on a thread already processing a 
{@link WebApplication}!
          *
          * @param pageProvider
          *            the provider of the page class/instance and its 
parameters
@@ -75,12 +381,16 @@ public class ComponentRenderer

         /**
          * Collects the html generated by the rendering of a component.
-        *
          * <p>
-        * NOTE: this method is meant to render fresh component instances that 
are disposed after the
+        * Important notes:
+        * <ul>
+        * <li>this method is meant to render fresh component instances that 
are disposed after the
          * html has been generate. To avoid unwanted side effects do not use 
it with components that
-        * are from an existing hierarchy.
-        * </p>
+        * are from an existing hierarchy.</li>
+        * <li>does <strong>not</strong> support rendering
+        * {@link org.apache.wicket.markup.html.panel.Fragment} instances</li>
+        * <li>must be called on a thread already processing a {@link 
WebApplication}!</li>
+        * </ul>
          *
          * @param component
          *            the component to render.

http://git-wip-us.apache.org/repos/asf/wicket/blob/6e6c273f/wicket-core/src/test/java/org/apache/wicket/core/util/string/componentrenderer/ComponentRendererInstanceTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/core/util/string/componentrenderer/ComponentRendererInstanceTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/core/util/string/componentrenderer/ComponentRendererInstanceTest.java
new file mode 100644
index 0000000..4aa6dfa
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/core/util/string/componentrenderer/ComponentRendererInstanceTest.java
@@ -0,0 +1,52 @@
+/*
+/*
+ * 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.wicket.core.util.string.componentrenderer;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.wicket.core.util.string.ComponentRenderer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for {@link ComponentRenderer}
+ */
+public class ComponentRendererInstanceTest
+{
+       private ComponentRenderer renderer;
+
+       @Before
+       public void setup() {
+               renderer = new ComponentRenderer();
+       }
+
+       @After
+       public void destroy() {
+               renderer.destroy();
+       }
+
+       @Test
+       public void render()
+       {
+               CharSequence html = renderer.renderComponent(() -> new Label("id", 
"Hello renderer"));
+
+               assertEquals("Hello renderer", html.toString());
+       }
+}
\ No newline at end of file




Reply via email to