tag:blogger.com,1999:blog-27595481450504165172024-03-19T06:41:10.136+01:00Yet Another TEch bLog"Everything there is to know about the shrimpin' business."Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-2759548145050416517.post-63051626691139602292017-11-12T16:28:00.000+01:002017-11-12T16:28:17.217+01:00Blog moved to blog.kramolis.czI've moved the blog site to Github pages (<a href="https://github.com/shamoh/pages-blog">https://github.com/shamoh/pages-blog</a>) available on a new web site <a href="http://blog.kramolis.cz/"><b>http://blog.kramolis.cz/</b></a>.Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com2tag:blogger.com,1999:blog-2759548145050416517.post-24584386546585215322016-05-06T22:51:00.000+02:002016-05-06T23:04:08.173+02:00Custom Restito Sequenced Stub ActionIn this post I show how to write custom <a href="https://github.com/mkotsur/restito">Restito</a> <a href="https://mkotsur.github.io/restito/javadoc/current/com/xebialabs/restito/semantics/Action.html">Action</a> to mock a single REST endpoint to response differently even is subsequent requests are identical.<br />
<br />
<b>Restito</b> is lightweight testing framework that provides a Java DSL to:<br />
<ul>
<li>mimic REST server behavior,</li>
<li>perform verification against happened calls.</li>
</ul>
<div>
It is based on <a href="https://grizzly.java.net/">Grizzly HTTP Server</a>. See <a href="https://github.com/mkotsur/restito/blob/master/guide.md">developer's guide</a> for more details about all supported features.</div>
<div>
<br /></div>
<div>
Let's say I want to test business login of application that calls following REST API:</div>
<div>
<ol>
<li>Gets list of all open comments (<span style="font-family: "verdana" , sans-serif; font-size: x-small;">GET /comments</span>),</li>
<li>Archives each comment that is older than a month (<span style="font-family: "verdana" , sans-serif; font-size: x-small;">DELETE /comments/{id}</span>),</li>
<li>Lists all remaining open comments (<span style="font-family: "verdana" , sans-serif; font-size: x-small;">GET /comments</span>).</li>
</ol>
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.util.List</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.xebialabs.restito.builder.ensure.EnsureHttp</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.xebialabs.restito.support.junit.StartServer</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.junit.Before</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.junit.Rule</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.junit.Test</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">builder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">stub</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">StubHttp</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">whenHttp</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">semantics</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Action</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">contentType</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">semantics</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Action</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">status</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">semantics</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Action</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">stringContent</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">semantics</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Condition</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">delete</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">com</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">xebialabs</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">restito</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">semantics</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Condition</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">get</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">org</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">glassfish</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">grizzly</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">http</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">util</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">HttpStatus</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">NO_CONTENT_204</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">org</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">glassfish</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">grizzly</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">http</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">util</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">HttpStatus</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">OK_200</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">org</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">hamcrest</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Matchers</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">hasSize</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">static</span> <span style="color: #f8f8f2;">org</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">junit</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Assert</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">assertThat</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">MyAppTest</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">static</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">String</span> <span style="color: #f8f8f2;">GET_COMMENTS_BEFORE</span> <span style="color: #f92672;">=</span>
<span style="color: #e6db74;">"{\"comments\":[\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">" {\"id\" : 1, \"content\" : \"Happy New Year ...\", \"date\" : \"2016-01-01\"},\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">" {\"id\" : 2, \"content\" : \"Happy Valentine...\", \"date\" : \"2016-02-14\"},\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">" {\"id\" : 3, \"content\" : \"I like Restito ...\", \"date\" : \"2016-05-06\"}\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">"]}"</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">static</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">String</span> <span style="color: #f8f8f2;">GET_COMMENTS_AFTER</span> <span style="color: #f92672;">=</span>
<span style="color: #e6db74;">"{\"comments\":[\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">" {\"id\" : 3, \"content\" : \"I like Restito ...\", \"date\" : \"2016-05-06\"}\n"</span>
<span style="color: #f92672;">+</span> <span style="color: #e6db74;">"]}"</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@Rule</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">StartServer</span> <span style="color: #f8f8f2;">startServer</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">StartServer</span><span style="color: #f92672;">();</span>
<span style="color: #a6e22e;">@Test</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">testArchiveOldComments</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #75715e;">// 1. Stub for: Gets list of all open comments (GET /comments):</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">get</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">OK_200</span><span style="color: #f92672;">),</span>
<span style="color: #f8f8f2;">contentType</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/json"</span><span style="color: #f92672;">),</span>
<span style="color: #f8f8f2;">stringContent</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">GET_COMMENTS_BEFORE</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// 2. Stub for: Archives each comment that is older than a month (DELETE /comments/{id}):</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">delete</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments/1"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">NO_CONTENT_204</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">delete</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments/2"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">NO_CONTENT_204</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// 3. Stub for: Lists all remaining open comments (GET /comments):</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">get</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">OK_200</span><span style="color: #f92672;">),</span>
<span style="color: #f8f8f2;">contentType</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/json"</span><span style="color: #f92672;">),</span>
<span style="color: #f8f8f2;">stringContent</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">GET_COMMENTS_AFTER</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// call business logic</span>
<span style="color: #f8f8f2;">MyApp</span> <span style="color: #f8f8f2;">myApp</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">MyApp</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">List</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Comment</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">comments</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">myApp</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">archiveOldComments</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// remaining 1 comment:</span>
<span style="color: #f8f8f2;">assertThat</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">comments</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">hasSize</span><span style="color: #f92672;">(</span><span style="color: #ae81ff;">1</span><span style="color: #f92672;">));</span>
<span style="color: #75715e;">// ensure that each stubs has been invoked:</span>
<span style="color: #f8f8f2;">EnsureHttp</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">ensureHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span><span style="color: #a6e22e;">gotStubsCommitmentsDone</span><span style="color: #f92672;">();</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
</div>
<div>
<br /></div>
<div>
But this test fails because DELETE stubs are not invoked.</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">MyAppTest</span> <span style="color: #f92672;">></span> <span style="color: #f8f8f2;">testArchiveOldComments</span> <span style="color: #66d9ef;">FAILED</span>
<span style="color: #f8f8f2;">java.lang.AssertionError</span> <span style="color: #f8f8f2;">at</span> <span style="color: #f8f8f2;">MyAppTest.java:</span><span style="color: #ae81ff;">72</span>
<span style="color: #f8f8f2;">Expected</span> <span style="color: #f8f8f2;">stub</span> <span style="color: #f8f8f2;">com.xebialabs.restito.semantics.Stub@</span><span style="color: #ae81ff;">775449</span><span style="color: #f8f8f2;">c1</span> <span style="color: #f8f8f2;">to</span> <span style="color: #f8f8f2;">be</span> <span style="color: #f8f8f2;">called</span> <span style="color: #ae81ff;">1</span> <span style="color: #f8f8f2;">times,</span> <span style="color: #f8f8f2;">called</span> <span style="color: #ae81ff;">0</span> <span style="color: #f8f8f2;">times</span> <span style="color: #f8f8f2;">instead</span>
<span style="color: #f8f8f2;">java.lang.AssertionError:</span> <span style="color: #f8f8f2;">Expected</span> <span style="color: #f8f8f2;">stub</span> <span style="color: #f8f8f2;">com.xebialabs.restito.semantics.Stub@</span><span style="color: #ae81ff;">775449</span><span style="color: #f8f8f2;">c1</span> <span style="color: #f8f8f2;">to</span> <span style="color: #f8f8f2;">be</span> <span style="color: #f8f8f2;">called</span> <span style="color: #ae81ff;">1</span> <span style="color: #f8f8f2;">times,</span> <span style="color: #f8f8f2;">called</span> <span style="color: #ae81ff;">0</span> <span style="color: #f8f8f2;">times</span> <span style="color: #f8f8f2;">instead</span>
</pre>
</div>
<div>
<br /></div>
<div>
<i>Note</i>: You can see the error output is not comprehensive. It is known issue, see <a href="https://github.com/mkotsur/restito/issues/45">https://github.com/mkotsur/restito/issues/45</a>.</div>
<div>
<br /></div>
<div>
The reason why DELETE methods are not invoked is that the first GET call does not return JSON with 3 comments but just 1 (JSON in <span style="font-family: "verdana" , sans-serif; font-size: x-small;">GET_COMMENTS_AFTER</span> String). It means that the second <span style="font-family: "verdana" , sans-serif; font-size: x-small;">GET /comments</span> stub overrides the first one. Or, the first stub that returns JSON with 3 comments (<span style="font-family: "verdana" , sans-serif; font-size: x-small;">GET_COMMENTS_BEFORE</span> String) is ignored because the <span style="font-family: "verdana" , sans-serif; font-size: x-small;">match</span> <a href="https://mkotsur.github.io/restito/javadoc/current/com/xebialabs/restito/semantics/Condition.html">Conditions</a> for both stubs are identical.</div>
<div>
<br /></div>
<div>
Unfortunately Restito does not support directly this use case. Fortunately you can create <span style="font-family: "verdana" , sans-serif; font-size: x-small;">custom</span> <a href="https://mkotsur.github.io/restito/javadoc/current/com/xebialabs/restito/semantics/Action.html#custom-com.xebialabs.restito.semantics.Function-">Action</a> or <a href="https://mkotsur.github.io/restito/javadoc/current/com/xebialabs/restito/semantics/Condition.html#custom-com.xebialabs.restito.semantics.Predicate-">Condition</a>. Described use-case can be solved by custom Action.</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.util.LinkedList</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.util.Queue</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.xebialabs.restito.semantics.Action</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.xebialabs.restito.semantics.Function</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.glassfish.grizzly.http.server.Response</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">SequencedAction</span> <span style="color: #66d9ef;">implements</span> <span style="color: #f8f8f2;">Function</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Response</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Response</span><span style="color: #f92672;">></span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">private</span> <span style="color: #f8f8f2;">Queue</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Action</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">queue</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">LinkedList</span><span style="color: #f92672;"><>();</span>
<span style="color: #66d9ef;">public</span> <span style="color: #a6e22e;">SequencedAction</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Action</span><span style="color: #f92672;">...</span> <span style="color: #f8f8f2;">actions</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">for</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Action</span> <span style="color: #f8f8f2;">action</span> <span style="color: #f92672;">:</span> <span style="color: #f8f8f2;">actions</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">this</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">queue</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">offer</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">action</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Response</span> <span style="color: #a6e22e;">apply</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Response</span> <span style="color: #f8f8f2;">input</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">Action</span> <span style="color: #f8f8f2;">next</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">queue</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">poll</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">if</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">next</span> <span style="color: #f92672;">!=</span> <span style="color: #66d9ef;">null</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">input</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">next</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">apply</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">input</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">input</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<div>
<br /></div>
<div>
Custom <span style="font-family: "verdana" , sans-serif; font-size: x-small;"><b>SequencedAction</b></span> keeps a <span style="font-family: Verdana, sans-serif; font-size: x-small;">queue</span> of not yet processed Actions and polls just one available Action from the <span style="font-family: Verdana, sans-serif; font-size: x-small;">queue</span> in <span style="font-family: Verdana, sans-serif; font-size: x-small;">apply</span> method. I.e. subsequent <span style="font-family: "verdana" , sans-serif; font-size: x-small;">SequencedAction.apply</span> invocation behaves differently. If the <span style="font-family: Verdana, sans-serif; font-size: x-small;">queue</span> is empty the <span style="font-family: "verdana" , sans-serif; font-size: x-small;">SequencedAction.apply</span> does nothing like <a href="https://mkotsur.github.io/restito/javadoc/current/com/xebialabs/restito/semantics/Action.html#noop--">noop</a> action.</div>
<div>
<br /></div>
<div>
So now I can update test method to use custom action.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #a6e22e;">@Test</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">testArchiveOldComments</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #75715e;">// 1. Stub for both: Gets list of all open comments (GET /comments):</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">get</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">OK_200</span><span style="color: #f92672;">),</span>
<span style="color: #f8f8f2;">contentType</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/json"</span><span style="color: #f92672;">),</span>
<span style="color: #75715e;">// use custom action:</span>
<span style="color: #f8f8f2;">Action</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">custom</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">SequencedAction</span><span style="color: #f92672;">(</span>
<span style="color: #75715e;">// the first get: returns 3 comments</span>
<span style="color: #f8f8f2;">stringContent</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">GET_COMMENTS_BEFORE</span><span style="color: #f92672;">),</span>
<span style="color: #75715e;">// the second get: returns 1 comment</span>
<span style="color: #f8f8f2;">stringContent</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">GET_COMMENTS_AFTER</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">))).</span>
<span style="color: #75715e;">// 2 actions in sequence:</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">(</span><span style="color: #ae81ff;">2</span><span style="color: #f92672;">);</span>
<span style="color: #75715e;">// 2. Stub for: Archives each comment that is older than a month (DELETE /comments/{id}):</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">delete</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments/1"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">NO_CONTENT_204</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">whenHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span>
<span style="color: #f8f8f2;">match</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">delete</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/comments/2"</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">then</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">status</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">NO_CONTENT_204</span><span style="color: #f92672;">)).</span>
<span style="color: #f8f8f2;">mustHappen</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// call business logic</span>
<span style="color: #f8f8f2;">MyApp</span> <span style="color: #f8f8f2;">myApp</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">MyApp</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">List</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Comment</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">comments</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">myApp</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">archiveOldComments</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// remaining 1 comment:</span>
<span style="color: #f8f8f2;">assertThat</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">comments</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">hasSize</span><span style="color: #f92672;">(</span><span style="color: #ae81ff;">1</span><span style="color: #f92672;">));</span>
<span style="color: #75715e;">// ensure that each stubs has been invoked:</span>
<span style="color: #f8f8f2;">EnsureHttp</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">ensureHttp</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">startServer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getServer</span><span style="color: #f92672;">()).</span><span style="color: #a6e22e;">gotStubsCommitmentsDone</span><span style="color: #f92672;">();</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
And the test is fixed.<br />
<br />
You are right, it is a little bit too verbose to use custom action. So I have decided to contribute the sequenced action directly to Restito <span style="font-family: "verdana" , sans-serif; font-size: x-small;">Action</span>, method <span style="font-family: "verdana" , sans-serif; font-size: x-small;"><b>sequence</b></span>, see or comment or vote for my GitHub pull request: <a href="https://github.com/mkotsur/restito/pull/49">https://github.com/mkotsur/restito/pull/49</a>. 😇<br />
<br /></div>
<div>
Enjoy,<br />
Libor</div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com10tag:blogger.com,1999:blog-2759548145050416517.post-82379973733075197712016-03-27T01:01:00.000+01:002016-03-27T01:01:08.001+01:00How to run standalone Java EE MVC application<div id="markdown-preview">
This project demonstrates how to create <strong>standalone Java EE MVC
application</strong>.
<br />
<br />
<a href="https://mvc-spec.java.net/">MVC</a> is newly developed Java
EE <a href="https://jcp.org/en/jsr/detail?id=371">JSR 371:
Model-View-Controller (MVC 1.0) Specification</a>.
<br />
<blockquote>
The MVC API defines an action-oriented Web framework as an
alternative to the component-oriented JSF. In an action-oriented
framework, developers are responsible for all the controller logic
and are given full control of the URI space for their application. </blockquote>
<blockquote>
The MVC API is layered on top of <a href="https://jax-rs-spec.java.net/">JAX-RS</a>
over <a href="https://jcp.org/en/jsr/detail?id=315">Servlets</a> and
integrates with existing EE technologies like <a href="https://www.jcp.org/en/jsr/detail?id=365">CDI</a>
and <a href="https://jcp.org/en/jsr/detail?id=349">Bean Validation</a>.
</blockquote>
MVC spec is going to be part of next <b>Java EE</b> <b>8</b>. MVC reference implementation named <a href="https://ozark.java.net/"><b>Ozark</b></a> is hosted on java.net. MVC depends on Servlets, JAX-RS and CDI. I've chosen to use <a href="http://undertow.io/"><b>Undertow</b></a>, <a href="https://jersey.java.net/"><b>Jersey</b></a> and <a href="http://weld.cdi-spec.org/"><b>Weld</b></a>. And <a href="https://deltaspike.apache.org/"><b>DeltaSpike</b></a> as CDI extension library. Finally, <a href="https://gradle.org/">Gradle</a> to build and run the project.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">ext</span> <span style="color: #f92672;">{</span>
<span style="line-height: 125%;"> </span><span style="color: #f8f8f2; line-height: 125%;">undertowVersion</span><span style="line-height: 125%;"> </span><span style="color: #f92672; line-height: 125%;">=</span><span style="line-height: 125%;"> </span><span style="color: #e6db74; line-height: 125%;">'1.3.18.Final'</span></pre>
<pre style="line-height: 125%; margin: 0;"> <span style="color: #f8f8f2;">weldVersion</span> <span style="color: #f92672;">=</span> <span style="color: #e6db74;">'2.3.3.Final'</span>
<span style="color: #f8f8f2;">deltaspikeVersion</span> <span style="color: #f92672;">=</span> <span style="color: #e6db74;">'1.5.4'</span>
<span style="color: #f8f8f2;">jerseyVersion</span> <span style="color: #f92672;">=</span> <span style="color: #e6db74;">'2.22.2'</span>
<span style="color: #f8f8f2;">ozarkVersion</span> <span style="color: #f92672;">=</span> <span style="color: #e6db74;">'1.0.0-m02'</span>
<span style="color: #f92672;">}</span>
<span style="color: #f8f8f2;">task</span> <span style="color: #a6e22e;">wrapper</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">type:</span> <span style="color: #f8f8f2;">Wrapper</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">gradleVersion</span> <span style="color: #f92672;">=</span> <span style="color: #e6db74;">'2.12'</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
<h3>
Standalone CDI container</h3>
<b>Weld</b> contains module to <b>support Java SE</b> applications. Together with <b>Apache DeltaSpike Java SE & Weld module</b>:<br />
<br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">dependencies</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.jboss.weld.se:weld-se:$weldVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.apache.deltaspike.cdictrl:deltaspike-cdictrl-weld:$deltaspikeVersion"</span>
</pre>
</div>
<br />
it is easy to bootstrap and shutdown CDI container:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 16.25px;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.enterprise.context.ApplicationScoped</span><span style="color: #f92672;">;</span>
</pre>
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.apache.deltaspike.cdise.api.CdiContainer</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.apache.deltaspike.cdise.api.CdiContainerLoader</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.jboss.weld.servlet.WeldInitialListener</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.jboss.weld.servlet.WeldTerminalListener</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">Main</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">static</span> <span style="color: #f8f8f2;">CdiContainer</span> <span style="color: #a6e22e;">init</span><span style="color: #f92672;">()</span> <span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">ServletException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">NoSuchMethodException</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">CdiContainer</span> <span style="color: #f8f8f2;">cdiContainer</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">CdiContainerLoader</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getCdiContainer</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">boot</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getContextControl</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">startContext</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">ApplicationScoped</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">initServlet</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #66d9ef;">static</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">destroy</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">CdiContainer</span> <span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getContextControl</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">stopContext</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">ApplicationScoped</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">cdiContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">shutdown</span><span style="color: #f92672;">();</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">...</span>
</pre>
</div>
<br />
You can see we also start and stop CDI <a href="https://docs.oracle.com/javaee/6/api/javax/enterprise/context/ApplicationScoped.html">ApplicationScoped</a> scope.<br />
<h3>
Initialize Servlet</h3>
Next we need to register <b>Jersey <a href="https://jersey.java.net/nonav/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletContainer.html">ServletContainer</a></b> as <b>Undertow</b> servlet:<br />
<br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">dependencies</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"io.undertow:undertow-core:$undertowVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"io.undertow:undertow-servlet:$undertowVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.glassfish.jersey.core:jersey-server:$jerseyVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.glassfish.jersey.containers:jersey-container-servlet-core:$jerseyVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.glassfish.jersey.ext.cdi:jersey-cdi1x-servlet:$jerseyVersion"</span>
</pre>
</div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.servlet.Servlet</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.servlet.ServletException</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.Undertow</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.servlet.Servlets</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.servlet.api.DeploymentInfo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.servlet.api.DeploymentManager</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.servlet.api.ServletContainer</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">io.undertow.servlet.api.ServletInfo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.jboss.weld.servlet.WeldInitialListener</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.jboss.weld.servlet.WeldTerminalListener</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">Main</span> <span style="color: #f92672;">{</span>
<span style="color: #f92672;">...</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">static</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">initServlet</span><span style="color: #f92672;">()</span> <span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">ServletException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">NoSuchMethodException</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">DeploymentInfo</span> <span style="color: #f8f8f2;">deploymentInfo</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">DeploymentInfo</span><span style="color: #f92672;">()</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">addListener</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Servlets</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">listener</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">WeldInitialListener</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">))</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">addListener</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Servlets</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">listener</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">WeldTerminalListener</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">))</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setContextPath</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/"</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setDeploymentName</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"standalone-javax-mvc-app"</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">addServlets</span><span style="color: #f92672;">(</span>
<span style="color: #f8f8f2;">createServletInfo</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/resources/*"</span><span style="color: #f92672;">,</span> <span style="color: #e6db74;">"JAX-RS Resources"</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">org</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">glassfish</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">jersey</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">servlet</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">ServletContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setClassIntrospecter</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">CdiClassIntrospecter</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">INSTANCE</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setAllowNonStandardWrappers</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">true</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setClassLoader</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">ClassLoader</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">getSystemClassLoader</span><span style="color: #f92672;">());</span>
<span style="color: #f8f8f2;">ServletContainer</span> <span style="color: #f8f8f2;">servletContainer</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">Servlets</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">defaultContainer</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">DeploymentManager</span> <span style="color: #f8f8f2;">deploymentManager</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">servletContainer</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">addDeployment</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">deploymentInfo</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">deploymentManager</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">deploy</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">Undertow</span> <span style="color: #f8f8f2;">server</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">Undertow</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">builder</span><span style="color: #f92672;">()</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">addHttpListener</span><span style="color: #f92672;">(</span><span style="color: #ae81ff;">8080</span><span style="color: #f92672;">,</span> <span style="color: #e6db74;">"0.0.0.0"</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setHandler</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">deploymentManager</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">start</span><span style="color: #f92672;">())</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">build</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">server</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">start</span><span style="color: #f92672;">();</span>
<span style="color: #f92672;">}</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">static</span> <span style="color: #f8f8f2;">ServletInfo</span> <span style="color: #a6e22e;">createServletInfo</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">String</span> <span style="color: #f8f8f2;">mapping</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">String</span> <span style="color: #f8f8f2;">servletName</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?</span> <span style="color: #66d9ef;">extends</span> <span style="color: #f8f8f2;">Servlet</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">servlet</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">NoSuchMethodException</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">ServletInfo</span> <span style="color: #f8f8f2;">servletInfo</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">Servlets</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">servlet</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">servletName</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">servlet</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setAsyncSupported</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">true</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">setLoadOnStartup</span><span style="color: #f92672;">(</span><span style="color: #ae81ff;">1</span><span style="color: #f92672;">)</span>
<span style="color: #f92672;">.</span><span style="color: #a6e22e;">addMapping</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">mapping</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">servletInfo</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">setInstanceFactory</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">CdiClassIntrospecter</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">INSTANCE</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">createInstanceFactory</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">servlet</span><span style="color: #f92672;">));</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">servletInfo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
Important part is registering of Weld Servlet listeners: <b>WeldInitialListener</b> and <b>WeldTerminalListener</b>.<br />
<br />
The instance of Jersey <b>ServletContainer</b> is provided as ApplicationScoped bean by custom <b>CdiProducer</b> using <b>CdiClassIntrospecter</b>.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.enterprise.inject.Produces</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.glassfish.jersey.server.ResourceConfig</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">org.glassfish.jersey.servlet.ServletContainer</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@ApplicationScoped</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">CdiProducer</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">long</span> <span style="color: #f8f8f2;">helloCounter</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@Produces</span>
<span style="color: #a6e22e;">@ApplicationScoped</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">ServletContainer</span> <span style="color: #a6e22e;">createServletContainer</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">ResourceConfig</span> <span style="color: #f8f8f2;">resourceConfig</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">ResourceConfig</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">resourceConfig</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">register</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">HelloController</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">resourceConfig</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">property</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"javax.mvc.engine.ViewEngine.viewFolder"</span><span style="color: #f92672;">,</span> <span style="color: #e6db74;">"WEB-INF/views/"</span><span style="color: #f92672;">);</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">new</span> <span style="color: #a6e22e;">ServletContainer</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">resourceConfig</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">...</span>
</pre>
</div>
<br />
You can see we need to customize <span style="font-family: "courier new" , "courier" , monospace;">"javax.mvc.engine.ViewEngine.viewFolder"</span> property to support standalone application class-path behaviour.<br />
<br />
<b>CdiClassIntrospecter</b> implements Undertow <a href="http://undertow.io/javadoc/1.3.x/io/undertow/servlet/api/class-use/ClassIntrospecter.html">ClassIntrospecter</a> interface and just delegates to CDI.<br />
<br />
<h3>
MVC</h3>
Now you can provide MVC @<a href="https://ozark.java.net/javax.mvc-api-1.0-edr1-javadoc/javax/mvc/Controller.html">Controller</a> methods:<br />
<br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">dependencies</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.glassfish.ozark:ozark:$ozarkVersion"</span>
<span style="color: #f8f8f2;">compile</span> <span style="color: #e6db74;">"org.glassfish.ozark.ext:ozark-mustache:$ozarkVersion"</span>
</pre>
</div>
<br />
<div style="background: #272822; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.enterprise.context.ApplicationScoped</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.inject.Inject</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.mvc.Models</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.mvc.annotation.Controller</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.mvc.annotation.View</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.DefaultValue</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.GET</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Path</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Produces</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.QueryParam</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@Path</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"hello"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@ApplicationScoped</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">HelloController</span> <span style="color: #f92672;">{</span>
<span style="color: #a6e22e;">@Inject</span>
<span style="color: #66d9ef;">private</span> <span style="color: #f8f8f2;">Models</span> <span style="color: #f8f8f2;">models</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@GET</span>
<span style="color: #a6e22e;">@Controller</span>
<span style="color: #a6e22e;">@Produces</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"text/html"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@View</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"hello.mustache"</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">hello</span><span style="color: #f92672;">(</span><span style="color: #a6e22e;">@QueryParam</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"user"</span><span style="color: #f92672;">)</span> <span style="color: #a6e22e;">@DefaultValue</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"World"</span><span style="color: #f92672;">)</span> <span style="color: #f8f8f2;">String</span> <span style="color: #f8f8f2;">user</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">models</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">put</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"user"</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">user</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
You can see I've chosen to use Mustache template engine, see <b>hello.mustache</b>:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f8f8f8; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: green; font-weight: bold;"><html></span>
<span style="color: green; font-weight: bold;"><head></span>
<span style="color: green; font-weight: bold;"><title></span>Hello<span style="color: green; font-weight: bold;"></title></span>
<span style="color: green; font-weight: bold;"></head></span>
<span style="color: green; font-weight: bold;"><body></span>
<span style="color: green; font-weight: bold;"><h1></span>Hello {{user}}!<span style="color: green; font-weight: bold;"></h1></span>
<span style="color: green; font-weight: bold;"></body></span>
<span style="color: green; font-weight: bold;"></html></span>
</pre>
</div>
<br />
<h3>
Sources</h3>
Complete project sources are available on GitHub, <a href="https://github.com/shamoh/standalone-javax-mvc">https://github.com/<b>shamoh/standalone-javax-mvc</b></a>.<br />
<div>
<br />
The easiest way how to run the project is:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f8f8f8; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">gradlew run
</pre>
</div>
<br />
The application is then available on: <span style="font-family: Arial, Helvetica, sans-serif;"><a href="http://localhost:8080/resources/hello">http://localhost:8080/resources/hello</a>?user=Libor</span>.<br />
<br />
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com7tag:blogger.com,1999:blog-2759548145050416517.post-62523512298341897982015-04-24T10:43:00.000+02:002015-04-24T10:43:07.168+02:00JAX-RS Kryo Message Body providers are placed to Jersey incubatorI have good news, mine JAX-RS Kryo support has been moved to <a href="https://github.com/jersey/jersey/tree/master/incubator/kryo">Jersey incubator</a>.<br />
<div>
<br /></div>
<div>
You can just add dependency on the module and your application can produce and consume <span style="font-family: Courier New, Courier, monospace;">application/x-kryo</span> entities:</div>
<div>
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #062873; font-weight: bold;"><dependency></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.glassfish.jersey.media<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>jersey-media-kryo<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>${jersey.version}<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></dependency></span>
</pre>
</div>
<div>
<br />
Original <a href="https://github.com/shamoh/jersey-kryo">GitHub repository</a> has been updated to use Jersey module. And as a bonus I've added two ways how to try it.<br />
<br />
This is true since Jersey 2.18. The version was not released yet in time of writing this blog post. So you need to use <span style="font-family: Courier New, Courier, monospace;">2.18-SNAPSHOT</span> version and add Maven snapshot repository to your project:<br />
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #062873; font-weight: bold;"><repositories></span>
<span style="color: #062873; font-weight: bold;"><repository></span>
<span style="color: #062873; font-weight: bold;"><id></span>java.net.snapshot<span style="color: #062873; font-weight: bold;"></id></span>
<span style="color: #062873; font-weight: bold;"><url></span>https://maven.java.net/content/repositories/snapshots/<span style="color: #062873; font-weight: bold;"></url></span>
<span style="color: #062873; font-weight: bold;"></repository></span>
<span style="color: #062873; font-weight: bold;"></repositories></span>
</pre>
</div>
<br />
<h2>
Grizzly it</h2>
Maven packaging of this demo application is <code><span style="font-family: Courier New, Courier, monospace;">war</span></code>. But it is possible to run the application using Grizzly HTTP container:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mvn <span style="color: #007020;">exec</span>:java
</pre>
</div>
<br />
You can enable <code>FINEST</code> logging using <code>logging.properties</code>:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mvn <span style="color: #007020;">exec</span>:java -Djava.util.logging.config.file<span style="color: #666666;">=</span>target/test-classes/logging.properties
</pre>
</div>
<br />
<h2>
Jetty it</h2>
Or you can run it as common webapp using Jetty container:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mvn jetty:run-war
</pre>
</div>
<br />
Again, you can enable <span style="font-family: Courier New, Courier, monospace;">FINEST</span> logging using <span style="font-family: Courier New, Courier, monospace;">logging.properties</span>:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">mvn jetty:run-war -Djava.util.logging.config.file<span style="color: #666666;">=</span>target/test-classes/logging.properties
</pre>
</div>
<br />
<h2>
Check it</h2>
GET method is available at URL <a href="http://localhost:8080/">http://localhost:8080/</a>, check it using <code>curl</code>:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">curl -v http://localhost:8080/
</pre>
</div>
<br />
Response should look like:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">> GET / HTTP/1.1
> User-Agent: curl/7.40.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Length: 20
< Content-Type: application/x-kryo
< Server: Jetty<span style="color: #666666;">(</span>8.1.16.v20140903<span style="color: #666666;">)</span>
<
Salzbur�*Wolfgan�
</pre>
</div>
<br />
<h2>
Origin</h2>
The Jersey Kryo support started as a "friday project". Evolution of the Kryo support shows list of previous blog posts:<br />
<ol>
<li><a href="http://yatel.kramolis.cz/2015/03/jax-rs-message-body-writer-using-kryo.html">JAX-RS Kryo support introduced</a></li>
<li><a href="http://yatel.kramolis.cz/2015/04/jax-rs-kryo-message-body-writer-reader.html">Performance report of JAX-RS Kryo support</a></li>
</ol>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com0tag:blogger.com,1999:blog-2759548145050416517.post-31699916855849101222015-04-10T22:04:00.000+02:002015-04-10T22:04:17.781+02:00JAX-RS Kryo Message Body Writer & Reader performanceIn this blog post I'm going to return to one of my <a href="http://yatel.kramolis.cz/2015/03/jax-rs-message-body-writer-using-kryo.html">previous post about JAX-RS Message Body Providers</a> using <a href="https://github.com/EsotericSoftware/kryo">Kryo serialization framework</a>. Today I'll show you performance statistics and compare it with some of Jersey build-in providers.<br />
<div>
<br /></div>
<h3>
Comparing to ...</h3>
<div>
I have chosen to compare my Kryo provider with:</div>
<div>
<ul>
<li><a href="https://github.com/jersey/jersey/tree/master/media/jaxb">JAXB RI providers</a> to read from and write to XML format.</li>
<li><a href="https://github.com/jersey/jersey/tree/master/media/json-jackson">Jackson providers</a> to read from and write to JSON format.</li>
<li><a href="https://github.com/jersey/jersey/blob/master/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/PersonProvider.java">Custom provider</a> that reads and writes test entity (<a href="https://github.com/jersey/jersey/blob/master/tests/performance/test-cases/mbw-custom-provider/src/main/java/org/glassfish/jersey/tests/performance/mbw/custom/Person.java">Person</a> class) by itself. (Note: Used format is really simple and implementation is Person specific, uses artificial MIKME type application/person.)</li>
<li>Just plain text provider to read and write String only. It uses Jersey build-in provider.</li>
</ul>
<div>
Test applications are very similar to mine <a href="https://github.com/shamoh/jersey-kryo">Jersey Kryo module</a> and are part of <a href="https://github.com/jersey/jersey">Jersey source code</a>:</div>
</div>
<div>
<ul>
<li><a href="https://github.com/jersey/jersey/tree/master/tests/performance/test-cases/mbw-xml-jaxb">JAXB/XML test application</a></li>
<li><a href="https://github.com/jersey/jersey/tree/master/tests/performance/test-cases/mbw-json-jackson">Jackson/JSON test application</a></li>
<li><a href="https://github.com/jersey/jersey/tree/master/tests/performance/test-cases/mbw-custom-provider">Custom provider test application</a></li>
<li><a href="https://github.com/jersey/jersey/tree/master/tests/performance/test-cases/mbw-text-plain">Plain text provider test application</a></li>
</ul>
<div>
<br /></div>
<h3>
Kryo provider</h3>
</div>
<div>
The Kryo provider has been introduced in <a href="http://yatel.kramolis.cz/2015/03/jax-rs-message-body-writer-using-kryo.html">previous blog post</a>. I have done one change since then. Performance of Kryo provider was several times improved using <a href="https://github.com/EsotericSoftware/kryo/blob/master/src/com/esotericsoftware/kryo/pool/KryoPool.java">KryoPool</a>:</div>
<div>
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #a6e22e;">@Consumes</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@Produces</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">KryoMessageBodyProvider</span> <span style="color: #66d9ef;">implements</span> <span style="color: #f8f8f2;">MessageBodyWriter</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">>,</span>
<span style="color: #f8f8f2;">MessageBodyReader</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">private</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">KryoPool</span> <span style="color: #f8f8f2;">kryoPool</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #a6e22e;">KryoMessageBodyProvider</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">KryoFactory</span> <span style="color: #f8f8f2;">kryoFactory</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">KryoFactory</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Kryo</span> <span style="color: #a6e22e;">create</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Kryo</span> <span style="color: #f8f8f2;">kryo</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Kryo</span><span style="color: #f92672;">();</span>
<span style="color: #75715e;">// configure kryo instance, customize settings</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">};</span>
<span style="color: #f8f8f2;">kryoPool</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">KryoPool</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">Builder</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">kryoFactory</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">softReferences</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">build</span><span style="color: #f92672;">();</span>
<span style="color: #f92672;">}</span>
<span style="color: #75715e;">//</span>
<span style="color: #75715e;">// MessageBodyWriter</span>
<span style="color: #75715e;">//</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">long</span> <span style="color: #a6e22e;">getSize</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f92672;">-</span><span style="color: #ae81ff;">1</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">boolean</span> <span style="color: #a6e22e;">isWriteable</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">true</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">writeTo</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MultivaluedMap</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">httpHeaders</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">OutputStream</span> <span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">IOException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">WebApplicationException</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">ByteArrayOutputStream</span> <span style="color: #f8f8f2;">baos</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">ByteArrayOutputStream</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Output</span> <span style="color: #f8f8f2;">output</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Output</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">baos</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">kryoPool</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">run</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">KryoCallback</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #a6e22e;">execute</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Kryo</span> <span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">writeObject</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">output</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">);</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">null</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">});</span>
<span style="color: #f8f8f2;">output</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">close</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">write</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">baos</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">toByteArray</span><span style="color: #f92672;">());</span>
<span style="color: #f92672;">}</span>
<span style="color: #75715e;">//</span>
<span style="color: #75715e;">// MessageBodyReader</span>
<span style="color: #75715e;">//</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">boolean</span> <span style="color: #a6e22e;">isReadable</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">true</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #a6e22e;">readFrom</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">MultivaluedMap</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">String</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">httpHeaders</span><span style="color: #f92672;">,</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">InputStream</span> <span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">IOException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">WebApplicationException</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">try</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Input</span> <span style="color: #f8f8f2;">input</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Input</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">);</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">kryoPool</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">run</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">KryoCallback</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #a6e22e;">execute</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Kryo</span> <span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">readObject</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">input</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">});</span>
<span style="color: #f8f8f2;">input</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">close</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span> <span style="color: #66d9ef;">catch</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Exception</span> <span style="color: #f8f8f2;">e</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">throw</span> <span style="color: #66d9ef;">new</span> <span style="color: #a6e22e;">WebApplicationException</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">e</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
<h3>
Test environment</h3>
<div>
Each test application was executed using <a href="https://github.com/jersey/jersey/tree/master/containers/grizzly2-http">Grizzly HTTP Server</a>, no servlet container, on 4 core VM. And load has been produced from another 2 client VMs using <a href="https://github.com/wg/wrk">wrk</a> - a HTTP benchmarking tool. GET, POST and PUT HTTP methods was measured. It is necessary to say each test works just with one instance of Person entity. It means data load is small. Test's focus is on throughput measurement. </div>
<div>
<br /></div>
<div>
<h3>
Test results</h3>
<div>
Following table shows number of requests per second for each tested provider and mentioned HTTP method:</div>
<div>
<br /></div>
<div style="text-align: center;">
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="153"></col><col width="68"></col><col width="70"></col><col width="62"></col></colgroup><tbody>
<tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td><td data-sheets-value="[null,2,"GET"]" style="background-color: #fce5cd; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom;">GET</td><td data-sheets-value="[null,2,"POST"]" style="background-color: #fce5cd; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom;">POST</td><td data-sheets-value="[null,2,"PUT"]" style="background-color: #fce5cd; border-bottom: 1px solid #000000; border-right: 1px solid #000000; border-top: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom;">PUT</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"XML (JAXB RI)"]" style="background-color: #cfe2f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom; vertical-align: middle;">XML (JAXB RI)</td><td data-sheets-formula="='Grizzly - Raw'!R10C1" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,21704.99966820025]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">21705</td><td data-sheets-formula="='Grizzly - Raw'!R10C2" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,11316.241537178166]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">11316</td><td data-sheets-formula="='Grizzly - Raw'!R10C3" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,12080.160191261519]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">12080</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"JSON (Jackson)"]" style="background-color: #cfe2f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom; vertical-align: middle;">JSON (Jackson)</td><td data-sheets-formula="='Grizzly - Raw'!R10C4" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,22097.179341419476]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">22097</td><td data-sheets-formula="='Grizzly - Raw'!R10C5" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,18590.0384261077]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">18590</td><td data-sheets-formula="='Grizzly - Raw'!R10C6" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,20115.832087282335]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">20116</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"Kryo"]" style="background-color: #cfe2f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom; vertical-align: middle;">Kryo</td><td data-sheets-formula="='Grizzly - Raw'!R10C13" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,21533.097328665102]" style="background-color: #d9ead3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">21533</td><td data-sheets-formula="='Grizzly - Raw'!R10C14" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,18370.75919471428]" style="background-color: #d9ead3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">18371</td><td data-sheets-formula="='Grizzly - Raw'!R10C15" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,21304.09941608362]" style="background-color: #d9ead3; border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">21304</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"Custom"]" style="background-color: #cfe2f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom; vertical-align: middle;">Custom</td><td data-sheets-formula="='Grizzly - Raw'!R10C7" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,21542.6853606492]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">21543</td><td data-sheets-formula="='Grizzly - Raw'!R10C8" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,18884.184308053365]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">18884</td><td data-sheets-formula="='Grizzly - Raw'!R10C9" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,20442.3464293926]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">20442</td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"TEXT (String)"]" style="background-color: #cfe2f3; border-bottom: 1px solid #000000; border-left: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; font-weight: bold; padding: 2px 3px 2px 3px; text-align: center; vertical-align: bottom; vertical-align: middle;">TEXT (String)</td><td data-sheets-formula="='Grizzly - Raw'!R10C10" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,21815.9496054341]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">21816</td><td data-sheets-formula="='Grizzly - Raw'!R10C11" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,17694.739488718216]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">17695</td><td data-sheets-formula="='Grizzly - Raw'!R10C12" data-sheets-numberformat="[null,2,"0"]" data-sheets-value="[null,3,null,19881.50361843937]" style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; font-size: 100%; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom; vertical-align: bottom;">19882</td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsbMKBMNzqTZ3dzHu6b7xguPxQbPGnMSI6i7sMqrwlRUYbrTpmvaCN1cf0uwZbNrupsPzvtl6DGpSyo7v0aaXRfGTyvq8RBreHfrOLIqFD81lNp88E71EkRZfysXpu7oG8KGcoszQ21H0/s1600/MBPbyMethod.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsbMKBMNzqTZ3dzHu6b7xguPxQbPGnMSI6i7sMqrwlRUYbrTpmvaCN1cf0uwZbNrupsPzvtl6DGpSyo7v0aaXRfGTyvq8RBreHfrOLIqFD81lNp88E71EkRZfysXpu7oG8KGcoszQ21H0/s1600/MBPbyMethod.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKiQHDBcsaunHVBYO0FoEHIuMDK46nYmXlt4SDI91y6xPr5W3miwpUp-DQWnlnw6qVN0PCxerKr-OMI1N6Y2TcqxIhwtpOZtvOaBy-uVj5FfHa26JlctksCuFwo4U6U3A8htJxYCVX5CQ/s1600/MBPbyProvider.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKiQHDBcsaunHVBYO0FoEHIuMDK46nYmXlt4SDI91y6xPr5W3miwpUp-DQWnlnw6qVN0PCxerKr-OMI1N6Y2TcqxIhwtpOZtvOaBy-uVj5FfHa26JlctksCuFwo4U6U3A8htJxYCVX5CQ/s1600/MBPbyProvider.png" /></a></div>
<br />
<h3>
Conclusion</h3>
</div>
<div>
Please note the Kryo provider is not in production quality. It just demonstrates how simple it is to enhance JAX-RS runtime to support new entity media type. However it is naive implementation of message body provider it provides very good performance. Kryo also support class registration and compression features that can also affect performance.<br />
<br />
And finally, test applications work just with one instance of entity (Person). I guess Kryo could show it's power while working with more complex objects or with collection of them. And Kryo compression feature would be very strong in such case. Maybe I could prepare such test in couple of next months. ;-)<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com1tag:blogger.com,1999:blog-2759548145050416517.post-63717556060873563152015-03-11T23:58:00.002+01:002015-03-14T11:49:06.694+01:00JAX-RS Client API Groovy DSL, prototype<a href="http://groovy-lang.org/">Groovy language</a> is DSL friendly language. See <a href="http://groovy-lang.org/dsls.html">http://groovy-lang.org/dsls.html</a> or <a href="http://groovy.codehaus.org/Writing+Domain-Specific+Languages">http://groovy.codehaus.org/Writing+Domain-Specific+Languages</a>.<br>
<br>
Let me share with you my JAX-RS Client API Groovy DSL prototype, code is available in GitHub <a href="https://github.com/shamoh/jersey-groovy">https://github.com/shamoh/jersey-groovy</a> repo. It just supports GET and POST methods. This is really just concept prototype. But it shows power of Groovy and way how simplified JAX-RS Client API could look like.<br>
<br>
The GitHub repository contains couple of <a href="https://github.com/shamoh/jersey-groovy/tree/master/tests/src/test/groovy/org/glassfish/jersey/groovy/tests">unit tests</a> to show the DSL. And also uses <a href="https://code.google.com/p/spock/">Spock Framework</a> what is another Groovy DSL example, in this case as testing framework/API.<br>
<br>
<h3>
Examples</h3>
<h4>
GET plain text, no parameters</h4>
<div>
JAX-RS Client API:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">WebTarget</span> <span style="color: #f8f8f2;">target</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">ClientBuilder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">newClient</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">target</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">target</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">request</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">TEXT_PLAIN_TYPE</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">get</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">)</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello World!"</span>
</pre>
</div>
</div>
<div>
Jersey Groovy DSL:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">GET</span><span style="color: #f92672;">[</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">].</span><span style="color: #a6e22e;">text</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello World!"</span>
</pre>
</div>
</div>
<h4>
<br></h4>
<h4>
GET plain text, path parameter</h4>
<div>
JAX-RS Client API:</div>
<div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">WebTarget</span> <span style="color: #f8f8f2;">target</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">ClientBuilder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">newClient</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">target</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">target</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">path</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">request</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">TEXT_PLAIN_TYPE</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">get</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">)</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<div>
Jersey Groovy DSL:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">GET</span><span style="color: #f92672;">[</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">/</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">].</span><span style="color: #a6e22e;">text</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
</div>
<h4>
<br></h4>
<h4>
GET XML, path parameter</h4>
<div>
JAX-RS Client API:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">WebTarget</span> <span style="color: #f8f8f2;">target</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">ClientBuilder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">newClient</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">target</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">target</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">path</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">request</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">APPLICATION_XML_TYPE</span><span style="color: #f92672;">).</span><span style="color: #a6e22e;">get</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Message</span><span style="color: #f92672;">)</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #66d9ef;">instanceof</span> <span style="color: #f8f8f2;">Message</span>
<span style="color: #f8f8f2;">response</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">greeting</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<div>
Jersey Groovy DSL:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">GET</span><span style="color: #f92672;">[</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">/</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">]</span> <span style="color: #f92672;">&</span> <span style="color: #f8f8f2;">APPLICATION_XML_TYPE</span><span style="color: #f92672;">)</span> <span style="color: #66d9ef;">as</span> <span style="color: #f8f8f2;">Message</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #66d9ef;">instanceof</span> <span style="color: #f8f8f2;">Message</span>
<span style="color: #f8f8f2;">response</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">greeting</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<h4>
<br></h4>
<h4>
POST plain text, response text</h4>
<div>
JAX-RS Client API:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">WebTarget</span> <span style="color: #f8f8f2;">target</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">ClientBuilder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">newClient</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">target</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">Entity</span> <span style="color: #f8f8f2;">entity</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">Entity</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">entity</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">TEXT_PLAIN_TYPE</span><span style="color: #f92672;">);</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">target</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">request</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">post</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">entity</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">String</span><span style="color: #f92672;">)</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<div>
Jersey Groovy DSL:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">POST</span><span style="color: #f92672;">[</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">]</span> <span style="color: #f92672;"><<</span> <span style="color: #e6db74;">"Jersey"</span> <span style="color: #66d9ef;">as</span> <span style="color: #f8f8f2;">String</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<div>
<br></div>
<h4>
POST object as JSON, response text</h4>
<div>
JAX-RS Client API:</div>
<div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f8f8f2;">WebTarget</span> <span style="color: #f8f8f2;">target</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">ClientBuilder</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">newClient</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">target</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">Entity</span> <span style="color: #f8f8f2;">entity</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">Entity</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">entity</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Message</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Date</span><span style="color: #f92672;">()),</span> <span style="color: #f8f8f2;">APPLICATION_JSON_TYPE</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">target</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">request</span><span style="color: #f92672;">().</span><span style="color: #a6e22e;">post</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">entity</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">String</span><span style="color: #f92672;">)</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
<div>
Jersey Groovy DSL:</div>
<div>
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #66d9ef;">def</span> <span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">=</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">POST</span><span style="color: #f92672;">[</span><span style="color: #f8f8f2;">RESOURCE_URL</span><span style="color: #f92672;">]</span> <span style="color: #f92672;">|</span> <span style="color: #f8f8f2;">APPLICATION_JSON_TYPE</span><span style="color: #f92672;">)</span> <span style="background-color: #1e0010; color: #960050;">\</span>
<span style="color: #f92672;"><<</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Message</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Jersey"</span><span style="color: #f92672;">,</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Date</span><span style="color: #f92672;">())</span> <span style="color: #66d9ef;">as</span> <span style="color: #f8f8f2;">String</span>
<span style="color: #f8f8f2;">response</span> <span style="color: #f92672;">==</span> <span style="color: #e6db74;">"Hello Jersey!"</span>
</pre>
</div>
</div>
</div>
<br>
(And finally there is simple <a href="http://shamoh.github.io/jersey-groovy/slides/">slide deck</a> to introduce the DSL API, same examples.)<br>
<div>
<br></div>
Enjoy.<br>
<br>Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com1tag:blogger.com,1999:blog-2759548145050416517.post-39662006387316566882015-03-11T01:56:00.000+01:002015-03-29T21:24:51.976+02:00JAX-RS Message Body Writer & Reader using Kryo serialization framework<br />
In this post I'm gonna show you how simple it is to enhance JAX-RS application by a new body format. In this example I use <b>Kryo</b> serialization framework.<br />
<br />
<h3>
Kryo serialization framework</h3>
<blockquote class="tr_bq">
<a href="http://kryo.googlecode.com/svn/wiki/kryo-logo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://kryo.googlecode.com/svn/wiki/kryo-logo.jpg" height="84" width="200" /></a><br />
<blockquote class="tr_bq">
<a href="https://github.com/EsotericSoftware/kryo">Kryo</a> is a fast and efficient object graph serialization framework for Java. The goals of the project are speed, efficiency, and an easy to use API. The project is useful any time objects need to be persisted, whether to a file, database, or over the network.</blockquote>
<blockquote class="tr_bq">
Kryo can also perform automatic deep and shallow copying/cloning. This is direct copying from object to object, not object->bytes->object.</blockquote>
</blockquote>
<h3>
JAX-RS Message Body providers</h3>
JAX-RS allows you to enhance JAX-RS engine to support another body type. There is <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/ext/MessageBodyReader.html">MessageBodyReader</a> and <a href="https://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/ext/MessageBodyWriter.html">MessageBodyWriter</a> SPI to be implemented. I have chosen to use <span style="font-family: Courier New, Courier, monospace;">application/x-kryo</span> media type for Kryo (de)serialized message bodies.<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">package</span> <span style="color: #f8f8f2;">cz</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kramolis</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">jersey</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kryo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.io.ByteArrayOutputStream</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.io.IOException</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.io.InputStream</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.io.OutputStream</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.lang.annotation.Annotation</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.lang.reflect.Type</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Consumes</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Produces</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.WebApplicationException</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.core.MediaType</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.core.MultivaluedMap</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.ext.MessageBodyReader</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.ext.MessageBodyWriter</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.esotericsoftware.kryo.Kryo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.esotericsoftware.kryo.io.Input</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">com.esotericsoftware.kryo.io.Output</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@Consumes</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@Produces</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">KryoMessageBodyProvider</span> <span style="color: #66d9ef;">implements</span>
<span style="color: #f8f8f2;">MessageBodyWriter</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">>,</span>
<span style="color: #f8f8f2;">MessageBodyReader</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f92672;">{</span>
<span style="color: #75715e;">//</span>
<span style="color: #75715e;">// MessageBodyWriter</span>
<span style="color: #75715e;">//</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">long</span> <span style="color: #a6e22e;">getSize</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f92672;">-</span><span style="color: #ae81ff;">1</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">boolean</span> <span style="color: #a6e22e;">isWriteable</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">true</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">writeTo</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">MultivaluedMap</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">httpHeaders</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">OutputStream</span> <span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">IOException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">WebApplicationException</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">ByteArrayOutputStream</span> <span style="color: #f8f8f2;">baos</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">ByteArrayOutputStream</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Kryo</span> <span style="color: #f8f8f2;">kryo</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Kryo</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Output</span> <span style="color: #f8f8f2;">output</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Output</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">baos</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">writeObject</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">output</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">output</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">close</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">write</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">baos</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">toByteArray</span><span style="color: #f92672;">());</span>
<span style="color: #f92672;">}</span>
<span style="color: #75715e;">//</span>
<span style="color: #75715e;">// MessageBodyReader</span>
<span style="color: #75715e;">//</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">boolean</span> <span style="color: #a6e22e;">isReadable</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">true</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Object</span> <span style="color: #a6e22e;">readFrom</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Object</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">Type</span> <span style="color: #f8f8f2;">genericType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">Annotation</span><span style="color: #f92672;">[]</span> <span style="color: #f8f8f2;">annotations</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">MediaType</span> <span style="color: #f8f8f2;">mediaType</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">MultivaluedMap</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">String</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">String</span><span style="color: #f92672;">></span> <span style="color: #f8f8f2;">httpHeaders</span><span style="color: #f92672;">,</span>
<span style="color: #f8f8f2;">InputStream</span> <span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">)</span> <span style="color: #66d9ef;">throws</span> <span style="color: #f8f8f2;">IOException</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">WebApplicationException</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">try</span> <span style="color: #f92672;">{</span>
<span style="color: #f8f8f2;">Kryo</span> <span style="color: #f8f8f2;">kryo</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Kryo</span><span style="color: #f92672;">();</span>
<span style="color: #f8f8f2;">Input</span> <span style="color: #f8f8f2;">input</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">Input</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">entityStream</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">Object</span> <span style="color: #f8f8f2;">object</span> <span style="color: #f92672;">=</span> <span style="color: #f8f8f2;">kryo</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">readObject</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">input</span><span style="color: #f92672;">,</span> <span style="color: #f8f8f2;">type</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">input</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">close</span><span style="color: #f92672;">();</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">object</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span> <span style="color: #66d9ef;">catch</span> <span style="color: #f92672;">(</span><span style="color: #f8f8f2;">Exception</span> <span style="color: #f8f8f2;">e</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">throw</span> <span style="color: #66d9ef;">new</span> <span style="color: #a6e22e;">WebApplicationException</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">e</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
You can see it is really simple Message Body provider. But I hope it shows you the way...<br />
<br />
Than you need to register provider class into JAX-RS Application, e.g.<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">package</span> <span style="color: #f8f8f2;">cz</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kramolis</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">jersey</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kryo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.util.HashSet</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">java.util.Set</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.core.Application</span><span style="color: #f92672;">;</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">JaxRsApplication</span> <span style="color: #66d9ef;">extends</span> <span style="color: #f8f8f2;">Application</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">static</span> <span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Set</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?>></span> <span style="color: #f8f8f2;">APP_CLASSES</span> <span style="color: #f92672;">=</span> <span style="color: #66d9ef;">new</span> <span style="color: #f8f8f2;">HashSet</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?>>()</span> <span style="color: #f92672;">{{</span>
<span style="color: #f8f8f2;">add</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">KryoMessageBodyProvider</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">);</span>
<span style="color: #f8f8f2;">add</span><span style="color: #f92672;">(</span><span style="color: #f8f8f2;">PersonResource</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">class</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}};</span>
<span style="color: #a6e22e;">@Override</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Set</span><span style="color: #f92672;"><</span><span style="color: #f8f8f2;">Class</span><span style="color: #f92672;"><?>></span> <span style="color: #f8f8f2;">getClasses</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">APP_CLASSES</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
<br />
And finally usage of the new body type is very easy:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #272822; border-width: .1em .1em .1em .8em; border: solid gray; overflow: auto; padding: .2em .6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #f92672;">package</span> <span style="color: #f8f8f2;">cz</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kramolis</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">jersey</span><span style="color: #f92672;">.</span><span style="color: #a6e22e;">kryo</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Consumes</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.GET</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.POST</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.PUT</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Path</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">import</span> <span style="color: #f8f8f2;">javax.ws.rs.Produces</span><span style="color: #f92672;">;</span>
<span style="color: #a6e22e;">@Path</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"/"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@Consumes</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #a6e22e;">@Produces</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"application/x-kryo"</span><span style="color: #f92672;">)</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">class</span> <span style="color: #a6e22e;">PersonResource</span> <span style="color: #f92672;">{</span>
<span style="color: #a6e22e;">@POST</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Person</span> <span style="color: #a6e22e;">echo</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Person</span> <span style="color: #f8f8f2;">person</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #f8f8f2;">person</span><span style="color: #f92672;">;</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@PUT</span>
<span style="color: #66d9ef;">public</span> <span style="color: #66d9ef;">void</span> <span style="color: #a6e22e;">put</span><span style="color: #f92672;">(</span><span style="color: #66d9ef;">final</span> <span style="color: #f8f8f2;">Person</span> <span style="color: #f8f8f2;">person</span><span style="color: #f92672;">)</span> <span style="color: #f92672;">{</span>
<span style="color: #f92672;">}</span>
<span style="color: #a6e22e;">@GET</span>
<span style="color: #66d9ef;">public</span> <span style="color: #f8f8f2;">Person</span> <span style="color: #a6e22e;">get</span><span style="color: #f92672;">()</span> <span style="color: #f92672;">{</span>
<span style="color: #66d9ef;">return</span> <span style="color: #66d9ef;">new</span> <span style="color: #a6e22e;">Person</span><span style="color: #f92672;">(</span><span style="color: #e6db74;">"Wolfgang"</span><span style="color: #f92672;">,</span> <span style="color: #ae81ff;">21</span><span style="color: #f92672;">,</span> <span style="color: #e6db74;">"Salzburg"</span><span style="color: #f92672;">);</span>
<span style="color: #f92672;">}</span>
<span style="color: #f92672;">}</span>
</pre>
</div>
<br />
<br />
<h3>
Conclusion</h3>
Whole sources are available in dedicated <a href="https://github.com/shamoh/jersey-kryo">GitHub repository</a>. Use it as you need. JAX-RS provides really simple way how to extend it's support. And Kryo is really powerful framework. Give it a try. Look at deeper <a href="https://github.com/eishay/jvm-serializers">JVM serializers comparision</a>.<br />
<br />
In one of the next blog posts I will provider some performance data comparing Kryo with JSON, XML and others message body providers.<br />
<br />
<h3>
Links</h3>
<ul>
<li><a href="https://github.com/EsotericSoftware/kryo">https://github.com/EsotericSoftware/kryo</a> - Kryo GitHub</li>
<li><a href="https://github.com/eishay/jvm-serializers">https://github.com/eishay/jvm-serializers</a> - Benchmark comparing serialization libraries on the JVM</li>
<li><a href="https://github.com/jersey/jersey">https://github.com/jersey/jersey</a> - Jersey GitHub</li>
<li><a href="https://jersey.java.net/">https://jersey.java.net/</a> - Jersey home page</li>
<li><a href="https://jersey.java.net/documentation/latest/message-body-workers.html">https://jersey.java.net/documentation/latest/message-body-workers.html</a> - Jersey Message Body providers docs</li>
<li><a href="https://github.com/shamoh/jersey-kryo">https://github.com/shamoh/jersey-kryo</a> - this blog post example GitHub project</li>
</ul>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com4tag:blogger.com,1999:blog-2759548145050416517.post-62698009401350242772015-02-14T22:06:00.000+01:002015-02-14T22:06:48.831+01:00Jersey 2.16 has been released<div class="p1">
<span class="s1"><a href="https://jersey.java.net/team-list.html">Jersey team</a> is happy to announce availability of <b><a href="https://jersey.java.net/">Jersey</a> 2.16</b>.</span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">For an overview of changes, bug fixes, new features and <b>7</b> merged <a href="https://github.com/jersey/jersey/">GitHub</a> pull requests, please consult <a href="https://jersey.java.net/release-notes/2.16.html">Jersey 2.16 Release Notes</a>.</span></div>
<h3>
<span class="s3"><b>Highlights</b></span></h3>
<h4>
<span class="s3">JAX-B providers separated from the core</span></h4>
<div class="p2">
From version 2.16 onwards, all JAX-B providers are being bundled in a separate module.</div>
<div class="p2">
<br /></div>
<div class="p2">
The main motivation behind that is t allow using Jersey Client on Android. <span class="s1"></span><span class="s1">Current status of Android support has been described by <a href="https://plus.google.com/u/0/108436407258959325104/about">Jakub Podlešák</a> in his </span><a href="https://blogs.oracle.com/japod/entry/jersey_2_x_client_on">Jersey 2.x Client on Android</a> blog post.</div>
<h4>
<span class="s3">Performance gain when using Sub-Resource Locators</span></h4>
<div class="p2">
<span class="s1">We improved the performance for using sub-resource locators in an Jersey application. The performance gains are available for cases when the sub-resource locator method returns either a resource class (return value is e.g. </span><span class="s4"><span style="font-family: Courier New, Courier, monospace;">Class<?></span></span><span class="s1"> or </span><span class="s4"><span style="font-family: Courier New, Courier, monospace;">Class<MySubResource></span></span><span class="s1">) or a (non-proxied) resource instance (when return value is an instance of <span style="font-family: Courier New, Courier, monospace;">MySubResource</span> class).</span><span class="s1"></span></div>
<div class="p2">
<span class="s1"><br /></span></div>
<div class="p2">
<span class="s1">This is described by <a href="https://plus.google.com/114019189542073327992/about">Michal Gajdoš</a> in more detail in his Performance Improvements of <a href="http://blog.dejavu.sk/2015/02/12/performance-improvements-of-sub-resource-locators-in-jersey/">Sub-Resource Locators in Jersey</a> blog post.</span></div>
<div class="p2">
<span class="s1"><br /></span></div>
<div class="p2">
<span class="s1">Another blog post about is again by Jakub about general <a href="https://blogs.oracle.com/japod/entry/jersey_2_performance">Jersey 2 performance improvements</a>.</span></div>
<h4>
<span class="s3">More unified connector configuration options</span></h4>
<div class="p2">
Jetty connector and Apache connector have been previously using their own custom properties to set SSL context on a connector. These properties have been deprecated and the code has been updated to read the SSL context information from the JAX-RS client configuration. This means that all Jersey connectors now properly accept SSL configuration as configured via standard JAX-RS <a href="http://jax-rs-spec.java.net/nonav/2.0/apidocs/javax/ws/rs/client/ClientBuilder.html"><span class="s5">ClientBuilder</span></a> methods.<span class="s1"></span></div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">Previously, all Jersey connectors have been using their own default chunk size when HTTP chunked coding was used. Since Jersey 2.16, there is a new default chunk size value used by all connectors, if a custom chunk size is not set. The new default value is stored under <a href="https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/client/ClientProperties.html#DEFAULT_CHUNK_SIZE"><span class="s5">ClientProperties.DEFAULT_CHUNK_SIZE</span></a> client property.</span></div>
<h3>
Links</h3>
<div class="p2">
To download Jersey 2.16, please check our <a href="https://jersey.java.net/download.html">download page</a>.</div>
<div class="p2">
<span class="s1"></span><br /></div>
<div class="p1">
<span class="s1">You can also check out the refreshed Jersey 2.16 documentation:</span></div>
<ul class="ul1">
<li class="li3"><span class="s6"></span><span class="s7">API: <a href="https://jersey.java.net/apidocs/2.16/jersey/index.html"><span class="s8">https://jersey.java.net/apidocs/2.16/jersey/</span></a></span></li>
<li class="li3"><span class="s6"></span><span class="s7">User Guide: <span class="s8"><a href="https://jersey.java.net/documentation/2.16/index.html">https://jersey.java.net/documentation/2.16/</a></span></span></li>
</ul>
<h4>
Other blog posts</h4>
<div>
<ul>
<li><a href="https://blogs.oracle.com/japod/entry/container_agnostic_cdi_support_in">Container Agnostic CDI Support In Jersey</a> by Jakub - Jersey 2.5 introduced Weld SE support, so that people could take advantage of CDI features also when running in Java SE environment.</li>
<li><a href="http://hnusfialovej.cz/2015/01/30/upload-file-to-mongodb-using-jersey-2/">Upload file to MongoDB using Jersey 2</a> by <a href="https://plus.google.com/u/0/+AdamLindenthal/about">Adam Lindenthal</a> - Using GridFS to store files accepted by RESTful API.</li>
<li><a href="http://blog.dejavu.sk/2015/02/04/jerseys-entity-filtering-meets-jackson/">Jersey’s Entity Filtering meets Jackson</a> by Michal - Entity Filtering in Jersey introduces a convenient facility for reducing the amount of JSON data exchanged over the wire between client and server without a need to create specialized data view components. Since Jersey 2.6 Entity Filtering feature is implemented with Moxy and as well as Jackson now.</li>
<li><a href="http://blog.dejavu.sk/2015/01/21/intercepting-jersey-resource-method-calls/">Intercepting Jersey resource method calls</a> by Michal - In Jersey 2 it is possible to intercept resource method calls outside CDI but via HK2.</li>
</ul>
</div>
<div class="p2">
<span class="s1"></span></div>
<h3>
Feedback</h3>
<div class="p2">
For feedback send an email to: <a href="mailto:users@jersey.java.net">users@jersey.java.net</a> (archived <a href="https://java.net/projects/jersey/lists/users/archive">here</a>)</div>
<div class="p2">
or log bugs/features <a href="https://java.net/jira/browse/JERSEY">here</a>.</div>
<div class="p2">
<br /></div>
<div class="p2">
<br /></div>
Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com1tag:blogger.com,1999:blog-2759548145050416517.post-82157241807465288482015-01-17T00:31:00.000+01:002015-01-17T00:43:46.733+01:00Reactive Jersey Client using Java 8, RxJava and Netflix HystrixIn this post I will show you how to use <b><a href="https://jersey.java.net/" target="_blank">Jersey</a></b> Client Reactive API, it's <b><a href="https://github.com/ReactiveX/RxJava" target="_blank">RxJava</a> <a href="http://reactivex.io/RxJava/javadoc/rx/Observable.html" target="_blank">Observable</a></b> support together with <b>Netflix <a href="https://github.com/Netflix/Hystrix" target="_blank">Hystrix</a></b>, latency and fault tolerance library. All sources are placed in GitHub <a href="https://github.com/shamoh/jersey--examples--rx-client-java8-webapp" target="_blank">jersey--examples--rx-client-java8-webapp</a> project.<br />
<br />
<b>Jersey<span id="goog_441710426"></span><span id="goog_441710427"></span><a href="https://draft.blogger.com/"></a></b> framework contains <b>Reactive Client API</b>. Reactive Jersey Client API is a generic API allowing end users to utilize the popular reactive programming model when using Jersey Client. Reactive programming is very popular these days. <b>It helps you to implement asynchronous code with solved <a href="http://www.infoq.com/research/tackling-async-callback-hell" target="_blank">callback hell</a> issue.</b><br />
<h3>
<br /></h3>
<h3>
Jersey</h3>
Jersey supports <b>RxJava Observable</b>, <b>Java 8 CompletionStage</b> and <b>CompletableFuture</b>, <b>Guava ListenableFuture</b> and <b>Futures</b>, <b>JSR-166e CompletableFuture</b>. It also provides <b>SPI</b> to be extended by custom reactive libraries.<br />
<br />
There is excellent 3 part blog post series written by <b><a href="https://plus.google.com/u/0/114019189542073327992/about" target="_blank">Michal Gajdoš</a></b> about Reactive Jersey Client:<br />
<ol>
<li><a href="http://blog.dejavu.sk/2015/01/07/reactive-jersey-client-part-1-motivation/" target="_blank">Reactive Jersey Client – Motivation</a></li>
<li><a href="http://blog.dejavu.sk/2015/01/07/reactive-jersey-client-part-2-usage-and-supported-reactive-libraries/" target="_blank">Reactive Jersey Client – Usage and Supported Reactive Libraries</a></li>
<li><a href="http://blog.dejavu.sk/2015/01/07/reactive-jersey-client-part-3-customization/" target="_blank">Reactive Jersey Client – Customization (SPI)</a></li>
</ol>
<br />
<a href="https://github.com/jersey/jersey" target="_blank">Jersey</a> source code contains also examples for supported reactive libraries, see modules:<br />
<ul>
<li><a href="https://github.com/jersey/jersey/tree/master/examples/rx-client-webapp" target="_blank">examples/rx-client-webapp</a> - Jersey Reactive Client Extension WebApp Example.</li>
<li><a href="https://github.com/jersey/jersey/tree/master/examples/rx-client-java8-webapp" target="_blank">examples/rx-client-java8-webapp</a> - Jersey Reactive Client Extension (Java8) WebApp Example.</li>
</ul>
<h3>
<br /></h3>
<h3>
Hystrix</h3>
<div>
<i>Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.</i></div>
<div>
<br /></div>
<div>
You usually use Hystrix to isolate dependent system call into <a href="http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/HystrixCommand.html" target="_blank"><b>HystrixCommand</b></a> class. It allows to be executed <a href="http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/HystrixCommand.html#execute()" target="_blank">synchronously</a>, <a href="http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/HystrixCommand.html#queue()" target="_blank">asynchronously</a> (returns java.util.concurrent.<b>Future</b>) and also <a href="http://netflix.github.io/Hystrix/javadoc/com/netflix/hystrix/HystrixCommand.html#observe()" target="_blank">asynchronously via RxJava Observable</a>.</div>
<br />
<h3>Code</h3>
In case dependent system already supports RxJava Observable API you can use specific <b><a href="https://github.com/Netflix/Hystrix/blob/master/hystrix-core/src/main/java/com/netflix/hystrix/HystrixObservableCommand.java" target="_blank">HystrixObservableCommand</a></b> class. And thanks to Jersey Reactive Client API and its RxJava support it allows us to write resilient JAX-RS client code.</u><br />
<br />
<pre>private class <u>ForecastCommand</u> extends <u><i>HystrixObservableCommand</i></u><Forecast> {
private final Destination destination;
...
@Override
protected Observable<Forecast> <u>run</u>() {
return <u>RxObservable</u>.from(forecastWebTarget)
.resolveTemplate("destination", destination.getDestination())
.request().<u>rx</u>()
.get(Forecast.class);
}
@Override
protected Observable<Forecast> <u>getFallback</u>() {
return Observable.just(new Forecast(destination.getDestination(), "<i>N/A</i>"));
}
}</pre>
<br />
The code above creates new Hystrix RxJava Observable ready Command that invokes remote REST API using Jersey Reactive Client API. Whenever API call fails or times out a <i>getFallback()</i> method is invoked. And in this case we return Forecast instance with <i>N/A</i> forecast value.<br />
<br />
Whole example web application enhanced by code using Hystrix is placed into my GitHub <a href="https://github.com/shamoh/jersey--examples--rx-client-java8-webapp" target="_blank">jersey--examples--rx-client-java8-webapp</a> repository. Shown and little but simplified code snipped is from <a href="https://github.com/shamoh/jersey--examples--rx-client-java8-webapp/blob/master/src/main/java/org/glassfish/jersey/examples/rx/agent/HystrixObservableAgentResource.java#L77" target="_blank">HystrixObservableAgentResource</a> class. The example module is clone of <i>rx-client-java8-webapp</i>.<br />
<br />
To run the example:<br />
<pre>
<i>mvn clean package jetty:run</i>
</pre>
<br />
At beginning of <i>HystrixObservableAgentResource</i> class there are <i>TIMEOUT_*</i> constants. You can play with values and you will see that sometimes you don't get all domain objects' values and sometimes you see default values (<i>N/A</i> for <i>Forecast</i> and <i>-1</i> for <i>Calculation</i>). You can also play with <i>Thread.sleep</i> intervals but because of Hystrix timeout support the overall JAX-RS resource method processing time is never (too much) longer than <i>TIMEOUT_OVERALL</i> (currently 900 ms).<br />
<br />
You can also check unit test <a href="https://github.com/shamoh/jersey--examples--rx-client-java8-webapp/blob/master/src/test/java/org/glassfish/jersey/examples/rx/RxClientsTest.java#L148" target="_blank">RxClientsTest</a>. Processing time is expected between 850 and 950 ms!<br />
<h3>
<br /></h3>
<h3>
Links</h3>
<div>
<br /></div>
<div>
<ul>
<li><a href="https://github.com/Netflix/Hystrix">https://github.com/Netflix/Hystrix</a> - Hystrix GitHub</li>
<li><a href="https://github.com/Netflix/Hystrix/wiki">https://github.com/Netflix/Hystrix/wiki</a> - Hystrix GitHub Wiki</li>
<li><a href="http://netflix.github.io/Hystrix/javadoc/">http://netflix.github.io/Hystrix/javadoc/</a> - Hystrix Javadoc</li>
<li><a href="https://jersey.java.net/documentation/latest/rx-client.html">https://jersey.java.net/documentation/latest/rx-client.html</a> - Jersey User Guide: Reactive Jersey Client API</li>
<li><a href="http://reactivex.io/RxJava/javadoc/">http://reactivex.io/RxJava/javadoc/</a> - RxJava Javadoc</li>
<li><a href="http://blogs.microsoft.co.il/bnaya/2010/02/25/rx-for-beginners-toc/">http://blogs.microsoft.co.il/bnaya/2010/02/25/rx-for-beginners-toc/</a> - Microsoft Blog: Rx for beginners</li>
<li><a href="https://speakerdeck.com/benjchristensen/reactive-streams-with-rx-at-javaone-2014">https://speakerdeck.com/benjchristensen/reactive-streams-with-rx-at-javaone-2014</a> - <b>Ben Christensen</b>'s Reactive Streams with Rx at JavaOne 2014 slides</li>
<li><a href="https://www.parleys.com/play/543f8d5be4b06e1184ae4106/about">https://www.parleys.com/play/543f8d5be4b06e1184ae4106/about</a> - Ben Christensen's <b>Reactive Streams</b> with Rx at JavaOne 2014 presentation</li>
</ul>
</div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com46tag:blogger.com,1999:blog-2759548145050416517.post-24422730886094512752013-11-18T11:39:00.000+01:002015-02-13T18:30:27.502+01:00How to configure JDK logging for Jersey 2 testsJersey uses <a href="http://docs.oracle.com/javase/7/docs/api/java/util/logging/package-summary.html">JDK Logging API</a> to log messages.<br />
<br />
One way how to configure JDK Logging is a <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/logging/overview.html#a1.8">properties file</a>. In such case you have to set JVM system property <a href="http://docs.oracle.com/javase/7/docs/api/java/util/logging/LogManager.html">java.util.logging.config.file</a> to reference the properties file.<br />
<br />
Initially the logging configuration file <span style="font-family: Courier New, Courier, monospace;">logging.properties</span> can look:<br />
<br />
<!-- HTML generated using hilite.me --><div style="background: #272822; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #75715e">#All attributes details</span>
<span style="color: #a6e22e">handlers</span><span style="color: #f92672">=</span><span style="color: #e6db74">java.util.logging.ConsoleHandler</span>
<span style="color: #a6e22e">java.util.logging.ConsoleHandler.level</span><span style="color: #f92672">=</span><span style="color: #e6db74">FINEST</span>
<span style="color: #a6e22e">java.util.logging.SimpleFormatter.format</span><span style="color: #f92672">=</span><span style="color: #e6db74">%4$-7s [%3$s] %5$s%6$s%n</span>
<span style="color: #75715e">#All log level details</span>
<span style="color: #a6e22e">.level</span><span style="color: #f92672">=</span><span style="color: #e6db74">INFO</span>
<span style="color: #a6e22e">org.glassfish.jersey.level</span><span style="color: #f92672">=</span><span style="color: #e6db74">CONFIG</span>
<span style="color: #a6e22e">org.glassfish.jersey.tracing.level</span><span style="color: #f92672">=</span><span style="color: #e6db74">FINEST</span>
</pre></div>
<br />
The configuration explained:<br />
<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">handlers=java.util.logging.ConsoleHandler</span> - log messages are written to <span style="font-family: Courier New, Courier, monospace;">System.err</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">java.util.logging.ConsoleHandler.level=FINEST</span> - allow to log <span style="font-family: Courier New, Courier, monospace;">FINEST</span> message;<br />default is <span style="font-family: Courier New, Courier, monospace;">INFO</span> so more detailed messages are suppressed by default</li>
<li><span style="font-family: Courier New, Courier, monospace;"><a href="http://docs.oracle.com/javase/7/docs/api/java/util/logging/SimpleFormatter.html#format(java.util.logging.LogRecord)">java.util.logging.SimpleFormatter.format</a></span> - example of simple and single line format - just level, logger name and message;<br />Note: It just works with Java 7.</li>
<li><span style="font-family: Courier New, Courier, monospace;">org.glassfish.jersey.level=CONFIG</span> - example of per-package level configuration;<br />log all <span style="font-family: Courier New, Courier, monospace;">SEVERE</span>, <span style="font-family: Courier New, Courier, monospace;">WARNING</span>, <span style="font-family: Courier New, Courier, monospace;">INFO</span> and <span style="font-family: Courier New, Courier, monospace;">CONFIG</span> level Jersey messages</li>
<li><span style="font-family: Courier New, Courier, monospace;">org.glassfish.jersey.tracing.level=FINEST</span> - example of detailed level configuration of specified package</li>
</ul>
And as mentioned it is necessary to set system property <span style="font-family: Courier New, Courier, monospace;">java.util.logging.config.file</span>. Do you want to see log messages during unit testing (e.g. using maven)? There are two options:<br />
<br />
<ul>
<li>run tests in new JVM instance (fork option) and configure the system property in such maven plugin</li>
<li>enhance maven command line parameter and add the <br /><span style="font-family: Courier New, Courier, monospace;">-Djava.util.logging.config.file=...</span> property</li>
</ul>
<br />
For example, run test application using Jetty server for test module <span style="font-family: Courier New, Courier, monospace;">tracing-support</span>:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">~/jersey2/tests/integration/tracing-support$ mvn compile jetty:run <b>-Djava.util.logging.config.file=<i>src/test/resources/logging.properties</i></b></span><br />
<br />
<span style="font-family: Verdana, sans-serif;">-that's all folks</span>Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com25tag:blogger.com,1999:blog-2759548145050416517.post-31418712332029502172013-11-16T00:11:00.000+01:002013-11-16T00:11:23.960+01:00Jersey 2 - Tracing support<h2>
What is Jersey?</h2>
This is my first Jersey related post so let me introduce <a href="https://jersey.java.net/">Jersey framework</a>.<br />
<blockquote class="tr_bq">
<a href="https://jersey.java.net/images/jersey_logo.png" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://jersey.java.net/images/jersey_logo.png" /></a>Jersey RESTful Web Services framework is open source, production quality, framework for developing RESTful Web Services in Java that provides support for <a href="http://jax-rs-spec.java.net/">JAX-RS</a> APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation.<br />
<br />
Jersey framework is more than the JAX-RS Reference Implementation. Jersey provides it’s own <a href="https://jersey.java.net/apidocs/latest/jersey/">API</a> that extend the JAX-RS toolkit with additional features and utilities to further simplify RESTful service and client development. Jersey also exposes numerous extension SPIs so that developers may extend Jersey to best suit their needs. </blockquote>
Today I would like to introduce Tracing support feature that is part of Jersey 2 <a href="https://jersey.java.net/release-notes/2.3.html">since 2.3 release</a>. Current version of writing this blog post is 2.4.1.<br />
<br />
<h2>
Tracing Support</h2>
Jersey can provide tracing or diagnostic information about server-side processing of individual requests. This facility may provide vital information when troubleshooting your misbehaving Jersey or JAX-RS application. When enabled, Jersey tracing facility collects useful information from all parts of JAX-RS server-side request processing pipeline: <span style="font-family: Courier New, Courier, monospace;">PreMatchRequestFilter</span>, <span style="font-family: Courier New, Courier, monospace;">ResourceMatching</span>, <span style="font-family: Courier New, Courier, monospace;">RequestFilter</span>, <span style="font-family: Courier New, Courier, monospace;">ReadIntercept</span>, <span style="font-family: Courier New, Courier, monospace;">MBR</span>, <span style="font-family: Courier New, Courier, monospace;">Invoke</span>, <span style="font-family: Courier New, Courier, monospace;">ResponseFilter</span>, <span style="font-family: Courier New, Courier, monospace;">WriteIntercept</span>, <span style="font-family: Courier New, Courier, monospace;">MBW</span>, as well as <span style="font-family: Courier New, Courier, monospace;">ExceptionHandling</span>.<br />
<br />
The collected tracing information related to a single request is returned to the requesting client in the HTTP headers of a response for the request. The information is also logged on the server-side using a dedicated Java Logger instance.<br />
<br />
<h3>
Configuration options</h3>
<br />
Tracing support is disabled by default. You can enable it either "globally" for all application requests or selectively per request. The tracing support activation is controlled by setting the <span style="font-family: Courier New, Courier, monospace;">jersey.config.server.tracing</span> application configuration property (<a href="https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/server/ServerProperties.html#TRACING">ServerProperties.TRACING</a>). The property value is expected to be one of the following:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">OFF</span> - tracing support is disabled (default value).</li>
<li><span style="font-family: Courier New, Courier, monospace;">ON_DEMAND</span> - tracing support is in a stand-by mode; it is enabled selectively per request, via a special <span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Accept</span> HTTP request header.</li>
<li><span style="font-family: Courier New, Courier, monospace;">ALL</span> - tracing support is enabled for all request.</li>
</ul>
<br />
The level of detail of the information provided by Jersey tracing facility - the tracing threshold - can be customized. The tracing threshold can be set at the application level via <span style="font-family: Courier New, Courier, monospace;">jersey.config.server.tracing.threshold</span> application configuration property (<a href="https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/server/ServerProperties.html#TRACING_THRESHOLD">ServerProperties.TRACING_THRESHOLD</a>), or at a request level, via <span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Threshold</span> HTTP request header. The request level configuration overrides any application level setting. There are 3 supported levels of detail for Jersey tracing:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">SUMMARY</span> - very basic summary information about the main request processing stages.</li>
<li><span style="font-family: Courier New, Courier, monospace;">TRACE</span> - detailed information about activities in all the main request processing stages (default threshold value).</li>
<li><span style="font-family: Courier New, Courier, monospace;">VERBOSE</span> - most verbose mode that provides extended information similar to <span style="font-family: Courier New, Courier, monospace;">TRACE</span> level, however with details on entity providers (<span style="font-family: Courier New, Courier, monospace;">MBR</span>/<span style="font-family: Courier New, Courier, monospace;">MBW</span>) that were skipped during the provider selection phase for any reason (lower priority, pattern matching, etc). Additionally, in this mode all received request headers are echoed as part of the tracing information.</li>
</ul>
Both properties accept <span style="font-family: Courier New, Courier, monospace;">String</span> value only.<br />
<br />
<h3>
Tracing Log</h3>
<br />
As mentioned earlier, all tracing information is also logged using a dedicated Java Logger at server-side. The individual tracing messages are logged immediately as the tracing events occur. The default name of the tracing logger is prefixed <span style="font-family: Courier New, Courier, monospace;">org.glassfish.jersey.tracing.</span> with a default suffix <span style="font-family: Courier New, Courier, monospace;">general</span>. This logger name can be customized per request by including a <span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Logger</span> HTTP request header as will be shown later.<br />
<br />
<h3>
Configuring tracing support via HTTP request headers</h3>
<br />
Whenever the tracing support is active (<span style="font-family: Courier New, Courier, monospace;">ON_DEMAND</span> or <span style="font-family: Courier New, Courier, monospace;">ALL</span>) you can customize the tracing behaviour by including one or more of the following request HTTP headers in your individual requests:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Accept</span> - used to enable the tracing support for the particular request. It is applied only when the application-level tracing support is configured to <span style="font-family: Courier New, Courier, monospace;">ON_DEMAND</span> mode. The value of the header is not used by the Jersey tracing facility and as such it can be any arbitrary (even empty) string.</li>
<li><span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Threshold</span> - used to override the tracing level of detail. Allowed values are: <span style="font-family: Courier New, Courier, monospace;">SUMMARY</span>, <span style="font-family: Courier New, Courier, monospace;">TRACE</span>, <span style="font-family: Courier New, Courier, monospace;">VERBOSE</span>.</li>
<li><span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-Logger</span> - used to override the tracing Java logger name suffix.</li>
</ul>
<br />
<h3>
Format of the HTTP response headers</h3>
<br />
At the end of request processing all tracing messages are appended to the HTTP response as individual headers named <span style="font-family: Courier New, Courier, monospace;">X-Jersey-Tracing-<i>nnn</i></span> where <span style="font-family: Courier New, Courier, monospace;"><i>nnn</i></span> is index number of message starting at <span style="font-family: Courier New, Courier, monospace;">0</span>.<br />
<br />
Each tracing message is in the following format: <span style="font-family: Courier New, Courier, monospace;">CATEGORY [TIME] TEXT</span>, e.g.<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-007: WI [85.95 / 183.69 ms | 46.77 %] WriteTo summary: 4 interceptors</span><br />
<br />
The <span style="font-family: Courier New, Courier, monospace;">CATEGORY</span> is used to categorize tracing events according to the following event types:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">START</span> - start of request processing information</li>
<li><span style="font-family: Courier New, Courier, monospace;">PRE-MATCH</span> - pre-matching request filter processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH</span> - matching request URI to a resource method</li>
<li><span style="font-family: Courier New, Courier, monospace;">REQ-FILTER</span> - request filter processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">RI</span> - entity reader interceptor processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR</span> - message body reader selection and invocation</li>
<li><span style="font-family: Courier New, Courier, monospace;">INVOKE</span> - resource method invocation</li>
<li><span style="font-family: Courier New, Courier, monospace;">RESP-FILTER</span> - response filter processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">WI</span> - write interceptor processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW</span> - message body writer selection and invocation</li>
<li><span style="font-family: Courier New, Courier, monospace;">MVC</span> - template engine integration</li>
<li><span style="font-family: Courier New, Courier, monospace;">EXCEPTION</span> - exception mapping</li>
<li><span style="font-family: Courier New, Courier, monospace;">FINISHED</span> - processing finish summary</li>
</ul>
<br />
The <span style="font-family: Courier New, Courier, monospace;">TIME</span>, if present, is a composite value that consists of 3 parts <span style="font-family: Courier New, Courier, monospace;">[ duration / time_from_start | total_req_ratio ]</span>:<br />
<ol>
<li><span style="font-family: Courier New, Courier, monospace;">duration</span> - the duration of the current trace event [milliseconds]; e.g. duration of filter processing</li>
<li><span style="font-family: Courier New, Courier, monospace;">time_from_start</span> - the end time of the current event with respect to the request processing start time [milliseconds]</li>
<li><span style="font-family: Courier New, Courier, monospace;">total_req_ratio</span> - the duration of the current event with respect to the total request processing time [percentage]; this value tells you how significant part of the whole request processing time has been spent in the processing phase described by the current event</li>
</ol>
<br />
There are certain tracing events that do not have any duration. In such case, duration values are not set (<span style="font-family: Courier New, Courier, monospace;">----</span> literal).<br />
<br />
The tracing event <span style="font-family: Courier New, Courier, monospace;">TEXT</span> is a free-form detailed text information about the current diagnostic event.<br />
<blockquote class="tr_bq">
For better identification, instances of JAX-RS components are represented by class name, identity hash code and <span style="font-family: Courier New, Courier, monospace;">@Priority</span> value if set, example of filter instance with priority 5001: <span style="font-family: Courier New, Courier, monospace;">[org.glassfish.jersey.tests.integration.tracing.ContainerResponseFilter5001 @494a8227 #5001]</span>.</blockquote>
<br />
<h3>
Tracing Examples</h3>
<h3>
<br /></h3>
<h4>
Threshold header, SUMMARY level example</h4>
<br />
Example of <span style="font-family: Courier New, Courier, monospace;">SUMMARY</span> level messages from <span style="font-family: Courier New, Courier, monospace;">tests/integration/tracing-support</span> module. Test application returns tracing headers for every request (<a href="https://github.com/jersey/jersey/blob/master/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/AllTracingSupport.java#L53">AllTracingSupport.java</a>, <a href="https://github.com/jersey/jersey/blob/master/tests/integration/tracing-support/src/main/java/org/glassfish/jersey/tests/integration/tracing/TracingSupport.java#L53">TracingSupport.java</a>).<br />
<br />
Run test application using Jetty server:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">~/jersey2/tests/integration/<b>tracing-support</b>$ <b>mvn compile jetty:run</b></span><br />
<br />
Let's trace <span style="font-family: Courier New, Courier, monospace;">POST</span> request with <span style="font-family: Courier New, Courier, monospace;">SUMMARY</span> level using "<span style="font-family: Courier New, Courier, monospace;">Threshold</span>" header (replacing default <span style="font-family: Courier New, Courier, monospace;">TRACE</span> level):<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$ curl -i http://localhost:9998/ALL/root/sub-resource-locator/sub-resource-method -H content-type:application/x-jersey-test --data '-=#[LKR]#=-' -H <b>X-Jersey-Tracing-Threshold:SUMMARY</b> -H accept:application/x-jersey-test -X POST</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span>
<span style="font-family: 'Courier New', Courier, monospace;"><span style="font-size: x-small;">X-Jersey-Tracing-000: <b>START</b> [ ---- / ---- ms | ---- %] baseUri=[http://localhost:9998/ALL/] requestUri=[http://localhost:9998/ALL/root/sub-resource-locator/sub-resource-method] method=[POST] authScheme=[n/a] accept=[application/x-jersey-test] accept-encoding=n/a accept-charset=n/a accept-language=n/a content-type=[application/x-jersey-test] content-length=[11]</span></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-001: <b>PRE-MATCH</b> [ 0.01 / 0.68 ms | 0.01 %] PreMatchRequest summary: 2 filters</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-002: <b>MATCH</b> [ 8.44 / 9.15 ms | 4.59 %] RequestMatching summary</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-003: <b>REQ-FILTER</b> [ 0.01 / 9.20 ms | 0.00 %] Request summary: 2 filters</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-004: <b>RI</b> [86.14 / 95.49 ms | 46.87 %] ReadFrom summary: 3 interceptors</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-005: <b>INVOKE</b> [ 0.04 / 95.70 ms | 0.02 %] Resource [org.glassfish.jersey.tests.integration.tracing.SubResource @901a4f3] method=[public org.glassfish.jersey.tests.integration.tracing.Message org.glassfish.jersey.tests.integration.tracing.SubResource.postSub(org.glassfish.jersey.tests.integration.tracing.Message)]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-006: <b>RESP-FILTER</b> [ 0.01 / 96.55 ms | 0.00 %] Response summary: 2 filters</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-007: <b>WI</b> [85.95 / 183.69 ms | 46.77 %] WriteTo summary: 4 interceptors</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-008: <b>FINISHED</b> [ ---- / 183.79 ms | ---- %] Response status: 200/SUCCESSFUL|OK</span><br />
<br />
<h4>
Accept header, MVC integration, TRACE level example</h4>
<br />
Second example shows MVC message (from <span style="font-family: Courier New, Courier, monospace;">jersey-mvc-jsp</span> integration module) using <span style="font-family: Courier New, Courier, monospace;">examples/bookstore-webapp</span> module.<br />
<br />
Run test application using Jetty server:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">~/jersey2/examples/<b>bookstore-webapp</b>$ <b>mvn compile jetty:run</b></span><br />
<br />
Let's trace <span style="font-family: Courier New, Courier, monospace;">GET</span> request using "<span style="font-family: Courier New, Courier, monospace;">Accept</span>" header to activate on-demand tracing support messages (<a href="https://github.com/jersey/jersey/blob/master/examples/bookstore-webapp/src/main/java/org/glassfish/jersey/examples/bookstore/webapp/MyApplication.java#L66">MyApplication.java</a>). This is just snippet of default TRACE level messages to demonstrate MVC JSP forwarding message:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$ curl -i http://localhost:9998/items/3/tracks/0 -H <b>X-Jersey-Tracing-Accept:<i>whatever</i></b></span><br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">...</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-033: WI [ 0.00 / 23.39 ms | 0.02 %] [org.glassfish.jersey.server.mvc.internal.TemplateMethodInterceptor @141bcd49 #4000] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-034: WI [ 0.01 / 23.42 ms | 0.02 %] [org.glassfish.jersey.filter.LoggingFilter @2d427def #-2147483648] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-035: MBW [ ---- / 23.45 ms | ---- %] Find MBW for type=[org.glassfish.jersey.server.mvc.internal.ImplicitViewable] genericType=[org.glassfish.jersey.server.mvc.internal.ImplicitViewable] mediaType=[[javax.ws.rs.core.MediaType @7bfbfeae]] annotations=[]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-036: MBW [ ---- / 23.52 ms | ---- %] [org.glassfish.jersey.server.mvc.internal.ViewableMessageBodyWriter @78b353d4] IS writeable</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-037: <b>MVC</b> [ ---- / 24.05 ms | ---- %] Forwarding view to JSP page [/org/glassfish/jersey/examples/bookstore/webapp/resource/Track/index.jsp], model [org.glassfish.jersey.examples.bookstore.webapp.resource.Track @3937f594]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-038: MBW [ 1.09 / 24.63 ms | 4.39 %] WriteTo by [org.glassfish.jersey.server.mvc.internal.ViewableMessageBodyWriter @78b353d4]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-039: WI [ 0.00 / 24.67 ms | 0.01 %] [org.glassfish.jersey.filter.LoggingFilter @2d427def #-2147483648] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-040: WI [ 0.00 / 24.70 ms | 0.01 %] [org.glassfish.jersey.server.mvc.internal.TemplateMethodInterceptor @141bcd49 #4000] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">...</span><br />
<br />
<h4>
Logger header, VERBOSE level example</h4>
<br />
The last example shows JDK logger name configuration and also uses <span style="font-family: Courier New, Courier, monospace;">tests/integration/tracing-support</span> module.<br />
<br />
Run test application using Jetty server with JDK logger config file set (JDK logging configuration from file works just on Java 7):<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">~/jersey2/tests/integration/<b>tracing-support</b>$ <b>mvn compile jetty:run</b></span><b style="font-family: 'Courier New', Courier, monospace; font-size: small;"> -Djava.util.logging.config.file=src/test/resources/logging.properties</b><br />
<br />
Let's trace <span style="font-family: Courier New, Courier, monospace;">POST</span> request with <span style="font-family: Courier New, Courier, monospace;">VERBOSE</span> level using "<span style="font-family: Courier New, Courier, monospace;">Threshold</span>" header and customize server-side logger name (suffix "<span style="font-family: Courier New, Courier, monospace;">lkr</span>") using "<span style="font-family: Courier New, Courier, monospace;">Logger</span>" header:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">$ curl -i http://localhost:9998/ALL/root/sub-resource-locator/sub-resource-method -H content-type:application/x-jersey-test --data '-=#[LKR]#=-' -H <b>X-Jersey-Tracing-Threshold:VERBOSE</b> -H <b>X-Jersey-Tracing-Logger:lkr</b> -H accept:application/x-jersey-test -X POST</span><br />
<br />
Snippet of response Tracing headers, see "skipped" messages available just with <span style="font-family: Courier New, Courier, monospace;">VERBOSE</span> level:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-055: <b>WI</b> [ 0.01 / 110.41 ms | 0.00 %] [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @25f3027c #10] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-056: <b>WI</b> [43.14 / 153.76 ms | 21.66 %] [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor39 @19378d8d #39] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-057: <b>WI</b> [ 0.02 / 154.15 ms | 0.01 %] [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor45 @e2e30ea #45] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-058: <b>WI</b> [ 0.01 / 154.49 ms | 0.01 %] [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @7a8d59eb #3000] BEFORE context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-059: <b>MBW</b> [ ---- / 154.72 ms | ---- %] Find MBW for type=[org.glassfish.jersey.tests.integration.tracing.Message] genericType=[org.glassfish.jersey.tests.integration.tracing.Message] mediaType=[[org.glassfish.jersey.message.internal.AcceptableMediaType @77d470a6]] annotations=[@javax.ws.rs.Path(value=sub-resource-method), @javax.ws.rs.POST()]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-060: <b>MBW</b> [ ---- / 154.95 ms | ---- %] [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterTestFormat @2b40fbd9] IS writeable</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-061: <b>MBW</b> [ ---- / 155.14 ms | ---- %] [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterGeneric @375679be] <b>is skipped</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-062: <b>MBW</b> [ ---- / 155.28 ms | ---- %] [org.glassfish.jersey.message.internal.XmlCollectionJaxbProvider$General @4e0919d8] <b>is skipped</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-063: <b>MBW</b> [ ---- / 155.42 ms | ---- %] [org.glassfish.jersey.message.internal.XmlRootElementJaxbProvider$General @683ca3a4] <b>is skipped</b></span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-064: <b>MBW</b> [ 0.03 / 155.58 ms | 0.01 %] WriteTo by [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterTestFormat @2b40fbd9]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-065: <b>WI</b> [ 0.00 / 155.77 ms | 0.00 %] [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @7a8d59eb #3000] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-066: <b>WI</b> [42.11 / 198.10 ms | 21.15 %] [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor45 @e2e30ea #45] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-067: <b>WI</b> [ 0.01 / 198.48 ms | 0.01 %] [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor39 @19378d8d #39] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-068: <b>WI</b> [ 0.00 / 198.72 ms | 0.00 %] [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @25f3027c #10] AFTER context.proceed()</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">X-Jersey-Tracing-069: <b>WI</b> [88.53 / 198.93 ms | 44.46 %] WriteTo summary: 4 interceptors</span><br />
<br />
And same messages written to server-side log (customized logger name):<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_BEFORE</b> [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @25f3027c #10] BEFORE context.proceed() [ 0.01 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_BEFORE</b> [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor39 @19378d8d #39] BEFORE context.proceed() [43.14 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_BEFORE</b> [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor45 @e2e30ea #45] BEFORE context.proceed() [ 0.02 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_BEFORE</b> [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @7a8d59eb #3000] BEFORE context.proceed() [ 0.01 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_FIND</b> Find MBW for type=[org.glassfish.jersey.tests.integration.tracing.Message] genericType=[org.glassfish.jersey.tests.integration.tracing.Message] mediaType=[[org.glassfish.jersey.message.internal.AcceptableMediaType @77d470a6]] annotations=[@javax.ws.rs.Path(value=sub-resource-method), @javax.ws.rs.POST()] [ ---- ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_SELECTED</b> [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterTestFormat @2b40fbd9] IS writeable [ ---- ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINEST</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_SKIPPED</b> [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterGeneric @375679be] is skipped [ ---- ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINEST</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_SKIPPED</b> [org.glassfish.jersey.message.internal.XmlCollectionJaxbProvider$General @4e0919d8] is skipped [ ---- ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINEST</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_SKIPPED</b> [org.glassfish.jersey.message.internal.XmlRootElementJaxbProvider$General @683ca3a4] is skipped [ ---- ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>MBW_WRITE_TO</b> WriteTo by [org.glassfish.jersey.tests.integration.tracing.MessageBodyWriterTestFormat @2b40fbd9] [ 0.03 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_AFTER</b> [org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor @7a8d59eb #3000] AFTER context.proceed() [ 0.00 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_AFTER</b> [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor45 @e2e30ea #45] AFTER context.proceed() [42.11 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_AFTER</b> [org.glassfish.jersey.tests.integration.tracing.WriterInterceptor39 @19378d8d #39] AFTER context.proceed() [ 0.01 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINER</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_AFTER</b> [org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor @25f3027c #10] AFTER context.proceed() [ 0.00 ms]</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>FINE</b> [org.glassfish.jersey.tracing.<b>lkr</b>] <b>WI_SUMMARY</b> WriteTo summary: 4 interceptors [88.53 ms]</span><br />
<br />
You can see some differences. There is just <span style="font-family: Courier New, Courier, monospace;">duration</span> value (if applicable), no <span style="font-family: Courier New, Courier, monospace;">time_from_start</span> or <span style="font-family: Courier New, Courier, monospace;">total_req_ratio</span>.<br />
<br />
Message tracing level is transformed to JDK logging level:<br />
<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">SUMMARY -> FINE</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">TRACE -> FINER</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">VERBOSE -> FINEST</span></li>
</ul>
<br />
Each message type has unique ID transformed to message category while formatting HTTP response headers:<br />
<ul>
<li><span style="font-family: Courier New, Courier, monospace;">START -> START</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">START_HEADERS -> START</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">PRE_MATCH -> PRE-MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">PRE_MATCH_SUMMARY -> PRE-MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_PATH_FIND -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_PATH_NOT_MATCHED -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_PATH_SELECTED -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_PATH_SKIPPED -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_LOCATOR -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_RESOURCE_METHOD -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_RUNTIME_RESOURCE -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_RESOURCE -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MATCH_SUMMARY -> MATCH</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">REQUEST_FILTER -> REQ-FILTER</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">REQUEST_FILTER_SUMMARY -> REQ-FILTER</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">METHOD_INVOKE -> INVOKE</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">DISPATCH_RESPONSE -> INVOKE</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">RESPONSE_FILTER -> RESP-FILTER</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">RESPONSE_FILTER_SUMMARY -> RESP-FILTER</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">FINISHED -> FINISHED</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">EXCEPTION_MAPPING -> EXCEPTION</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">RI_BEFORE -> RI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">RI_AFTER -> RI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">RI_SUMMARY -> RI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR_FIND -> MBR</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR_NOT_READABLE -> MBR</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR_SELECTED -> MBR</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR_SKIPPED -> MBR</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBR_READ_FROM -> MBR</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW_FIND -> MBW</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW_NOT_WRITEABLE -> MBW</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW_SELECTED -> MBW</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW_SKIPPED -> MBW</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">MBW_WRITE_TO -> MBW</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">WI_BEFORE -> WI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">WI_AFTER -> WI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">WI_SUMMARY -> WI</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">JSP_FORWARD -> MVC</span></li>
</ul>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<h2>
Feedback</h2>
This is extended version of user guide capture <a href="https://jersey.java.net/documentation/latest/monitoring_tracing.html#tracing">Tracing Support</a>. I am looking forward to your comments bellow the post. You can also use Jersey <a href="https://jersey.java.net/mailing.html">mailing lists</a>. Don't hesitate to report any bugs, feature, and/or improvement requests in Jersey <a href="http://java.net/jira/browse/JERSEY">JIRA</a> issue tracker.<br />
<br />
Thanks,<br />
-lk<br />
<br />Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com10tag:blogger.com,1999:blog-2759548145050416517.post-21510271379553846232012-03-31T01:15:00.001+02:002012-03-31T15:46:13.844+02:00Methods in a Java interface with or without public access modifierZlobím se na tvůrce jazyka <b>Java</b>, že v případě <b>interface</b> je modifikátor <b>public</b> u metod nepovinný. :o
<br />
<br />
Moc děkuji tvůrcům jazyka Java, že vytvořili velmi přehledný jazyk, jehož součástí je i jmenná konvence, která podporuje dlouhé názvy a "potlačuje" zkratkovitost v zápisu kódu.<br />
<br />
<b>Jsem přesvědčen, že Sun udělal chybu a public u metod interfacu měl být povinný.</b> Jak je někde volba, tak zákonitě vznikají 2 nesmiřitelné tábory. Jeden tvrdí, že redundantní informace má být potlačena. Druzí jsou přesvědčeni o poctivosti plného zápisu a explicitním potvrzení, že i metoda interfacu je veřejná.<br />
<br />
Jistě jste pochopili, že já patřím k té druhé skupině. Mám rád čitelný kód. Nejsem líný napsat více znaků pokud jsem přesvědčen, že to přispěje k přehlednosti zdrojáku. Do této kategorie spadá i deklarace public metod interfacu. <b>Na variantě první mi vadí, že deklarace viditelnosti metody je kontextově závislá - default je u třídy jiný než u rozhraní a to mi nevyhovuje.</b> Podpůrný argument, proč public uvádět i u interfaců je migrace interface na abstraktní třídu a už musíte modifikátory doplňovat.<br />
<br />
Mnohem víc je ale pro mě důležité, aby celý tým dodržoval stejné konvence. Kód by měl vypadat podobně a všichni by s konvencemi měli souhlasit. A v tomto případě asi budu muset ustoupit ze své pravdy, protože se zdá, že <b>většina javovské populace preferuje klíčové slovo public nepsat</b>. A co se teda zlobím na kluky ze Sunu, že přímo v <b>The Java™ Language Specification</b> (JSL) doporučují redundantní public nepoužívat: <i>It is permitted, but strongly discouraged as a matter of style, to redundantly specify the public modifier for interface methods.</i><br />
<br />
Je to teda ústupek na úkor čitelnosti kódu, což je jen škoda pro začínající a poctivé programátory. :P (Omlouvám se za malou demagogii.)<br />
<br />
<b>Najde se vůbec někdo, kdo stejně jako já preferuje tu ukecanější variantu?</b><br />
<br />
Odkazy:<br />
<br />
<ul>
<li><b>JSL</b> - <a href="http://docs.oracle.com/javase/specs/jls/se5.0/html/interfaces.html#9.4">http://docs.oracle.com/javase/specs/jls/se5.0/html/interfaces.html#9.4</a></li>
<li><b>Stack Overflow</b> - <a href="http://stackoverflow.com/questions/161633/methods-in-a-java-interface-with-or-without-public-access-modifier">http://stackoverflow.com/questions/161633/methods-in-a-java-interface-with-or-without-public-access-modifier</a></li>
</ul>
<div>
<br /></div>
<div>
<br /></div>
<iframe frameborder="0" height="552" marginheight="0" marginwidth="0" src="https://docs.google.com/spreadsheet/embeddedform?formkey=dE11cDZBMkhSenVjOXhTQ0g3SG43S2c6MQ" width="640">&amp;lt;p&amp;gt;&amp;amp;amp;amp;amp;lt;p&amp;amp;amp;amp;amp;gt;Načítání...&amp;amp;amp;amp;amp;lt;/p&amp;amp;amp;amp;amp;gt;&amp;lt;/p&amp;gt;</iframe>Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com0tag:blogger.com,1999:blog-2759548145050416517.post-36993379952175807252011-01-23T12:06:00.000+01:002011-12-14T23:03:30.317+01:00Java Double QuizPro kolegy jsem si připravil krátký kvíz na datový typ <b>double</b> v jazyce <b>Java</b>. Věřím, že pobaví i vás.<br />
<br />
<iframe src="https://spreadsheets.google.com/embeddedform?formkey=dDg1MU9ucTRXX2h0OTRTWHJVdUxNdFE6MQ" width="650" height="813" frameborder="0" marginheight="0" marginwidth="0">Loading...</iframe><br />
<br />
<i>Dotazník byl vytvořen pomocí <b>Google Docs</b>, takže vaše odpovědi pod článkem nehledejte. Těším se na diskuzi pod článkem.</i>Anonymoushttp://www.blogger.com/profile/16418949627188312916noreply@blogger.com14