Author: buildbot
Date: Sun Jan  9 21:20:56 2022
New Revision: 1077937

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    
websites/production/tapestry/content/rest-support-page-is-work-in-progress.html

Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: 
websites/production/tapestry/content/rest-support-page-is-work-in-progress.html
==============================================================================
--- 
websites/production/tapestry/content/rest-support-page-is-work-in-progress.html 
(original)
+++ 
websites/production/tapestry/content/rest-support-page-is-work-in-progress.html 
Sun Jan  9 21:20:56 2022
@@ -106,7 +106,90 @@ Object save(@RequestBody User user) {
 Object save(Long id, @RequestBody User user) {
        (...)
 }</code></pre>
-</div></div><p>The following types are supported 
out-of-the-box:</p><ul><li><code>String</code></li><li><code>Reader</code></li><li><code>InputStream</code></li><li>Primitive
 types and their wrapper types</li></ul><p>The actual conversion logic is 
implemented in the <code>HttpRequestBodyConverter</code> service, which is 
defined is an ordered configuration of <code>HttpRequestBodyConverter</code> 
instances. The service calls all contributed instances until one of them 
returns a non-null value. If none of them returns a non-null value, it falls 
back to trying to find a coercion, direct or indirect, from 
<code>HttpServletRequest</code> to the desired type.&#160;</p><p></p></div>
+</div></div><p>The following types are supported 
out-of-the-box:</p><ul><li><code>String</code></li><li><code>Reader</code></li><li><code>InputStream</code></li><li><code>JSONObject</code></li><li><code>JSONArray</code></li><li>Primitive
 types and their wrapper types</li></ul><p>The actual conversion logic is 
implemented in the <code>HttpRequestBodyConverter</code> service, which is 
defined is an ordered configuration of <code>HttpRequestBodyConverter</code> 
instances. The service calls all contributed instances until one of them 
returns a non-null value. If none of them returns a non-null value, it falls 
back to trying to find a coercion, direct or indirect, from 
<code>HttpServletRequest</code> to the desired type.&#160;</p><p>Here's one 
example of implementing an new <code>HttpRequestBodyConverter</code> then the 
code added to <code>AppModule</code> or any other Tapestry-IoC module class to 
have it used by <code>@RequestBody</code>:</p><div class="code panel pdl" 
style="border-wid
 th: 1px;"><div class="codeContent panelContent pdl">
+<pre><code class="language-java">/**
+ * Converts the body of HTTP requests to {@link User} instances. It delegates 
this task
+ * to {@link UserService#toObject(String)}.
+ */
+public class UserHttpRequestBodyConverter implements HttpRequestBodyConverter {
+    
+    private final UserService userService;
+
+    public UserHttpRequestBodyConverter(UserService userService) {
+        super();
+        this.userService = userService;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public &lt;T&gt; T convert(HttpServletRequest request, Class&lt;T&gt; 
type) {
+        T value = null;
+        // Check whether this converter handles the given type
+        if (User.class.equals(type)) {
+                       // Actual conversion logic
+            try {
+                value = (T) 
userService.toObject(IOUtils.toString(request.getReader()));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+ &#160; &#160; &#160; &#160;}
+        return value;
+    }
+
+}</code></pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>UserHttpRequestBodyConverter contribution</b></div><div 
class="codeContent panelContent pdl">
+<pre><code class="language-java">    public static void 
contributeHttpRequestBodyConverter(
+            OrderedConfiguration&lt;HttpRequestBodyConverter&gt; 
configuration) {
+        
+        configuration.addInstance("User", UserHttpRequestBodyConverter.class); 
// automatic instantiation and dependency injection
+               // or configuration.add("User", new 
UserHttpRequestBodyConverter(...));
+    }</code></pre>
+</div></div><h2 
id="RESTSupport(pageisworkinprogress)-AnsweringRESTrequests">Answering REST 
requests</h2><p>Just like any other Tapestry event handler method, the returned 
value defines what gets to be sent to the user agent making the request. This 
logic is written in <code>ComponentEventResultProcessor</code> implementations, 
usually but not necessarily one per return type/class, which are contributed to 
the <code>ComponentEventResultProcessor</code> service. These implementations 
can also set additional HTTP headers and set the HTTP status code.</p><p>REST 
requests responses usually fall into 2 types: ones just returning HTTP status 
and and headers (for example, <code>HEAD</code> and <code>DELETE</code> 
requests) and ones returning that and also content (for example, 
<code>GET</code>, sometimes other methods too).</p><h3 
id="RESTSupport(pageisworkinprogress)-Contentresponses">Content 
responses</h3><p>For content responses, Tapestry has out-of-the-box support for 
<code>StreamRespo
 nse</code> (mostly binary content),&#160; <code>TextStreamResponse</code> 
(simple text content), <code>JSONArray</code> (since Tapestry 5.8.0) and 
<code>JSONObject</code> (since 5.8.0).&#160; Here's one example for adding 
support for a class, <code>User</code>, converting it to the JSON 
format:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
+<pre><code class="language-java">/**
+ * Handles {@link User} instances when they're returned by event handler 
methods.
+ * Heavily inspired by {@link JSONCollectionEventResultProcessor} from 
Tapestry itself.
+ */
+final public class UserComponentEventResultProcessor 
+        implements ComponentEventResultProcessor&lt;User&gt; {
+
+    private final Response response;
+
+    private final ContentType contentType;
+    
+    private final UserService userService;
+
+    public UserComponentEventResultProcessor(Response response,
+            @Symbol(TapestryHttpSymbolConstants.CHARSET) String outputEncoding,
+            UserService userService)    {
+        this.response = response;
+        this.userService = userService;
+        contentType = new 
ContentType(InternalConstants.JSON_MIME_TYPE).withCharset(outputEncoding);
+    }
+
+    public void processResultValue(User user) throws IOException
+    {
+        PrintWriter pw = response.getPrintWriter(contentType.toString());
+        pw.write(userService.toJsonString(user));
+        pw.close();
+               // You could also set extra HTTP headers or the status code here
+    }        
+}</code></pre>
+</div></div><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeHeader panelHeader pdl" style="border-bottom-width: 
1px;"><b>UserComponentEventResultProcessor contribution</b></div><div 
class="codeContent panelContent pdl">
+<pre><code class="language-java">    public void 
contributeComponentEventResultProcessor(
+            MappedConfiguration&lt;Class, ComponentEventResultProcessor&gt; 
configuration) {
+        configuration.addInstance(User.class, 
UserComponentEventResultProcessor.class);
+    }</code></pre>
+</div></div><h3 class="auto-cursor-target" 
id="RESTSupport(pageisworkinprogress)-Non-contentresponses">Non-content 
responses</h3><p>For responses without content, just HTTP status and headers, 
and also for simple String responses, Tapestry 5.8.0 introduced the 
<code>HttpStatus</code> class. You can create instances of it by either using 
its utility static methods that match HTTP status names like <code>ok()</code>, 
<code>created()</code>, <code>accepted()</code>,&#160;<code>notFound()</code> 
and <code>forbidden() </code>or using one of its constructors. In both cases, 
you can customize the response further by using a fluent interface with methods 
for header-specific methods like <code>withLocation(url)</code> and 
<code>withContentLocation(url)</code> or the generic 
<code>withHttpHeader(String name, String value)</code>. Check the 
<code>HttpStatus</code> JavaDoc for the full list of methods.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelConten
 t pdl">
+<pre><code class="language-java">    @OnEvent(EventConstants.HTTP_PUT) 
+    Object save(@RequestBody User user) {
+        userService.save(user);
+        return HttpStatus.created()
+                .withContentLocation("Some URL")
+                .withHttpHeader("X-Something", "X-Value");
+    }
+
+</code></pre>
+</div></div><p></p></div>
             </div>
             <!-- /// Content End -->
           </div>


Reply via email to