Congratulations!

[Valid RSS] This is a valid RSS feed.

Recommendations

This feed is valid, but interoperability with the widest range of feed readers could be improved by implementing the following recommendations.

Source: http://hasselba.ch/blog/?feed=rss2

  1. <?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
  2. xmlns:content="http://purl.org/rss/1.0/modules/content/"
  3. xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  4. xmlns:dc="http://purl.org/dc/elements/1.1/"
  5. xmlns:atom="http://www.w3.org/2005/Atom"
  6. xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  7. xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  8. >
  9.  
  10. <channel>
  11. <title>[email protected]</title>
  12. <atom:link href="http://hasselba.ch/blog/?feed=rss2" rel="self" type="application/rss+xml" />
  13. <link>http://hasselba.ch/blog</link>
  14. <description></description>
  15. <lastBuildDate>Thu, 16 Mar 2017 20:53:42 +0000</lastBuildDate>
  16. <language>de-DE</language>
  17. <sy:updatePeriod>hourly</sy:updatePeriod>
  18. <sy:updateFrequency>1</sy:updateFrequency>
  19. <generator>https://wordpress.org/?v=4.7.3</generator>
  20. <item>
  21. <title>Re: Domino REST performance analysis</title>
  22. <link>http://hasselba.ch/blog/?p=2364</link>
  23. <comments>http://hasselba.ch/blog/?p=2364#comments</comments>
  24. <pubDate>Thu, 16 Mar 2017 20:51:54 +0000</pubDate>
  25. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  26. <category><![CDATA[REST]]></category>
  27. <category><![CDATA[Domino]]></category>
  28. <category><![CDATA[Performance]]></category>
  29. <category><![CDATA[Web]]></category>
  30.  
  31. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2364</guid>
  32. <description><![CDATA[I have created a Quick-n-Dirty performance test for Csaba&#8217;s &#8222;10K record test&#8220;: Loading time 200 ms overall, 60 ms TTFB. Do you want to know how this works? Feel free to come to SNoUG next week or to Rudi&#8217;s EntwicklerCamp and &#8230; <a href="http://hasselba.ch/blog/?p=2364">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  33. <content:encoded><![CDATA[<p>I have created a Quick-n-Dirty performance test for <a href="http://xpagexplorer.org/domino-rest-performance-analysis/" target="_blank">Csaba&#8217;s &#8222;10K record test&#8220;</a>:</p>
  34. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox.png"><img class="alignnone size-full wp-image-2365" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox.png" alt="" width="1361" height="369" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox.png 1361w, http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox-300x81.png 300w, http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox-768x208.png 768w, http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-16-21_36_54-Mozilla-Firefox-1024x278.png 1024w" sizes="(max-width: 1361px) 100vw, 1361px" /></a></p>
  35. <p>Loading time 200 ms overall, 60 ms TTFB.</p>
  36. <p>Do you want to know how this works? Feel free to come to <a href="http://snoug.ch/SNOUG/webX-New.nsf/home.xsp" target="_blank">SNoUG</a> next week or to Rudi&#8217;s <a href="http://entwicklercamp.de/" target="_blank">EntwicklerCamp</a> and join my sessions about &#8222;High Performance REST Applications&#8220;.</p>
  37. ]]></content:encoded>
  38. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2364</wfw:commentRss>
  39. <slash:comments>6</slash:comments>
  40. </item>
  41. <item>
  42. <title>Domino &#038; Java 1.8: Thank you, IBM!</title>
  43. <link>http://hasselba.ch/blog/?p=2353</link>
  44. <comments>http://hasselba.ch/blog/?p=2353#respond</comments>
  45. <pubDate>Tue, 14 Mar 2017 13:16:13 +0000</pubDate>
  46. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  47. <category><![CDATA[Java]]></category>
  48. <category><![CDATA[Domino]]></category>
  49. <category><![CDATA[FP 8]]></category>
  50. <category><![CDATA[Java 8]]></category>
  51. <category><![CDATA[Maven]]></category>
  52.  
  53. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2353</guid>
  54. <description><![CDATA[For years it was a lot of pain when developing for the Domino platform using Java 1.6 only. But now, Java 1.8 is available, and this allows to use the latest versions for a lot of libraries and development tools. &#8230; <a href="http://hasselba.ch/blog/?p=2353">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  55. <content:encoded><![CDATA[<p>For years it was a lot of pain when developing for the Domino platform using Java 1.6 only. But now, Java 1.8 is available, and this allows to use the latest versions for a lot of libraries and development tools.</p>
  56. <p>After installing FP8 to the Client, Eclipse allowes to use the Domino JRE in a JavaSE-1.8 environment:</p>
  57. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/JRE18.png"><img class="alignnone size-full wp-image-2356" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/JRE18.png" alt="" width="824" height="556" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/JRE18.png 824w, http://hasselba.ch/blog/wp-content/uploads/2017/03/JRE18-300x202.png 300w, http://hasselba.ch/blog/wp-content/uploads/2017/03/JRE18-768x518.png 768w" sizes="(max-width: 824px) 100vw, 824px" /></a></p>
  58. <p>This gives access to the latest <a href="https://www.eclipse.org/m2e/" target="_blank">M2Eclipse plugin (1.7.0)</a>. The old version problem when running with JRE 1.6&#8230;</p>
  59. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16.png"><img class="alignnone size-full wp-image-2357" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16.png" alt="" width="1113" height="277" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16.png 1113w, http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16-300x75.png 300w, http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16-768x191.png 768w, http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE16-1024x255.png 1024w" sizes="(max-width: 1113px) 100vw, 1113px" /></a>&#8230; is solved:</p>
  60. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE18.png"><img class="alignnone size-full wp-image-2358" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE18.png" alt="" width="678" height="255" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE18.png 678w, http://hasselba.ch/blog/wp-content/uploads/2017/03/MavenJRE18-300x113.png 300w" sizes="(max-width: 678px) 100vw, 678px" /></a></p>
  61. <p>Eclipse Updates? No problem, just do it!</p>
  62. <p>Latest Java features like switch statement with Strings? Here we go:</p>
  63. <pre><code>String token = "FOO";
  64. switch(token) {
  65.    case "FOO": return (T) Foo.class;
  66.    case "BAR": return (T) Bar.class;
  67. }</code></pre>
  68. <p>Third party libraries like Jackson 2.8.0? Works like a charm!</p>
  69. <p>Thank you, IBM!</p>
  70. ]]></content:encoded>
  71. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2353</wfw:commentRss>
  72. <slash:comments>0</slash:comments>
  73. </item>
  74. <item>
  75. <title>Domino &#038; REST: Debug your Plugin</title>
  76. <link>http://hasselba.ch/blog/?p=2326</link>
  77. <comments>http://hasselba.ch/blog/?p=2326#respond</comments>
  78. <pubDate>Tue, 07 Mar 2017 11:14:02 +0000</pubDate>
  79. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  80. <category><![CDATA[Jackson]]></category>
  81. <category><![CDATA[Java]]></category>
  82. <category><![CDATA[JEE]]></category>
  83. <category><![CDATA[OSGi]]></category>
  84. <category><![CDATA[REST]]></category>
  85. <category><![CDATA[Apache Wink]]></category>
  86. <category><![CDATA[Domino]]></category>
  87. <category><![CDATA[Server]]></category>
  88.  
  89. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2326</guid>
  90. <description><![CDATA[When developing OSGi Plugins, you should have your own development server running on your local machine. Not only because of the faster deployment of changes (a new version of a plugin must always deployed with a HTTP restart), but because &#8230; <a href="http://hasselba.ch/blog/?p=2326">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  91. <content:encoded><![CDATA[<p>When developing OSGi Plugins, you should have your own development server running on your local machine. Not only because of the faster deployment of changes (a new version of a plugin must always deployed with a HTTP restart), but because of the Java debugging posibilities: Only one Eclipse instance can connect to the JVM, and every request processed by the server will start the debugger. If multiple users a accessing the server while you are debugging, your Eclipse will try to debug every incoming request, and this can lead into a confusing situation for all.</p>
  92. <p>To enable debugging, you first have to add two parameters to the <em>notes.ini</em>:</p>
  93. <pre><code>JavaEnableDebug=1
  94. JavaDebugOptions=transport=dt_socket,server=y,suspend=n,address=8000</code></pre>
  95. <p>This starts the debugging on port 8000. Feel free to change the value to every port you want. Because of security reasons you should not start debugging on a productive machine.</p>
  96. <p>After restarting the domino server, you can connect to the JVM in your Eclipse IDE by creating a new JVM remote debugging session. Create a new debug configuration&#8230;</p>
  97. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_44_17-Java-Eclipse.png"><img class="alignnone size-full wp-image-2337" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_44_17-Java-Eclipse.png" alt="" width="270" height="133" /></a></p>
  98. <p>&#8230; choose (1) &#8222;<em>Remote Java Application</em>&#8222;, (2) give a name to it, (3) select the plugin project, (4) enter the port the server listens, and click on (5) &#8222;<em>Apply</em>&#8222;.</p>
  99. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_53_30-Java-Eclipse-1.png"><img class="alignnone size-full wp-image-2340" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_53_30-Java-Eclipse-1.png" alt="" width="862" height="537" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_53_30-Java-Eclipse-1.png 862w, http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_53_30-Java-Eclipse-1-300x187.png 300w, http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_53_30-Java-Eclipse-1-768x478.png 768w" sizes="(max-width: 862px) 100vw, 862px" /></a></p>
  100. <p>If you want to connect to your server, you need to start debugging by clicking on the project:</p>
  101. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_36_02-Java-Eclipse.png"><img class="alignnone size-full wp-image-2341" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/2017-03-06-09_36_02-Java-Eclipse.png" alt="" width="221" height="129" /></a></p>
  102. <p>After setting a breakpoint and sending a request to the servlet, Eclipse switches to the Debug perspective where you can look what happens with your servlet.</p>
  103. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/03/Eclipse-debugger.png"><img class="alignnone size-full wp-image-2344" src="http://hasselba.ch/blog/wp-content/uploads/2017/03/Eclipse-debugger.png" alt="" width="491" height="485" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/03/Eclipse-debugger.png 491w, http://hasselba.ch/blog/wp-content/uploads/2017/03/Eclipse-debugger-300x296.png 300w" sizes="(max-width: 491px) 100vw, 491px" /></a></p>
  104. <p>Sometimes you are connecting to the &#8222;wrong&#8220; JVM, because a Java agent is running and/or a DOTS task does it&#8217;s job. It&#8217;s better to disable these tasks on your development server.</p>
  105. <p>During debugging you are able to <a href="https://wiki.eclipse.org/FAQ_What_is_hot_code_replace%3F" target="_blank">hotswap your code</a>, but keep in mind that after a restart of the HTTP JVM all your changes are no longer &#8222;installed&#8220;. You have to build a new plugin or replace your code during runtime again.</p>
  106. <p>In the next blog post, let&#8217;s talk about our development tools.</p>
  107. ]]></content:encoded>
  108. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2326</wfw:commentRss>
  109. <slash:comments>0</slash:comments>
  110. </item>
  111. <item>
  112. <title>Domino &#038; REST: More about Jackson</title>
  113. <link>http://hasselba.ch/blog/?p=2297</link>
  114. <comments>http://hasselba.ch/blog/?p=2297#respond</comments>
  115. <pubDate>Fri, 03 Mar 2017 10:16:30 +0000</pubDate>
  116. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  117. <category><![CDATA[Apache Wink]]></category>
  118. <category><![CDATA[Jackson]]></category>
  119. <category><![CDATA[JEE]]></category>
  120. <category><![CDATA[REST]]></category>
  121. <category><![CDATA[Domino]]></category>
  122. <category><![CDATA[Web]]></category>
  123.  
  124. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2297</guid>
  125. <description><![CDATA[When creating a REST API servlet, Jackson provides a huge list of possibilities to manipulate the JSON data, mostly using annotations. Let&#8217;s demonstrate some of them with this little class, which has only two properties: public class Demo { private String foo; &#8230; <a href="http://hasselba.ch/blog/?p=2297">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  126. <content:encoded><![CDATA[<p style="text-align: left;">When creating a REST API servlet, Jackson provides a huge list of possibilities to manipulate the JSON data, mostly using annotations.</p>
  127. <p>Let&#8217;s demonstrate some of them with this little class, which has only two properties:</p>
  128. <pre><code>public class Demo {
  129.  
  130.    private String foo;
  131. </code><code>    private String bar;
  132.  
  133. </code><code>    public String getFoo() {
  134.        return foo;
  135.    }
  136.    public void setFoo(String foo) {
  137.        this.foo = foo;
  138.    }
  139.  
  140. </code><code>    public String getBar() {
  141.        return bar;
  142.    }
  143.  
  144.    public void setBar(String bar) {
  145.        this.bar = bar;
  146.    }</code><code>
  147. }</code></pre>
  148. <p>The playground converts the <em>content</em> string to a POJO and back to a string:</p>
  149. <pre><code>String content = "{ \"foo\": \"bar\" }";
  150. // init the ObjectMapper
  151. ObjectMapper mapper = new ObjectMapper();
  152. // build the Object
  153. Demo test = null;
  154. try {
  155.     test = mapper.readValue(content, Demo.class);
  156. } catch (Exception e) {
  157.     e.printStackTrace();
  158. }
  159.  
  160. // and now convert it back to a String
  161. String data = null;
  162. try {
  163.     data = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(test);
  164. } catch (Exception e) {
  165.     e.printStackTrace();
  166. }
  167.  
  168. System.out.println( data );</code></pre>
  169. <p>If we run this code, the result is not really spectacular:</p>
  170. <pre><code>{
  171. "foo" : "bar",
  172. "bar" : null
  173. }</code></pre>
  174. <p>So let&#8217;s ignore the property foo by adding the annotation <em>@JsonIgnoreProperties</em> to the <em>Demo</em> class:</p>
  175. <pre><code>@JsonIgnoreProperties({"foo"})
  176. public class Demo { ... }</code></pre>
  177. <p>Now, <em>foo</em> is no longer in our resulting JSON:</p>
  178. <pre><code>{
  179.    "bar" : null
  180. }</code></pre>
  181. <p>The property <em>bar</em> is null, and we don&#8217;t like nulled properties in our JSON. That&#8217;s why we add another annotation, <em>@JsonInclude</em>:</p>
  182. <pre><code>@JsonInclude(JsonInclude.Include.NON_EMPTY)
  183. public class Demo { ... }</code></pre>
  184. <p>After removing the previously added <em>@JsonIgnoreProperties</em> annotation, our result looks like this (the empty property <em>bar</em> was skipped):</p>
  185. <pre><code>{
  186.    "foo" : "bar"
  187. }</code></pre>
  188. <p>What happens if we change our <em>content</em> string, and add an unknown property?</p>
  189. <pre><code>String content = "{ \"foo\": \"bar\", \"undefined\": \"property\" }";</code></pre>
  190. <p>An error occurs because Jackson does not know how to handle the new property:</p>
  191. <pre><code>com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "undefined" (class ch.hasselba.JacksonPlayground.Demo), not marked as ignorable (2 known properties: "foo", "bar"])
  192. at [Source: { "foo": "bar", "undefined": "property" }; line: 1, column: 31] (through reference chain: ch.hasselba.JacksonPlayground.Demo["undefined"])
  193. at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:51)
  194. at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:817)
  195. at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:954)
  196. at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1315)
  197. at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1293)
  198. at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:249)
  199. at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
  200. at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3560)
  201. at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2576)
  202. at ch.hasselba.JacksonPlayground.App.main(App.java:24)
  203. null</code></pre>
  204. <p>But there are two annotations to the rescue, <em>@JsonAnyGetter</em> &amp; <em>@JsonAnySetter</em>. By changing our <em>Demo</em> class and adding the following lines of code&#8230;</p>
  205. <pre><code>private Map&lt;String, Object&gt; others = new ConcurrentHashMap&lt;String, Object&gt;();
  206.  
  207. @JsonAnyGetter
  208. public Map&lt;String, Object&gt; getOthers() {
  209.    return this.others;
  210. }
  211.  
  212. @JsonAnySetter
  213. public void addOther(final String name, final Object value) {
  214.    this.others.put(name, value);
  215. }</code></pre>
  216. <p>&#8230; Jackson now puts all the unknown/undefined properties in the <em>others</em> map (uses the method defined by <em>@JsonSetter</em>). And then it uses the method with the <em>@JsonGetter</em> annotation when producing the JSON from the Demo instance.</p>
  217. <pre><code>{
  218.  "foo" : "bar",
  219.  "bar" : null,
  220.  "undefined" : "property"
  221. }
  222. </code></pre>
  223. <p>What if we want to handle multiple &#8222;Demo&#8220; objects in a JSON Array?</p>
  224. <pre><code>String content = "[ { \"foo\": \"bar\" }, {\"foo\": \"bar2\" } ]";</code></pre>
  225. <p>In this case we change our reading routine to work with lists:</p>
  226. <pre><code>// build the Object
  227. List&lt;Demo&gt; test = null;
  228. try {
  229.    test = mapper.readValue(content, mapper.getTypeFactory()
  230.            .constructCollectionType(List.class, Demo.class));
  231. } catch (Exception e) {
  232.    e.printStackTrace();
  233. }</code></pre>
  234. <p>In the result all entries are now contained in the list of <em>Demo</em> objects:</p>
  235. <pre><code>[ {
  236. "foo" : "bar",
  237. "bar" : null
  238. }, {
  239. "foo" : "bar2",
  240. "bar" : null
  241. } ]</code></pre>
  242. <p>Back to our <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/RestApiApplication.java" target="_blank">RestApiApplication</a>, have a look at this line:</p>
  243. <pre><code>objMapper.setSerializationInclusion(Include.NON_EMPTY);</code></pre>
  244. <p>This removes all empty properties globally from the generated output of our the servlet. So there is no need to add the <em>@JsonIgnore</em> annotation to any class. You can modifiy the globally used ObjectMapper in your servlet with multiple option, more will follow in another blog post.</p>
  245. ]]></content:encoded>
  246. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2297</wfw:commentRss>
  247. <slash:comments>0</slash:comments>
  248. </item>
  249. <item>
  250. <title>Domino &#038; REST: Accessing Domino&#8217;s Environment / Check Authentication</title>
  251. <link>http://hasselba.ch/blog/?p=2316</link>
  252. <comments>http://hasselba.ch/blog/?p=2316#comments</comments>
  253. <pubDate>Thu, 02 Mar 2017 11:00:37 +0000</pubDate>
  254. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  255. <category><![CDATA[Apache Wink]]></category>
  256. <category><![CDATA[Jackson]]></category>
  257. <category><![CDATA[Java]]></category>
  258. <category><![CDATA[JEE]]></category>
  259. <category><![CDATA[REST]]></category>
  260. <category><![CDATA[Domino]]></category>
  261. <category><![CDATA[HTTP]]></category>
  262. <category><![CDATA[OSGi]]></category>
  263. <category><![CDATA[Web]]></category>
  264.  
  265. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2316</guid>
  266. <description><![CDATA[If we want to access Domino&#8217;s Environment, it is the ContextInfo class which gives us all we need. Everything you need to do to use the class is described in an earlier blog post. The class gives mainly access to the &#8230; <a href="http://hasselba.ch/blog/?p=2316">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  267. <content:encoded><![CDATA[<p>If we want to access Domino&#8217;s Environment, it is the <em>ContextInfo </em>class which gives us all we need. Everything you need to do to use the class is described in an <a href="http://hasselba.ch/blog/?p=1889" target="_blank">earlier blog post</a>.</p>
  268. <p>The class gives mainly access to the following methods:</p>
  269. <table style="width: 639px;">
  270. <tbody>
  271. <tr>
  272. <td><strong>Method</strong></td>
  273. <td><strong>Description</strong></td>
  274. </tr>
  275. </tbody>
  276. <tbody>
  277. <tr>
  278. <td style="width: 302.722px;">getDataDirectory()</td>
  279. <td style="width: 239.278px;">Path to notes data directory</td>
  280. </tr>
  281. <tr>
  282. <td style="width: 302.722px;">getEnvironmentString(String envName)</td>
  283. <td style="width: 239.278px;">Returns the environment variable</td>
  284. </tr>
  285. <tr>
  286. <td style="width: 302.722px;">getServerDatabase()</td>
  287. <td style="width: 239.278px;">The actual database as NAPI object, if any</td>
  288. </tr>
  289. <tr>
  290. <td style="width: 302.722px;">getServerVariable(String varName)</td>
  291. <td style="width: 239.278px;">Variables from the Request, i.e. &#8222;QUERY_STRING&#8220;</td>
  292. </tr>
  293. <tr>
  294. <td style="width: 302.722px;">getUserDatabase()</td>
  295. <td style="width: 239.278px;">The actual database as Domino Java object, if any</td>
  296. </tr>
  297. <tr>
  298. <td style="width: 302.722px;">getUserSession()</td>
  299. <td style="width: 239.278px;">The session of the actual user performing the request (</td>
  300. </tr>
  301. <tr>
  302. <td style="width: 302.722px;">isAnonymous()</td>
  303. <td style="width: 239.278px;">true if the current user is Anonymous</td>
  304. </tr>
  305. </tbody>
  306. </table>
  307. <p>Keep in mind that the incoming request is independently of any underlying Notes database. In our example, the URI <em>http://your.server/dominorestservlet/helloworld/ </em>does not run inside of a NSF, that&#8217;s why the <em>getServerDatabase()</em> and the <em>getUserDatabase()</em> methods returns <em>null</em>.</p>
  308. <p>As a consequence, our servlet does not have any access restriction and is reachable as anonymous. If you want to access a database programatically, the &#8222;normal&#8220; Domino access control is intervening again, but we can do the access check by ourself.</p>
  309. <p>To prevent the access to the servlet, I have added a &#8222;<em>checkAuthentication</em>&#8220; method to the <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/RestApiServlet.java" target="_blank">RestApiServlet</a> class. This method checks if the current user is a) not anonymous and b) a member of the group <em>RESTAPIAccessAllowed</em>. The method throws a <em>NotAuthenticatedException</em> which let&#8217;s the servlet return a <a href="https://en.wikipedia.org/wiki/HTTP_403" target="_blank">HTTP 403</a>.</p>
  310. ]]></content:encoded>
  311. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2316</wfw:commentRss>
  312. <slash:comments>2</slash:comments>
  313. </item>
  314. <item>
  315. <title>Domino &#038; REST: Consuming JSON</title>
  316. <link>http://hasselba.ch/blog/?p=2313</link>
  317. <comments>http://hasselba.ch/blog/?p=2313#comments</comments>
  318. <pubDate>Wed, 01 Mar 2017 07:25:45 +0000</pubDate>
  319. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  320. <category><![CDATA[Apache Wink]]></category>
  321. <category><![CDATA[Jackson]]></category>
  322. <category><![CDATA[Java]]></category>
  323. <category><![CDATA[JEE]]></category>
  324. <category><![CDATA[REST]]></category>
  325. <category><![CDATA[Domino]]></category>
  326. <category><![CDATA[HTTP]]></category>
  327. <category><![CDATA[Web]]></category>
  328.  
  329. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2313</guid>
  330. <description><![CDATA[Consuming JSON is as easy as pie: Just create a new method to the RestApiServlet,  add a @POST annotation, and declare the object you want to the parameters of the method:     @POST    [email protected]("/helloworld/")    [email protected](MediaType.APPLICATION_JSON)     public Response postHelloWorld(HelloWorld helloWorld) &#8230; <a href="http://hasselba.ch/blog/?p=2313">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  331. <content:encoded><![CDATA[<p>Consuming JSON is as easy as pie: Just create a new method to the <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/RestApiServlet.java" target="_blank">RestApiServlet</a>,  add a @POST annotation, and declare the object you want to the parameters of the method:</p>
  332. <pre><code>    @POST
  333.    [email protected]("/helloworld/")
  334.    [email protected](MediaType.APPLICATION_JSON)
  335.     public Response postHelloWorld(HelloWorld helloWorld) {
  336.         return Response.ok(helloWorld, MediaType.APPLICATION_JSON).build();
  337.     }</code></pre>
  338. <p>In this example we are using the same URI &#8222;<em>/helloworld/</em>&#8222;; because we now are using another HTTP method, there is no conflict between the two methods.</p>
  339. <p>Have a look at the parameter of the <em>postHelloWorld</em> method: It is the <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/HelloWorld.java" target="_blank">HelloWorld</a> class which now instantiated and filled automatically from the POSTed JSON data! We can access the object in Java, and in this short example the result is directly returned back in the response.</p>
  340. <p>If we now send a JSON request with a &#8222;message&#8220; field&#8230;</p>
  341. <pre><code>curl -i -X POST -d <strong>"{\"message\": \"foo\"}"</strong> \
  342.     -H "Content-Type: application/json" \
  343.     http://your.server/dominorestservlet/helloworld/</code></pre>
  344. <p>&#8230; the response contains the message we have posted:</p>
  345. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-jsonpost.png"><img class="alignnone size-full wp-image-2314" src="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-jsonpost.png" alt="" width="680" height="202" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-jsonpost.png 680w, http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-jsonpost-300x89.png 300w" sizes="(max-width: 680px) 100vw, 680px" /></a></p>
  346. ]]></content:encoded>
  347. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2313</wfw:commentRss>
  348. <slash:comments>1</slash:comments>
  349. </item>
  350. <item>
  351. <title>Domino &#038; REST: A basic Servlet</title>
  352. <link>http://hasselba.ch/blog/?p=2307</link>
  353. <comments>http://hasselba.ch/blog/?p=2307#respond</comments>
  354. <pubDate>Tue, 28 Feb 2017 13:49:09 +0000</pubDate>
  355. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  356. <category><![CDATA[Jackson]]></category>
  357. <category><![CDATA[Java]]></category>
  358. <category><![CDATA[JEE]]></category>
  359. <category><![CDATA[REST]]></category>
  360. <category><![CDATA[Web]]></category>
  361. <category><![CDATA[Apache Wink]]></category>
  362.  
  363. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2307</guid>
  364. <description><![CDATA[To have a good starting point when creating RESTful applications on top of Domino, I have created a &#8222;Hello World&#8220; example of a JEE Application, based on Apache Wink &#38; Jackson 2.5.0. The Jackson AnnotaionProcessor is registered into Apache Wink &#8230; <a href="http://hasselba.ch/blog/?p=2307">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  365. <content:encoded><![CDATA[<p>To have a good starting point when creating RESTful applications on top of Domino, I have created a &#8222;Hello World&#8220; example of a JEE Application, based on <a href="https://wink.apache.org/" target="_blank">Apache Wink</a> &amp; <a href="http://wiki.fasterxml.com/JacksonHome" target="_blank">Jackson 2.5.0</a>.</p>
  366. <p>The Jackson AnnotaionProcessor is registered into Apache Wink application and is enabled by default, the JAXB processor is also included as the secondary AnnotationProcessor. The benefit of this is that only one global <a href="http://wiki.fasterxml.com/ObjectMapper" target="_blank">ObjectMapper</a> instance is created and is reused, wich allows a better performance as when you create an own instance of an ObjectMapper for every request.</p>
  367. <p>The servlet is deployed as a Plugin, so you need a working XPages plugin development environment first before you can build it (I won&#8217;t get in the details at this time). The code of the servlet can be found in the <a href="https://github.com/hasselbach/domino-rest-servlet/tree/master/domino-rest-servlet.plugin" target="_blank">domino-rest-servlet.plugin</a> project.</p>
  368. <p>First have a look into <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/plugin.xml" target="_blank">plugin.xml</a>: This file contains the extension point used by the plugin, which means that this tells the Domino server what is inside and what to do next with the plugin. The extension point is of type &#8222;<em>com.ibm.pvc.webcontainer.application</em>&#8220; and allows to run our own JEE application, independently of the XPages runtime. The <em>contextRoot </em>is the URI part on which our application &#8222;listens&#8220;. The <em>contentLocation</em> is where files are searched when accessed from the browser, and points to the <a href="https://github.com/hasselbach/domino-rest-servlet/tree/master/domino-rest-servlet.plugin/WebContent/" target="_blank">WebContent </a>folder (as you already know, it is the same as in XPages projects when using the package explorer view). Here you can store static files and/or resources if required.</p>
  369. <p>The <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/WebContent/WEB-INF/web.xml" target="_blank">web.xml</a> file is the servlet configuration and the place where the servlet is registered. With <em>servlet-mappings</em> you can define URI pathes *inside* of the JEE application.</p>
  370. <p>In this example, every request is mapped to the <em>RestServlet</em> servlet when it is send to &#8222;<em>http://your.server/dominorestservlet/</em>&#8222;. It will be now processed by the class <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/RestApiApplication.java" target="_blank">ch.hasselba.dominorestservlet.RestApiApplication</a>, which &#8222;knows&#8220; the <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/RestApiServlet.java" target="_blank">RestApiServlet</a> because of the <a href="http://docs.oracle.com/javaee/6/api/javax/ws/rs/Path.html">@Path</a> annotations.</p>
  371. <p><strong><a href="http://hasselba.ch/blog/wp-content/uploads/2017/02/console-rest.png"><img class="alignnone size-full wp-image-2309" src="http://hasselba.ch/blog/wp-content/uploads/2017/02/console-rest.png" alt="" width="676" height="405" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/02/console-rest.png 676w, http://hasselba.ch/blog/wp-content/uploads/2017/02/console-rest-300x180.png 300w" sizes="(max-width: 676px) 100vw, 676px" /></a></strong></p>
  372. <p>Our &#8222;Hello World&#8220; example is registered for the URI &#8222;<em>/helloworld/</em>&#8220; and only for HTTP GET requests. As soon you are opening &#8222;<em>http://your.server/dominorestservlet/helloworld/</em>&#8222;, an instance of <a href="https://github.com/hasselbach/domino-rest-servlet/blob/master/domino-rest-servlet.plugin/src/ch/hasselba/dominorestservlet/HelloWorld.java" target="_blank">HelloWorld</a> is created and transformed to JSON. The result looks like this:</p>
  373. <pre><code>{"message":"Hello World!"}</code></pre>
  374. <p>During the next blog posts, I will expand this example and explain step by step how a seamless integration in the Domino environment works.</p>
  375. <p>You can find the code here: <a href="https://github.com/hasselbach/domino-rest-servlet" target="_blank">https://github.com/hasselbach/domino-rest-servlet</a></p>
  376. ]]></content:encoded>
  377. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2307</wfw:commentRss>
  378. <slash:comments>0</slash:comments>
  379. </item>
  380. <item>
  381. <title>Domino &#038; REST: Listeners for Initialization &#038; Destroying of a Servlet</title>
  382. <link>http://hasselba.ch/blog/?p=2300</link>
  383. <comments>http://hasselba.ch/blog/?p=2300#respond</comments>
  384. <pubDate>Mon, 27 Feb 2017 09:15:43 +0000</pubDate>
  385. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  386. <category><![CDATA[Java]]></category>
  387. <category><![CDATA[JEE]]></category>
  388. <category><![CDATA[REST]]></category>
  389. <category><![CDATA[Server]]></category>
  390. <category><![CDATA[Apache Wink]]></category>
  391. <category><![CDATA[Domino]]></category>
  392. <category><![CDATA[Servlet]]></category>
  393. <category><![CDATA[Web]]></category>
  394.  
  395. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2300</guid>
  396. <description><![CDATA[If you need to know when your Servlet is initialized or destroyed, you can use a ServletContextListener in your application. First, create the class AppServletContextListener and implement the javax.servlet.ServletContextListener interface. This provides two methods for capturing the events: contextInitialized and &#8230; <a href="http://hasselba.ch/blog/?p=2300">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  397. <content:encoded><![CDATA[<p>If you need to know when your Servlet is initialized or destroyed, you can use a <em>ServletContextListener</em> in your application.</p>
  398. <p>First, create the class <em>AppServletContextListener</em> and implement the <em>javax.servlet.ServletContextListener </em>interface<em>.</em> This provides two methods for capturing the events: <em>contextInitialized</em> and <em>contextDestroyed:</em></p>
  399. <pre><code>package ch.hasselba.servlet;
  400.  
  401. import javax.servlet.ServletContextEvent;
  402. import javax.servlet.ServletContextListener;
  403.  
  404. public class AppServletContextListener
  405.                implements ServletContextListener{
  406.  
  407.    [email protected]
  408.     public void contextDestroyed(ServletContextEvent event) {
  409.         System.out.println("ServletContextListener destroyed");
  410.     }
  411.  
  412.    [email protected]
  413.     public void contextInitialized(ServletContextEvent event) {
  414.         System.out.println("ServletContextListener started");
  415.     }
  416. }</code></pre>
  417. <p>The <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContextEvent.html" target="_blank"><em>ServletContextEvent</em></a> allows you to access the <a href="http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html" target="_blank"><em>ServletContext</em></a> if required.</p>
  418. <p>Now you have to register the listener in your <em>web.xml</em>:</p>
  419. <pre><code>&lt;web-app&gt;
  420.      &lt;listener&gt;
  421.          &lt;listener-class&gt;
  422.              ch.hasselba.servlet.AppServletContextListener
  423.          &lt;/listener-class&gt;
  424.     &lt;/listener&gt;
  425. &lt;/web-app&gt;</code></pre>
  426. <p>As soon as you start or stop the HTTP task, the Listener is called, and you can execute some application specific code (i.e. shutdown threads, bring out the garbage, etc.)</p>
  427. <p><a href="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-startup.png"><img class="alignnone size-full wp-image-2302" src="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-startup.png" alt="" width="680" height="224" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-startup.png 680w, http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-startup-300x99.png 300w" sizes="(max-width: 680px) 100vw, 680px" /></a><a href="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-shutdown.png"><img class="alignnone size-full wp-image-2301" src="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-shutdown.png" alt="" width="681" height="149" srcset="http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-shutdown.png 681w, http://hasselba.ch/blog/wp-content/uploads/2017/02/screenshot-shutdown-300x66.png 300w" sizes="(max-width: 681px) 100vw, 681px" /></a></p>
  428. ]]></content:encoded>
  429. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2300</wfw:commentRss>
  430. <slash:comments>0</slash:comments>
  431. </item>
  432. <item>
  433. <title>Jackson: Skip Objects conditionally</title>
  434. <link>http://hasselba.ch/blog/?p=2293</link>
  435. <comments>http://hasselba.ch/blog/?p=2293#respond</comments>
  436. <pubDate>Wed, 08 Feb 2017 07:51:41 +0000</pubDate>
  437. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  438. <category><![CDATA[Jackson]]></category>
  439. <category><![CDATA[REST]]></category>
  440. <category><![CDATA[Domino]]></category>
  441. <category><![CDATA[Java]]></category>
  442. <category><![CDATA[Web]]></category>
  443.  
  444. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2293</guid>
  445. <description><![CDATA[I had a simple problem when implementing this brilliant solution in one of my REST applications: As soon I was using @JsonAnyGetter / @JsonAnySetter and the HidableSerializer together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 &#8230; <a href="http://hasselba.ch/blog/?p=2293">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  446. <content:encoded><![CDATA[<p>I had a simple problem when implementing <a href="http://www.baeldung.com/jackson-serialize-field-custom-criteria" target="_blank">this brilliant</a> solution in one of my REST applications: As soon I was using <em>@JsonAnyGetter</em> / <em>@JsonAnySetter</em> and the <em>HidableSerializer</em> together, a NPE was thrown during serialization. The Problem occured in Jackson 1.9.13 and even 2.5.0, the latest version usable with the actual Domino JVM.</p>
  447. <ul>
  448. <li><strong>Stack Trace</strong></li>
  449. </ul>
  450. <pre class="lang-java prettyprint prettyprinted"><code><span class="pln">org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test["[anySetter]"])
  451. null
  452.     at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
  453.     at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
  454.     at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
  455.     at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
  456.     at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
  457. at ch.hasselba.HidableSerializer.serialize(HidableSerializer.java:29)
  458.     at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
  459.     at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
  460.     at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
  461.     at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
  462.     at ch.hasselba.Demo.main(Demo.java:54)
  463. Caused by: java.lang.NullPointerException
  464.     at org.codehaus.jackson.map.ser.std.MapSerializer.serializeFields(MapSerializer.java:243)
  465.     at org.codehaus.jackson.map.ser.AnyGetterWriter.getAndSerialize(AnyGetterWriter.java:41)
  466.     at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:154)
  467.     ... 7 more</span></code></pre>
  468. <p>After hours of investigation, a simple solution came up on <a href="http://stackoverflow.com/questions/41890497/jackson-jsonanysetter-nullpointer-exception-during-serialization-deserializat" target="_blank">SO</a>: The default serializer must be resolved, and then the code will work. I just had to override resolve method of my <em>HidableSerializer</em>:</p>
  469. <pre class="lang-java prettyprint prettyprinted"><code><span class="pun">@Override
  470. public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
  471.     if(defaultSerializer instanceof ResolvableSerializer) {
  472.          ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
  473.     }
  474. }</span></code></pre>
  475. <p>Here is a complete working example:</p>
  476. <p>&nbsp;</p>
  477. <ul>
  478. <li><strong>The Demo Code</strong></li>
  479. </ul>
  480. <pre class="lang-java prettyprint prettyprinted"><code><span class="kwd">package ch.hasselba;
  481.  
  482. import org.codehaus.jackson.Version;
  483. import org.codehaus.jackson.map.JsonSerializer;
  484. import org.codehaus.jackson.map.ObjectMapper;
  485. import org.codehaus.jackson.map.SerializationConfig;
  486. import org.codehaus.jackson.map.introspect.BasicBeanDescription;
  487. import org.codehaus.jackson.map.module.SimpleModule;
  488. import org.codehaus.jackson.map.ser.BeanSerializerModifier;
  489.  
  490. public class Demo {
  491.  
  492.     public static void main(String[] args) {
  493.  
  494.         ObjectMapper mapper = new ObjectMapper();
  495.  
  496.         // register the module
  497.         Version version = new Version(1, 0, 0, "SNAPSHOT");
  498.         mapper.registerModule(new SimpleModule("HidableModule", version) {
  499.             @Override
  500.             public void setupModule(SetupContext context) {
  501.                 super.setupModule(context);
  502.                 context.addBeanSerializerModifier(new BeanSerializerModifier() {
  503.                     @SuppressWarnings("unchecked")
  504.                     @Override
  505.                     public JsonSerializer&lt;?&gt; modifySerializer(SerializationConfig config, BasicBeanDescription desc,
  506.                         JsonSerializer&lt;?&gt; serializer) {
  507.                         if (IHidable.class.isAssignableFrom(desc.getBeanClass())) {
  508.                             return new HidableSerializer&lt;Object&gt;((JsonSerializer&lt;Object&gt;) serializer);
  509.                         }
  510.                         return serializer;
  511.                     }
  512.                 });
  513.             }
  514.         });
  515.  
  516.         // the data
  517.         String content = "{ \"foo\": \"bar\" }";
  518.  
  519.         // build the Object
  520.         Test test = null;
  521.         try {
  522.             test =  mapper.readValue(content, Test.class);
  523.         } catch (Exception e) {
  524.             e.printStackTrace();
  525.         }
  526.  
  527.         // and now convert it back to a String
  528.         String data = null;
  529.         try {
  530.              data = mapper.writeValueAsString(test);
  531.         } catch (Exception e) {
  532.             e.printStackTrace();
  533.         }
  534.  
  535.         System.out.println( data );
  536.  
  537.     }
  538.  
  539. }</span>
  540. </code></pre>
  541. <p>&nbsp;</p>
  542. <ul>
  543. <li><strong>Test Class</strong></li>
  544. </ul>
  545. <pre class="lang-java prettyprint prettyprinted"><code><span class="pln">package ch.hasselba;
  546.  
  547. import java.util.Map;
  548. import java.util.concurrent.ConcurrentHashMap;
  549.  
  550. import org.codehaus.jackson.annotate.JsonAnyGetter;
  551. import org.codehaus.jackson.annotate.JsonAnySetter;
  552.  
  553. public class Test implements IHidable {
  554.  
  555.     private Map&lt;String, Object&gt; others = new ConcurrentHashMap&lt;String, Object&gt;();
  556.  
  557.     @JsonAnyGetter
  558.     public Map&lt;String, Object&gt; getOthers() {
  559.         return this.others;
  560.     }
  561.  
  562.     @JsonAnySetter
  563.     public void addOther(final String name, final Object value) {   
  564.         this.others.put(name, value);
  565.     }
  566.  
  567.     @Override
  568.     public boolean isHidden() {
  569.         return false;
  570.     }
  571.  
  572. }</span></code></pre>
  573. <p>&nbsp;</p>
  574. <ul>
  575. <li><strong>Hideable Serializer</strong></li>
  576. </ul>
  577. <pre class="lang-java prettyprint prettyprinted"><code><span class="pun">package ch.hasselba;
  578.  
  579. import java.io.IOException;
  580.  
  581. import org.codehaus.jackson.JsonGenerator;
  582. import org.codehaus.jackson.JsonProcessingException;
  583. import org.codehaus.jackson.map.JsonSerializer;
  584. import org.codehaus.jackson.map.SerializerProvider;
  585.  
  586. public class HidableSerializer&lt;T&gt; extends JsonSerializer&lt;T&gt;  implements ResolvableSerializer {
  587.  
  588.     private JsonSerializer&lt;T&gt; defaultSerializer;
  589.  
  590.     public HidableSerializer(JsonSerializer&lt;T&gt; serializer) {
  591.         defaultSerializer = serializer;
  592.     }
  593.  
  594.     @Override
  595.     public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
  596.             throws IOException, JsonProcessingException {
  597.  
  598.         if( value instanceof IHidable ){
  599.             IHidable hidableValue = (IHidable) value;
  600.             if( hidableValue.isHidden() )
  601.                 return;
  602.         }
  603.         defaultSerializer.serialize(value, jgen, provider);
  604.     }
  605.  
  606.   @Override
  607.   public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
  608.        if(defaultSerializer instanceof ResolvableSerializer) {
  609.             ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
  610.        }
  611.   }
  612. }</span></code></pre>
  613. <p>&nbsp;</p>
  614. <ul>
  615. <li><strong>IHidable Interface</strong></li>
  616. </ul>
  617. <pre class="lang-java prettyprint prettyprinted"><code><span class="kwd">package</span><span class="pln"> ch</span><span class="pun">.</span><span class="pln">hasselba</span><span class="pun">;</span>
  618.  
  619. <span class="kwd">public</span> <span class="kwd">interface</span> <span class="typ">IHidable</span> <span class="pun">{</span>
  620.    <span class="kwd">boolean</span><span class="pln"> isHidden</span><span class="pun">();</span>
  621. <span class="pun">}</span></code></pre>
  622. ]]></content:encoded>
  623. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2293</wfw:commentRss>
  624. <slash:comments>0</slash:comments>
  625. </item>
  626. <item>
  627. <title>Entwicklercamp 2017: Meine Vorträge &#038; Hands-On</title>
  628. <link>http://hasselba.ch/blog/?p=2279</link>
  629. <comments>http://hasselba.ch/blog/?p=2279#respond</comments>
  630. <pubDate>Thu, 19 Jan 2017 07:51:44 +0000</pubDate>
  631. <dc:creator><![CDATA[Sven Hasselbach]]></dc:creator>
  632. <category><![CDATA[Allgemein]]></category>
  633. <category><![CDATA[REST]]></category>
  634. <category><![CDATA[XPages]]></category>
  635.  
  636. <guid isPermaLink="false">http://hasselba.ch/blog/?p=2279</guid>
  637. <description><![CDATA[Dieses Jahr spreche ich wieder auf dem Entwicklercamp, und halte neben den Vorträgen auch noch eine Hands-On Session: Track 1 &#8211; Session 2: XPages erweitern und ausbauen &#8211; Ausgabe 2017 Im Laufe des Jahres 2016 kamen einige Themen hinzu, und dank &#8230; <a href="http://hasselba.ch/blog/?p=2279">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
  638. <content:encoded><![CDATA[<p>Dieses Jahr spreche ich wieder auf dem <a href="http://entwicklercamp.de/" target="_blank">Entwicklercamp</a>, und halte neben den Vorträgen auch noch eine Hands-On Session:</p>
  639. <ul>
  640. <li><a href="http://entwicklercamp.de/EC17/Track1Session2">Track 1 &#8211; Session 2: XPages erweitern und ausbauen &#8211; Ausgabe 2017</a></li>
  641. </ul>
  642. <p>Im Laufe des Jahres 2016 kamen einige Themen hinzu, und dank FP8 wird es wohl auch einige Neuerungen geben, über die man mal reden müsste&#8230;</p>
  643. <ul>
  644. <li><a href="http://entwicklercamp.de/EC17/Track4Session3" target="_blank">Track 4 &#8211; Session 3: High-Performance REST Applications</a></li>
  645. </ul>
  646. <p>Hochperformante REST Schnittstellen entwickeln, die auf dem Domino Server laufen? Der Vortrag gibt Antworten auf die essentiellen Fragen des „Warum“ und des „Wieso“, und beleuchtet an praktischen Beispielen vor allem ausführlich die Frage des „Wie“.</p>
  647. <ul>
  648. <li><a href="http://entwicklercamp.de/EC17/Handson8" target="_blank">Hands On 8 &#8211; High-Performance REST Applications</a></li>
  649. </ul>
  650. <p>Die praktische Umsetzung des Vortrages. Learning by doing.</p>
  651. <p>Zur Anmeldung geht es <a href="http://entwicklercamp.de/EntwicklerCampAnmeldung" target="_blank">hier entlang</a>. Bis morgen (20.01.2017) gibt es auch noch den Frühbucherrabatt.</p>
  652. ]]></content:encoded>
  653. <wfw:commentRss>http://hasselba.ch/blog/?feed=rss2&#038;p=2279</wfw:commentRss>
  654. <slash:comments>0</slash:comments>
  655. </item>
  656. </channel>
  657. </rss>
  658.  

If you would like to create a banner that links to this page (i.e. this validation result), do the following:

  1. Download the "valid RSS" banner.

  2. Upload the image to your own server. (This step is important. Please do not link directly to the image on this server.)

  3. Add this HTML to your page (change the image src attribute if necessary):

If you would like to create a text link instead, here is the URL you can use:

http://www.feedvalidator.org/check.cgi?url=http%3A//hasselba.ch/blog/%3Ffeed%3Drss2

Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda