<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5962243442399061945</id><updated>2011-09-15T13:28:35.613+02:00</updated><category term='rest'/><category term='rest URI'/><category term='i18n'/><category term='devoxx08'/><category term='JavaEE'/><category term='JPA'/><category term='javascript'/><category term='servlets'/><category term='devoxx10'/><category term='Derby'/><category term='Hibernate'/><category term='JavaSE'/><category term='OO Design'/><category term='GAE'/><category term='WADL'/><category term='JSF'/><category term='devoxx09'/><category term='BPM'/><category term='productivity'/><category term='SOA'/><category term='Jersey'/><category term='wadl2java'/><category term='JavaFX'/><category term='struts1'/><title type='text'>Jeroen Wyseur</title><subtitle type='html'>Jeroen Wyseur is a senior consultant at &lt;a href="http://www.ae.be"&gt;AE&lt;/a&gt; focused on JavaEE application development.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>28</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-3547787112371454656</id><published>2010-11-18T15:02:00.000+01:00</published><updated>2010-11-18T15:02:36.651+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx10'/><title type='text'>Devoxx 2010</title><content type='html'>Only one day at devoxx 2010 because I'm in between clients. Two days at the new client, one day devoxx and two days at the old client, a nice compromise.&lt;br /&gt;&lt;br /&gt;My feelings of the first conference day were:&lt;br /&gt;&lt;b&gt;Keynotes&lt;/b&gt;&lt;br /&gt;JavaSE7 will be released mid 2011 and does not include that much (since 6 is from december 2006 ...), the most interesting being project coin and DynamicInvoke. The rest of the features as project lambda and jigsaw will have to wait till 8.&lt;br /&gt;The "State of the web" presentation gave great insights about what the web needs. An app store as the one &lt;a href="https://appstore.mozillalabs.com/"&gt;mozilla is preparing&lt;/a&gt; would be nice and HTML5 being a real standard instead of a grouping of features which is different for every browser.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JPA2&lt;/b&gt;&lt;br /&gt;A lot of new stuff but most of it was already in some form in Hibernate so it just seems to me I will be using less hibernate specific things. The &lt;a href="http://www.developer.com/java/ent/article.php/3897331/Pessimistic-Locking-in-JPA-2-and-Hibernate.htm"&gt;pessimistic locking&lt;/a&gt;, I didn't know about and seems to be interesting for the cases where database locking is needed. Something to remember when the need arrises ...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Infinispan&lt;/b&gt;&lt;br /&gt;An interesting data grid but I don't seem to be using those. I wonder who does but didn't get an answer on that.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Vaadin&lt;/b&gt;&lt;br /&gt;A great Server side RIA based on top of GWT. Because of the number of components, you won't need much else. I would use it if I needed a desktop like app in the browser. Another thing to remember if that use case pops up.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Spring (3.1 and caching)&lt;/b&gt;&lt;br /&gt;Two sessions that I can combine. The first one a nice overview of 3.0 (already available) and 3.1 (Spring 2011 - would also be a nice name!). I like the annotations a lot. I depends on what you prefer but having the code and the configuration in one place is very important for me.&lt;br /&gt;The last session was about the cache abstraction that will be available in 3.1. Spring is only a mediator between your application and the actual caching provider and allows you to determine what to cache (with what key) and what to evict. Putting the @Cachable annotation will make you think about what it means to have that cached. Apparently cache misses are something to be feared!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-3547787112371454656?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/3547787112371454656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=3547787112371454656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3547787112371454656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3547787112371454656'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2010/11/devoxx-2010.html' title='Devoxx 2010'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-7837272644046618893</id><published>2010-02-19T14:40:00.004+01:00</published><updated>2010-02-19T14:47:47.454+01:00</updated><title type='text'>Mocking properties in struts using mockrunner</title><content type='html'>I didn't find any example on how to use com.mockrunner.struts.MapMessageResourcesFactory class. So here we go:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;Map&amp;lt;string, string&amp;gt; resources = new HashMap&amp;lt;string, string&amp;gt;();&lt;br /&gt;resources.put("TEST", "TEST_MESSAGE");&lt;br /&gt;resources.put("TEST2", "TEST_MESSAGE2");&lt;br /&gt;MapMessageResourcesFactory.setMessageMap(resources);&lt;br /&gt;MessageResourcesFactory.setFactoryClass("com.mockrunner.struts.MapMessageResourcesFactory");&lt;br /&gt;&lt;/string,&gt;&lt;/string,&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The last line makes sure that when the message resources are loaded using&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;MessageResources.getMessageResources("PropertiesFile");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;that the given map is used to represent the resource bundle.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-7837272644046618893?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/7837272644046618893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=7837272644046618893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/7837272644046618893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/7837272644046618893'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2010/02/mocking-properties-in-struts-using.html' title='Mocking properties in struts using mockrunner'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-6604889987345524588</id><published>2010-01-05T10:29:00.004+01:00</published><updated>2010-01-05T10:44:07.704+01:00</updated><title type='text'>Hibernate validation</title><content type='html'>While using &lt;a href="http://www.dbunit.org/"&gt;dbunit &lt;/a&gt;for unit testing, we disabled the database constraint validation, making it possible to create the database rows in the wrong order or not filling in fields if they are not needed for the test. I would recommend dbunit to anyone who wants to run tests with a database (the long-running kind of tests you want to include in your nightly build, not the continuous).&lt;br /&gt;&lt;br /&gt;Then we ran into the problem that hibernate does its own validation based on for example a @NotNull annotation you placed inside your model giving one of the following exceptions:&lt;br /&gt;&lt;pre style="font-family:courier new;"&gt;org.hibernate.PropertyValueException: not-null property references a null or transient value: your.domain.Object.nonNullField&lt;br /&gt;org.hibernate.validator.InvalidStateException: validation failed for: your.domain.Object&lt;/pre&gt;&lt;br /&gt;This can be fixed by &lt;a href="http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5.0.0/html-single/Hibernate_Validator/index.html#validator-checkconstraints-orm-hibernateevent"&gt;disabling &lt;/a&gt;this kind of checks in the persistence unit using the following properties:&lt;br /&gt;&lt;pre style="font-family:courier new;"&gt;&lt;br /&gt;&amp;lt;property name="hibernate.validator.apply_to_ddl" value="false"/&amp;gt;&lt;br /&gt;&amp;lt;property name="hibernate.validator.autoregister_listeners" value="false"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-6604889987345524588?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/6604889987345524588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=6604889987345524588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6604889987345524588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6604889987345524588'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2010/01/hibernate-validation.html' title='Hibernate validation'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-578013494387239237</id><published>2009-11-19T16:27:00.002+01:00</published><updated>2009-11-20T13:59:46.177+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Five and summary</title><content type='html'>Last day already. First about the sessions I followed:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;"BPM on a SOA environment" The difference I noticed earlier between BPM &amp;amp; BPEL, has a name, the difference between managed and unmanaged process. The presentation tackled the problems between reality and how to reflect in BPM (don't forget the error handling!) At &lt;a href="http://total-architecture.com/"&gt;total architecture&lt;/a&gt;, you can read more about it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;"Towards a universal VM" The JVM start to integrate features in its JIT compilation, not for the Java language but for dynamic languages on top of it. The presented feature was &lt;a href="http://jcp.org/en/jsr/detail?id=292"&gt;invokedynamic&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://archimate.org"&gt;Archimate &lt;/a&gt;tries to bridge between the free format boardroom type models and very specific UML models. It focused on Enterprise Architects and integrating different high level views.&lt;/li&gt;&lt;/ol&gt;For me the main topics where cloud computing and service-orientation (don't say SOA anymore). Both are still not there yet but further maturing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-578013494387239237?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/578013494387239237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=578013494387239237' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/578013494387239237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/578013494387239237'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-five-and-summary.html' title='Devoxx Day Five and summary'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-1990671864153087304</id><published>2009-11-19T14:56:00.006+01:00</published><updated>2009-11-20T13:47:19.867+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Four - part 2</title><content type='html'>The "JavaFX in the enterprise" session showed a lot of the &lt;a href="http://jfxtras.org"&gt;JFXtras &lt;/a&gt;project which is a step in the right direction but I think still a lot of work has to be done to make JavaFX usable in the enterprise.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://mulesoft.org/iBeans"&gt;iBeans framework&lt;/a&gt; offers easy integration without using a full SOA. Simplifies the development of a small app/widget with integrates a lot. I found it a bit annotation heavy.&lt;br /&gt;&lt;br /&gt;Glassfish v3 I saw already the previous time at Devoxx. Still an impressive application server, I will surely check it out when it comes out 10/12/2009. Before the demo, Roberto Chinnci explained a bit the extensability of JavaEE 6 at servlet level through &lt;a href="http://www.ermalaev.spb.ru/javaee/6/docs/api/javax/servlet/ServletContainerInitializer.html"&gt;ServletContainerInitializer&lt;/a&gt; subclasses and the dependency injection through an Extension implementation. I won't go into details but basically, you can by adding a jar to your classpath, dynamically add servlets, servlets and beans when the app starts up. Very powerful and a blessing for the common developer onces the frameworks start using this. No more configuration but pure magic.&lt;br /&gt;&lt;br /&gt;Last session performance. I have to agree with the speaker which is from &lt;a href="http://www-01.ibm.com/software/support/isa/"&gt;IBM Support Assistant&lt;/a&gt;. Performance is only an issue when it's bad. The techniques explained for finding CPU, I/O, memory of lock problems often involved some sort of tool. Still experience in understanding the returned data is often more important than the used tool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-1990671864153087304?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/1990671864153087304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=1990671864153087304' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1990671864153087304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1990671864153087304'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-four-part-2.html' title='Devoxx Day Four - part 2'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-1436338686368796651</id><published>2009-11-19T13:23:00.007+01:00</published><updated>2009-11-19T14:56:05.767+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Four - part 1</title><content type='html'>The keynote of today was very good with speakers focussing on a foundation of developing software (&lt;a href="http://www.ivarjacobson.com/"&gt;Ivar Jacobson&lt;/a&gt;) and craftmanship (&lt;a href="http://www.objectmentor.com/"&gt;uncle bob&lt;/a&gt;).  The foundation was alot about how to define a base which could be extended by different practices instead of reinventing the whole process each time. The &lt;a href="http://www.semat.org/bin/view"&gt;SEMAT initiative&lt;/a&gt; was started to do just this. &lt;a href="http://en.wikipedia.org/wiki/Software_Craftsmanship"&gt;Craftmanship &lt;/a&gt;is all about being proud of your work and behaving like a professional. I have already read the clean code book and while I found it to be repeating, the points are valid.&lt;br /&gt;&lt;br /&gt;First real session, "Using XML for Java" by &lt;a href="http://www.saxonica.com/"&gt;Michael Kay&lt;/a&gt; gave a good overview of how to handle that damn XML. From low to high level :&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Event processing (SAX/STAX) : use when high performance is needed and schema remains fixed.&lt;/li&gt;&lt;li&gt;Tree based : certainly don't use the standard DOM but JDOM, DOM4J or the newest kid around the block XOM.&lt;/li&gt;&lt;li&gt;Data binding (JAXB and others): only when conversion is needed!&lt;/li&gt;&lt;li&gt;XSLT/XQuery : higher level language to handle XML.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The speaker would like us to have an all XML application where Java is the glue/infrastructure. From an XML database through a XSLT/XQuery pipeline to an XForms frontend. Sounds nice but since XSLT/XQuery is a specific language, I don't believe it has the same flexibility. I can agree that if not needed (XML is input and output), don't map the XML to Java but use conversion.&lt;br /&gt;&lt;br /&gt;I followed a quickie about fluent languages (internal DSL) just a better way to write an API. Examples can be found in the &lt;a href="http://fluval.sourceforge.net/"&gt;fluent validation framework&lt;/a&gt;. Try writing you own, it's a lot of fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-1436338686368796651?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/1436338686368796651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=1436338686368796651' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1436338686368796651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1436338686368796651'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-four-part-1.html' title='Devoxx Day Four - part 1'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-4250512196779191749</id><published>2009-11-18T16:44:00.009+01:00</published><updated>2009-11-19T14:56:05.768+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Three - part 2</title><content type='html'>After a few technical problems, the "SLF4J and logback" session started. I have to say, I'm impressed that so much could be improved. Some highlights:&lt;br /&gt;&lt;a href="http://www.slf4j.org/"&gt;SLF4J&lt;/a&gt; a commons-logging replacement:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Parameterized logging: replacing the if (logger.isDebugEnabled()) guard clause by a smarter method logger.debug("Hello {}", name) which is fast. Three lines to one!&lt;/li&gt;&lt;li&gt;Easy logging backend selection by just putting the right jar in the path. No more searching why what backend was selected.&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://logback.qos.ch/"&gt;Logback&lt;/a&gt; : a log4j replacement&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Very nice configuration which is easy extensible. Builds on dependency injection.&lt;/li&gt;&lt;li&gt;Easy filtering on log statements using evaluations.&lt;/li&gt;&lt;li&gt;SiftingAppender: multiple files based on an evaluation&lt;/li&gt;&lt;li&gt;Stack traces contain jar file and its version number.&lt;/li&gt;&lt;/ul&gt;Migration is made easy by a migrator tool. Seems really terrific. It also has an &lt;a href="http://logback.qos.ch/consolePlugin.html"&gt;eclipse plugin&lt;/a&gt; to read the logfiles better than with the standard console view. &lt;a href="http://stackoverflow.com/questions/178836/should-new-projects-use-logback-instead-of-log4j"&gt;Should you migrate?&lt;/a&gt; I think so.&lt;br /&gt;&lt;br /&gt;A very crowded session with a very long title, "Traditional Programming Models: Knives and bearskins in the google age", had some nice points but didn't do anything with them. Like programming concepts as ordered , reliable and only once execution are very expensive in a distributed environment as messaging and databases. So it is normal that scaling is difficult. But further no real answers ...&lt;br /&gt;&lt;br /&gt;"Solr: power to lucene" was a more interesting session. Solr is a compelling product if you need search. A bit too much bullet points in the presentation about what Solr can do. Just saying 'get a great "google like" search for the documents/databases/... you add to it' says almost the same.&lt;br /&gt;&lt;br /&gt;Last session of the day 'Animation Rules! A fun session telling a lot about disney animation and its relation with the GUI world. Explains a bit why some things look good in a GUI. Examples: slow in/out, hover over for a button, ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-4250512196779191749?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/4250512196779191749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=4250512196779191749' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4250512196779191749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4250512196779191749'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-three-part-2.html' title='Devoxx Day Three - part 2'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-2352889914902403823</id><published>2009-11-18T12:19:00.004+01:00</published><updated>2009-11-19T14:56:05.768+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Three - part 1</title><content type='html'>In the keynote I learned:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Oracle is committed to Java (or at least wants to give us that message).&lt;/li&gt;&lt;li&gt;Java EE 6 will be great, as will GlassFish v3 and it's coming 10/12/2009.&lt;/li&gt;&lt;li&gt;Adobe wants developers to switch to their platform which has great tools to benefit the interaction between designers and developers. Definitely something to consider if you want a cool client app.&lt;/li&gt;&lt;/ul&gt;Then I followed the "ESB's &amp;amp; web services in practice" because I liked the previous talk of Nicolai Josuttis. Learned some things but still the talk looked a bit too much too the one of yesterday. SOA is a solution to a problem (how to connect heterogeneous systems) but not one without its own issues. It was a bit more in depth, discussing problems with ESB and WSDL instead of SOA in general. This showed to me that it is complicated and for example if you only have 5 systems, point to point could be preferable to an intermediate ESB. A pragmatic approach is probably the best. I remember doing routing of messages from and to different systems using just a plain appllication server without any other framework/tool/product. Using an ESB for just that would have been too much overhead.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-2352889914902403823?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/2352889914902403823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=2352889914902403823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2352889914902403823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2352889914902403823'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-three-part-1.html' title='Devoxx Day Three - part 1'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-6196007694010099295</id><published>2009-11-17T11:03:00.010+01:00</published><updated>2009-11-17T19:32:31.762+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GAE'/><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><title type='text'>Devoxx Day Two</title><content type='html'>I wanted to start with the apache wicket session which was cancelled. So I ended up in a google app engine session. Seems very nice to get a small/personal app up in there however because of the restrictions placed (which seem fair to me), you will run in to unexpected problems here and there. They demonstrated a SpringMVC, JSF2 and GWT user interface on top of a common spring bean service layer using a JDO DAO layer. I think &lt;a href="http://code.google.com/p/swagswap/"&gt;the presented application&lt;/a&gt; is interesting as a starting point since they encountered and fixed a number of gotchas. It looks like of the three, SpringMVC gave the least problems.&lt;br /&gt;&lt;br /&gt;I tested a couple of weeks ago Google App Engine and tried to run grails on it. Worked fine with some tweaks but I couldn't get my JRebel to work with it but this is &lt;a href="http://www.zeroturnaround.com/forum/topic.php?id=328#post-1369"&gt;getting worked on&lt;/a&gt;. Look at &lt;a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine?pli=1"&gt;this page&lt;/a&gt; to see if your favorite framework works on it. Apache Wicket doesn't so I have to find something else to know what this Wicket stuff is about ...&lt;br /&gt;&lt;br /&gt;Next session "SOA in practice" by &lt;a href="http://www.it-communication.com/"&gt;Nicolai Josuttis&lt;/a&gt;, apparently he also has a &lt;a href="http://www.soa-in-practice.com/"&gt;book &lt;/a&gt;about the topic.  From all code session to a no code session. Very very interesting session which also confirmed my suspicions on BPEL the previous day. It should only be used for backend processes, not when user interaction is needed. He really doesn't like BPEL (probably had to work with too long) and raised valid points that vendors won't tell you:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You need to implement the services to be able to plug an play.&lt;/li&gt;&lt;li&gt;Implementing error handling is hard and takes 80% of your workflow.&lt;/li&gt;&lt;li&gt;It doesn't help you to handle your SLA (service level agreement)&lt;/li&gt;&lt;li&gt;Converting from UML, BPMN, EPC or visio to BPEL may work but the result will not be readable.&lt;/li&gt;&lt;/ul&gt;But that was not what the talk was about. You should only use SOA if you need it because of&lt;br /&gt;&lt;ul&gt;&lt;li&gt;distributed processes&lt;/li&gt;&lt;li&gt;on heterogenous systems (using different technologies)&lt;/li&gt;&lt;li&gt;with different owners.&lt;/li&gt;&lt;/ul&gt;and even then it will be hard. A large system that is tightly coupled may sound bad but loosely coupling and a lot of systems is complex. The gained flexibility comes at a price! Maintaining a landscape of systems instead of developing one system brings not only technical challenges but also organizational. You can't buy SOA!&lt;br /&gt;&lt;br /&gt;After that he also talked about the &lt;a href="http://www.soa-manifesto.org/"&gt;SOA manifesto&lt;/a&gt; that he helped creating. While probably useful as communication instrument, it is too abstract for me.&lt;br /&gt;&lt;br /&gt;Last sesion about "Gradle, a better way to build" or not because&lt;span style="font-style: italic;"&gt; &lt;/span&gt;I left for the &lt;a href="http://java-monitor.com/"&gt;java monitor&lt;/a&gt; session which was quite interesting. A lot of garbage collector insights. A pity the session was so short but you can find the slides &lt;a href="http://java-monitor.com/forum/showthread.php?t=646"&gt;here&lt;/a&gt;. An interesting thing was that the server VM is faster than the client VM which starts up faster.&lt;br /&gt;The gradle session I left because it seemed very complicated. I could as well use Ant which I know already instead of learning another complicated thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-6196007694010099295?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/6196007694010099295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=6196007694010099295' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6196007694010099295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6196007694010099295'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-two.html' title='Devoxx Day Two'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-8973888397633754530</id><published>2009-11-16T19:45:00.003+01:00</published><updated>2009-11-16T19:58:49.742+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx09'/><category scheme='http://www.blogger.com/atom/ns#' term='BPM'/><title type='text'>Devoxx Day One</title><content type='html'>The first day of the &lt;a href="http://www.devoxx.com"&gt;Devoxx conference in Antwerp&lt;/a&gt;, I followed the sessions "jBPM 4 In Action" and "SOA, OpenESB &amp; OpenSSO : Programming with Passion". During the second session I noticed that both sessions were somewhat related since they were both handling Business Processes and how the respective frameworks jBPM and OpenESB can help you to implement those.&lt;br /&gt;However when I look at the two presentation, I notice that jBPM is more focused on high level business processes involving human interaction while OpenESB focuses more on the composition of a difficult service in different subservices probably provided by different parties. Maybe this is because the second talk was focused around the BPEL Service Engine (JBI component in OpenESB), if I look to the &lt;a href="http://wiki.open-esb.java.net/Wiki.jsp?page=WLMSE"&gt;WLM Service Engine&lt;/a&gt;, I some more similarities with jBPM.&lt;br /&gt;The jBPM engine saves the current state of the instance of the process, keeps historical data and provides statistics on this. I didn't see any of that on the OpenESB side. On the other hand, all this database stuff also means that a process that was already running when the process is updated, needs to be migrated to the new process. This issue has been taken care of for jBPM4.&lt;br /&gt;Integrating for example a UI with jBPM has to be done with the jBPM API which seems to work quite natural. Integrating with a composite application of OpenESB has to be done through a kind of binding. Often this will be SOAP but also another one could be created.&lt;br /&gt;&lt;br /&gt;Having no experience with any of these (however I played with both a couple of years ago), I would select jBPM if I would need to implement a process with a lot of human interaction (for example requesting/approving holidays) and I would choose OpenESB to integrate between different systems.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-8973888397633754530?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/8973888397633754530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=8973888397633754530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/8973888397633754530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/8973888397633754530'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/11/devoxx-day-one.html' title='Devoxx Day One'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-1069898217442314580</id><published>2009-10-30T11:15:00.006+01:00</published><updated>2009-10-30T13:52:15.528+01:00</updated><title type='text'>Timing information EJB3</title><content type='html'>To test the performance of an application, a lot of complicated tools exist. And while they are very useful, often a pragmatic solution suffices to find the trouble spots. The suggestion below allows you to test the application and find out how long each EJB3 call took. The same could be done for any framework supporting interception of calls.&lt;br /&gt;&lt;br /&gt;The EJB3 specification provides support for interceptors making it possible to time the execution of every EJB3 on the fly. The following code intercepts each EJB3 call and stores the timing information per thread in a static variable. The recording can be enabled and disabled using the logging configuration. Another dependency is the org.apache.commons.lang.time.StopWatch.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import org.apache.commons.lang.time.StopWatch;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;&lt;br /&gt;import javax.interceptor.AroundInvoke;&lt;br /&gt;import javax.interceptor.InvocationContext;&lt;br /&gt;&lt;br /&gt;import java.util.*;&lt;br /&gt;&lt;br /&gt;public class TimerInterceptor {&lt;br /&gt;private static final Logger LOG = Logger.getLogger(TimerInterceptor.class);&lt;br /&gt;&lt;br /&gt;private static ThreadLocal&amp;lt;calltiming&amp;gt; callTrace = new ThreadLocal&amp;lt;calltiming&amp;gt;();&lt;br /&gt;&lt;br /&gt;public static Vector&amp;lt;calltiming&amp;gt; recordedTimings = new Vector&amp;lt;calltiming&amp;gt;();&lt;br /&gt;&lt;br /&gt;@AroundInvoke&lt;br /&gt;public Object timeCall(InvocationContext context) throws Exception{&lt;br /&gt;    Object returnValue;&lt;br /&gt;    boolean infoEnabled = LOG.isInfoEnabled();&lt;br /&gt;    try{&lt;br /&gt;        String key = context.getTarget().getClass().getName() + "." + context.getMethod().getName();&lt;br /&gt;        StopWatch watch = null;&lt;br /&gt;        CallTiming timing = null;&lt;br /&gt;        CallTiming parentTiming = null;&lt;br /&gt;        if (infoEnabled){&lt;br /&gt;            watch = new StopWatch();&lt;br /&gt;            watch.start();&lt;br /&gt;            parentTiming = callTrace.get();&lt;br /&gt;            if (parentTiming == null) {&lt;br /&gt;                timing = new CallTiming(key);&lt;br /&gt;                callTrace.set(timing);&lt;br /&gt;            } else {&lt;br /&gt;                timing = parentTiming.getSubTiming(key);&lt;br /&gt;                callTrace.set(timing);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        returnValue = context.proceed();&lt;br /&gt;        if (infoEnabled){&lt;br /&gt;            watch.stop();&lt;br /&gt;            LOG.info("The call to " + key + " took " + watch + " seconds");&lt;br /&gt;            timing.addTime(watch);&lt;br /&gt;&lt;br /&gt;            if (parentTiming != null) {&lt;br /&gt;                callTrace.set(parentTiming);&lt;br /&gt;            } else {&lt;br /&gt;                if (recordedTimings.size() &amp;gt; 20){&lt;br /&gt;                    recordedTimings.removeAllElements();&lt;br /&gt;                }&lt;br /&gt;                recordedTimings.add(callTrace.get());&lt;br /&gt;                callTrace.remove();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }catch(Exception e){&lt;br /&gt;        if (infoEnabled){&lt;br /&gt;            LOG.error("Error was rethrown during timing -&amp;gt; no information was recorded.", e);&lt;br /&gt;            callTrace.remove();&lt;br /&gt;        }&lt;br /&gt;        throw e;&lt;br /&gt;    }&lt;br /&gt;    return returnValue;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static class CallTiming {&lt;br /&gt;    String name;&lt;br /&gt;    Set&amp;lt;stopwatch&amp;gt; timeSet = new HashSet&amp;lt;stopwatch&amp;gt;();&lt;br /&gt;    List&amp;lt;calltiming&amp;gt; childCalls = new ArrayList&amp;lt;calltiming&amp;gt;();&lt;br /&gt;&lt;br /&gt;    CallTiming(String name) {&lt;br /&gt;        this.name = name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    CallTiming getSubTiming(String name) {&lt;br /&gt;        if (!childCalls.isEmpty() &amp;amp;&amp;amp; childCalls.get(childCalls.size() - 1).getName().equals(name)) {&lt;br /&gt;            return childCalls.get(childCalls.size() - 1);&lt;br /&gt;        } else {&lt;br /&gt;            CallTiming timing = new CallTiming(name);&lt;br /&gt;            childCalls.add(timing);&lt;br /&gt;            return timing;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void addTime(StopWatch watch) {&lt;br /&gt;        timeSet.add(watch);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getName() {&lt;br /&gt;        return name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Set&amp;lt;stopwatch&amp;gt; getTimeSet() {&lt;br /&gt;        return timeSet;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public List&amp;lt;calltiming&amp;gt; getChildCalls() {&lt;br /&gt;        return childCalls;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Any EJB you want to record the information from an EJB you need to add @Interceptors(TimerInterceptor.class).&lt;br /&gt;&lt;br /&gt;Then the recorded information can be read using a simple servlet like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;import be.post.pla.util.TimerInterceptor;&lt;br /&gt;import org.apache.commons.lang.time.StopWatch;&lt;br /&gt;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;import javax.servlet.http.HttpServlet;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;import javax.servlet.http.HttpServletResponse;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.PrintWriter;&lt;br /&gt;import java.util.List;&lt;br /&gt;import java.util.Vector;&lt;br /&gt;&lt;br /&gt;public class TimeInfoServlet extends HttpServlet {&lt;br /&gt; @Override&lt;br /&gt; protected void doGet(HttpServletRequest request,&lt;br /&gt;                      HttpServletResponse response)&lt;br /&gt;         throws ServletException, IOException {&lt;br /&gt;&lt;br /&gt;     response.setContentType("text/html");&lt;br /&gt;     PrintWriter writer = response.getWriter();&lt;br /&gt;&lt;br /&gt;     Vector&amp;lt;timerinterceptor.calltiming&amp;gt; recordedTimings = TimerInterceptor.recordedTimings;&lt;br /&gt;     writer.println("&amp;lt;title&amp;gt;Timings&amp;lt;/title&amp;gt;");&lt;br /&gt;     int i = 0;&lt;br /&gt;     for (TimerInterceptor.CallTiming recordedTiming : recordedTimings) {&lt;br /&gt;         writer.println("&amp;lt;h2&amp;gt;Recording" + i++ +"&amp;lt;/h2&amp;gt;");&lt;br /&gt;         writer.print("&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;");&lt;br /&gt;         writer.print(recordedTiming.getName());&lt;br /&gt;         writer.println("&amp;lt;/b&amp;gt;");&lt;br /&gt;         long subTotal = printChildCalls(writer, recordedTiming.getChildCalls());&lt;br /&gt;         long total = 0;&lt;br /&gt;         for (StopWatch stopWatch : recordedTiming.getTimeSet()) {&lt;br /&gt;             total += stopWatch.getTime();&lt;br /&gt;             writer.print(stopWatch);&lt;br /&gt;             writer.print(", ");&lt;br /&gt;         }&lt;br /&gt;         writer.println("&lt;br /&gt;Total time spent " + String.format("%.3fs", total / 1000d) + " seconds");&lt;br /&gt;         writer.println("&lt;br /&gt;of which " + String.format("%.3fs", subTotal / 1000d) + " seconds were in children calls");&lt;br /&gt;     }&lt;br /&gt;     writer.println("");&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private long printChildCalls(PrintWriter writer, List&amp;lt;timerinterceptor.calltiming&amp;gt; calls) {&lt;br /&gt;     long childrenTotal = 0;&lt;br /&gt;     if (!calls.isEmpty()) {&lt;br /&gt;         writer.println("&amp;lt;/timerinterceptor.calltiming&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;ul&amp;gt;");&lt;br /&gt;         for (TimerInterceptor.CallTiming call : calls) {&lt;br /&gt;             writer.print("&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;");&lt;br /&gt;             writer.print(call.getName());&lt;br /&gt;             writer.print("&amp;lt;/b&amp;gt; -- ");&lt;br /&gt;             writer.print(call.getTimeSet().size());&lt;br /&gt;             writer.println(" times");&lt;br /&gt;             long subTotal = printChildCalls(writer, call.getChildCalls());&lt;br /&gt;             long total = 0;&lt;br /&gt;             if (call.getTimeSet().size() &amp;gt; 1) {&lt;br /&gt;                 writer.print("&lt;br /&gt;");&lt;br /&gt;                 for (StopWatch stopWatch : call.getTimeSet()) {&lt;br /&gt;                     total += stopWatch.getTime();&lt;br /&gt;                     writer.print(stopWatch);&lt;br /&gt;                     writer.print(", ");&lt;br /&gt;                 }&lt;br /&gt;             } else {&lt;br /&gt;                 total = call.getTimeSet().iterator().next().getTime();&lt;br /&gt;             }&lt;br /&gt;             writer.println("&lt;br /&gt;Total time spent " + String.format("%.3fs", total / 1000d) + " seconds");&lt;br /&gt;             writer.println("&lt;br /&gt;of which " + String.format("%.3fs", subTotal / 1000d) + " seconds were in child calls");&lt;br /&gt;             writer.println("&amp;lt;/li&amp;gt;");&lt;br /&gt;             childrenTotal += total;&lt;br /&gt;         }&lt;br /&gt;         writer.println("&amp;lt;/ul&amp;gt;");&lt;br /&gt;     }&lt;br /&gt;     return childrenTotal;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Add that servlet to your web.xml :&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;   &amp;lt;servlet&amp;gt;&lt;br /&gt;       &amp;lt;servlet-name&amp;gt;Timer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;       &amp;lt;servlet-class&amp;gt;***packagename***.TimeInfoServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;   &amp;lt;/servlet&amp;gt;&lt;br /&gt;   &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;        &amp;lt;servlet-name&amp;gt;Timer&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;        &amp;lt;url-pattern&amp;gt;/timer&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;   &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Giving you some information as :&lt;br /&gt;&lt;br /&gt;Recording0&lt;br /&gt;&lt;br /&gt;xxx.ContractsFacadeBean.getPersonContracts&lt;br /&gt;    * xxx.ContractServiceBean.getPersonContracts -- 1 times&lt;br /&gt;          o xxx.ContractDAOBean.getPersonContracts -- 1 times&lt;br /&gt;            Total time spent 0,590s seconds&lt;br /&gt;            of which 0,000s seconds were in child calls&lt;br /&gt;      Total time spent 1,012s seconds&lt;br /&gt;      of which 0,590s seconds were in child calls&lt;br /&gt;0:00:05.178,&lt;br /&gt;Total time spent 5,178s seconds&lt;br /&gt;of which 1,012s seconds were in children calls&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-1069898217442314580?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/1069898217442314580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=1069898217442314580' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1069898217442314580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1069898217442314580'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/10/timing-information-ejb3.html' title='Timing information EJB3'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-2053998307989287754</id><published>2009-09-22T16:25:00.006+02:00</published><updated>2009-09-23T14:00:00.980+02:00</updated><title type='text'>Concurrency ...</title><content type='html'>Most java developers don't know a thing about concurrency other than there is a synchronized keyword that can be applied and that does some magic. The pity is that it doesn't always does it's magic and little is understood why. As web developer, I admit that concurrency is a weak point. The only times I see it used is when self-implementing a cache what you shouldn't do anyway. For the rest, if you keep yourself to JavaEE standards as not using fields in session beans or servlets, you should be safe. (I think and hope!)&lt;br /&gt;&lt;br /&gt;I happened to work on some swing code and work together with a swing developer, there concurrency is something that you have to know. The last book I read (&lt;a href="http://www.goodreads.com/book/show/3735293.Clean_Code_A_Handbook_of_Agile_Software_Craftsmanship"&gt;"Clean Code"&lt;/a&gt;) also talked a bit about concurrency and then I started reading the &lt;a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/"&gt;Sun tutorial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I learned to use more of the provided framework instead of inventing the wheel yourself:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/collections.html"&gt;Thread-safe collections&lt;/a&gt; such as ConcurrentHashMap. Very useful if you have some kind of cache instead of using synchronized all over the place and hope for the best.&lt;/li&gt;&lt;li&gt;Use &lt;a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/executors.html"&gt;Executors&lt;/a&gt; and &lt;a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html"&gt;swingworkers&lt;/a&gt; instead of dealing with threads yourself.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Some other &lt;a href="http://weblogs.java.net/blog/caroljmcdonald/archive/2009/09/17/some-java-concurrency-tips"&gt;concurreny tips from Joshua Bloch, Brian         Goetz and others&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-2053998307989287754?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/2053998307989287754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=2053998307989287754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2053998307989287754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2053998307989287754'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/09/concurrency.html' title='Concurrency ...'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-3835858382726582984</id><published>2009-08-14T16:01:00.003+02:00</published><updated>2009-08-14T16:25:53.645+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OO Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Using hibernate custom types to make a better domain model</title><content type='html'>When designing a domain model, it is good practice to encapsulate business types in their own class to be able to add specific methods to type. This avoids having some helper class around that contains these methods but is not found by every programmer. Some examples:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The social security number of a person is stored in the database as a string but should be represented in its own SSN class.&lt;/li&gt;&lt;li&gt;A month can be represented in the database as a number containing for example 200907. Encapsulating this in a Month class makes it possible to add comparison methods or for example a nextMonth() method.&lt;/li&gt;&lt;li&gt;A bank account number is stored as a string. Encapsulating this makes sure it is a valid bank account.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The problem here is that when retrieving this from the database, a string or number is retrieved which doesn't hold the same meaning. A possible solution is to store it as a String internally but use the right class when showing it to the outside. This still means that the mapping needs to be done internally too and needs to be copied to every place where this type is used.&lt;br /&gt;&lt;br /&gt;A better solution is to instruct hibernate how to do the conversion by implementing &lt;a href="https://www.hibernate.org/hib_docs/v3/api/org/hibernate/usertype/UserType.html"&gt;org.hibernate.usertype.UserType&lt;/a&gt; and adding the &lt;a href="http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#d0e2282"&gt;@TypeDef and @Type annotations&lt;/a&gt;. A nice article about how to actually implement this can be found &lt;a href="http://www.jroller.com/eyallupu/entry/hibernate_compositeusertype_and_annotations"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For Java5 enumerations using the the &lt;a href="https://www.hibernate.org/272.html"&gt;EnumUserType&lt;/a&gt; or &lt;a href="https://www.hibernate.org/273.html"&gt;this solution&lt;/a&gt; if the value in the database is different than the enumeration.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-3835858382726582984?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/3835858382726582984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=3835858382726582984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3835858382726582984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3835858382726582984'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/08/using-hibernate-custom-types-to-make.html' title='Using hibernate custom types to make a better domain model'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-149623657660836373</id><published>2009-06-29T07:59:00.006+02:00</published><updated>2009-06-29T08:25:30.422+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaEE'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Casting hibernate proxies to subclasses</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ye7OBxEm_Ow/Skhd6iT-7DI/AAAAAAAABHI/xoOMEciid5I/s1600-h/Address.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px; height: 96px;" src="http://3.bp.blogspot.com/_ye7OBxEm_Ow/Skhd6iT-7DI/AAAAAAAABHI/xoOMEciid5I/s320/Address.jpg" alt="" id="BLOGGER_PHOTO_ID_5352631417354251314" border="0" /&gt;&lt;/a&gt;For a hibernate entity with subclasses like the&lt;br /&gt;following:&lt;br /&gt;&lt;br /&gt;When retrieving all addresses, hibernate can return a list of proxies instead of the real addresses (&lt;a href="http://blog.xebia.com/2008/03/08/advanced-hibernate-proxy-pitfalls/"&gt;something more about proxies&lt;/a&gt;). These proxies, subclass Address and not the HomeAddress or WorkAddress class that they could represent. This results in the following exception when casting to HomeAddress or WorkAddress:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;java.lang.ClassCastException: package.Address_$$_javassist_36&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The solution is to deproxy the classes before casting them as follows:&lt;br /&gt;&lt;pre name="code" class="java"&gt;if (type instanceof HibernateProxy)&lt;br /&gt;type = Address .class.cast(((HibernateProxy) type).getHibernateLazyInitializer().getImplementation());&lt;br /&gt;else&lt;br /&gt;type = Address .class.cast(type);&lt;br /&gt;&lt;/pre&gt;I ran into this problem when hibernate fetched a list of all rows of one table (some 25 records) and somehow manages to provide actual classes for a number of those and proxies for the rest. If somebody could explain me why it doesn't retrieve all classes (or all proxies), I would be very happy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-149623657660836373?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/149623657660836373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=149623657660836373' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/149623657660836373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/149623657660836373'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/06/casting-hibernate-proxies-to-subclasses.html' title='Casting hibernate proxies to subclasses'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_ye7OBxEm_Ow/Skhd6iT-7DI/AAAAAAAABHI/xoOMEciid5I/s72-c/Address.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-4285675256411207157</id><published>2009-05-09T16:22:00.001+02:00</published><updated>2009-05-09T16:24:05.543+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WADL'/><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='Jersey'/><category scheme='http://www.blogger.com/atom/ns#' term='wadl2java'/><title type='text'>really using wadl2java</title><content type='html'>I recently tried out the &lt;a href="https://wadl.dev.java.net/"&gt;wadl2java code generator&lt;/a&gt;, together with some simple test REST service written with &lt;a href="https://jersey.dev.java.net/"&gt;Jersey&lt;/a&gt;. Jersey provides after deployment a &lt;a href="https://wadl.dev.java.net/"&gt;&lt;/a&gt;Web Application Description Language (WADL) and using that wadl2java generates a client to access that REST service. The generated WADL has version number 1.0 thus also that generator is needed. Further information about WADL versions can be found on the wadl2java web site.&lt;br /&gt;&lt;br /&gt;The first problem I encountered is that the &lt;a href="https://wadl.dev.java.net/wadl2java.html"&gt;wadl2java documentation&lt;/a&gt; describes very good how to use the generator but doesn't speak of using the generated code. Thus while the generation went smoothly, using the generated code meant reading the generated source code to figure out what each function does and how to use it. And I thought that generating a client would make my life simpeler!&lt;br /&gt;&lt;br /&gt;As I see this blog as a way to share stuff I learned so that hopefully someone who needs the same information can google this up, I'll try to explain who I think it has to be used. A single class EndPoint is generated containing a lot of inner classes. Using the inner classes, you can build the URL you would like to access.&lt;br /&gt;/resource becomes new EndPoint.Resource()&lt;br /&gt;/resource/contract becomes new EndPoint.Resource.Contract()&lt;br /&gt;/resource/{id} becomes new EndPoint.Resource.Id(id)&lt;br /&gt;/resource/{id}/contract becomes EndPoint.Resource.IdContract(id)&lt;br /&gt;&lt;br /&gt;The inner classes have methods combining the HTTP method and representation. Some examples should clarify this.&lt;br /&gt;getAsHtml() does a HTTP GET to retrieve a HTML representation&lt;br /&gt;getAsJson() does a HTTP GET to retrieve a JSON representation&lt;br /&gt;put() performs a HTTP PUT with as input a DataSource&lt;br /&gt;&lt;br /&gt;What you get back (or need to send in case of a PUT/POST) is of type DataSource. Some things you can do with this DataSource object:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Retrieve a representation out of it:&lt;br /&gt;&lt;blockquote&gt;dataSource.getInputStream()&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Put an XML representation in it:&lt;br /&gt;&lt;blockquote&gt;String updatedPerson = "&lt;person lastname="\" firstname="\" pdbkey="\"&gt;";&lt;br /&gt;input = new ByteArrayDataSource(updatedPerson.getBytes(), "application/xml");&lt;/person&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;/ul&gt;This should help you use the generated classes. If you find some easier methods, don't hesitate to comment further.&lt;br /&gt;&lt;br /&gt;I like the wadl2java generation as fast client builder but I think it has a lot of shortcomings to provide a powerful interface to a REST service. It should also make it easier to use more advanced features as caching, conditional GET, error handling and such. I know understand the concerns of others that when using WADL you dumb down REST and hide the advanced features. It has the same problems as giving WSDL client generation to the developer masses so that they aren't aware of how powerful SOAP and WS-* can be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-4285675256411207157?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/4285675256411207157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=4285675256411207157' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4285675256411207157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4285675256411207157'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/05/really-using-wadl2java.html' title='really using wadl2java'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-1231870172711786685</id><published>2009-05-08T16:14:00.002+02:00</published><updated>2009-05-08T16:24:22.377+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaSE'/><category scheme='http://www.blogger.com/atom/ns#' term='OO Design'/><title type='text'>Know why ...</title><content type='html'>When doing things as they have always been done, it is important to sometimes say 'STOP!' and try to figure out why you should do it like that. If encountered this a couple of times this week.&lt;br /&gt;&lt;br /&gt;When adding a comment on an overridden method, eclipse automagically enters {@inheritDoc} and that's it. Made sense to me but I had no idea what the things does. Well in this case, the  {@inheritDoc} and what the default behavior is when there is no comment is the same. Thus for keeping you're code clean instead of cluttering it with unuseful stuff, you could just ommit it. You can still use it if you want to add to the original comment because  {@inheritDoc} will copy over the original comment at that place. Something like this:&lt;br /&gt;&lt;blockquote&gt;/**&lt;br /&gt; *  {@inheritDoc} and does a lot of other useful stuff.&lt;br /&gt; */&lt;br /&gt;public void overriddenMethod()&lt;/blockquote&gt;Generating getters and setters for domain objects was the second thing I do most of the time. It seems like a good idea and makes all information easily accessible. On the other hand it makes things so simple that you don't think about encapsulation anymore and do things in the wrong place. A better approach is to wait to create the getters and setters until you really need them and at that time think how you could still keep the data encapsulated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-1231870172711786685?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/1231870172711786685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=1231870172711786685' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1231870172711786685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/1231870172711786685'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/05/know-why.html' title='Know why ...'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-5404568059488123584</id><published>2009-01-12T13:12:00.004+01:00</published><updated>2009-01-12T13:32:15.693+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaEE'/><category scheme='http://www.blogger.com/atom/ns#' term='i18n'/><title type='text'>Internationalization for javascript on top of a Java  web application</title><content type='html'>In a Java web application, the i18n is usually handled by using &lt;a href="http://java.sun.com/docs/books/tutorial/i18n/resbundle/concept.html"&gt;resource bundles&lt;/a&gt;. When using javascript, you could use something resource bundle alike &lt;a href="http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/i18n/globalization-guidelines/locale-and-resou"&gt;like dojo suggests&lt;/a&gt; but then you need to make the properties files available to the browser and for every page, all translations are loaded. I would rather like to keep using the resource bundles that I know and have tools to edit for in both my jsp's and javascript.&lt;br /&gt;&lt;br /&gt;For this end, I have written a small tag that reads the translations you need and puts them in a small JSON object. The tag currently looks like this (I only use it in one application thus customization is not yet an issue):&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class ResourceToJavaScriptTag extends TagSupport {&lt;br /&gt; /**&lt;br /&gt;  * Only the keys starting with this filter will be added to the bundle.&lt;br /&gt;  * Also this starting part of the key will be removed (making JSON attributes easier to access).&lt;br /&gt;  */&lt;br /&gt; private String filter = "";&lt;br /&gt; /**&lt;br /&gt;  * The name of the bundle.&lt;br /&gt;  */&lt;br /&gt; private String name = "";&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public int doStartTag() throws JspException {&lt;br /&gt;     try {&lt;br /&gt;         StringBuilder bundle = new StringBuilder();&lt;br /&gt;         bundle.append("&lt;script type=" \"&gt;");&lt;br /&gt;            bundle.append("var "+name+" = {");&lt;br /&gt;            Locale locale = pageContext.getRequest().getLocale();&lt;br /&gt;            ResourceBundle resourceBundle = ResourceBundle.getBundle("ApplicationResources", locale);&lt;br /&gt;            Enumeration&lt;string&gt; keys = resourceBundle.getKeys();&lt;br /&gt;            boolean isFirst = true;&lt;br /&gt;            while(keys.hasMoreElements()){&lt;br /&gt;                String key = keys.nextElement();&lt;br /&gt;                if (key.startsWith(filter)){&lt;br /&gt;                    if (!isFirst){&lt;br /&gt;                        bundle.append(",");&lt;br /&gt;                    }&lt;br /&gt;                    isFirst = false;&lt;br /&gt;                    bundle.append("\""+key.replaceFirst(filter + ".", "")+"\":\""+resourceBundle.getString(key)+"\"");&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            bundle.append("}&lt;/script&gt;");&lt;br /&gt;         pageContext.getOut().print(bundle);&lt;br /&gt;     } catch (Exception ex) {&lt;br /&gt;        throw new JspTagException("ResourceToJavaScriptTag: " +&lt;br /&gt;           ex.getMessage());&lt;br /&gt;     }&lt;br /&gt;     return SKIP_BODY;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt;  public int doEndTag() {&lt;br /&gt;     return EVAL_PAGE;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setFilter(String filter){&lt;br /&gt;      this.filter = filter;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String getFilter(){&lt;br /&gt;      return filter;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; public String getName() {&lt;br /&gt;     return name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setName(String name) {&lt;br /&gt;     this.name = name;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The filter is determines which translations to select. Only the keys starting with this filter will be added to the object. The name is the name of the javascript object containing the translations.&lt;br /&gt;The tag &lt;span style="font-weight: bold;"&gt;&amp;lt;tags:i18n filter="my.translations" name="myBundle"&amp;gt;&lt;/span&gt; gives me:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&amp;lt;script type="text/javascript"&amp;gt;var myBundle = {"trans1":"my translation1","trans2":"my translation2"}&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;for the properties&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;my.translations.trans1=my translation1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;my.translations.trans2=my translation2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;your.translations.trans3=your translation3&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;As &lt;/span&gt;&lt;span&gt;you can see, only&lt;/span&gt;&lt;span&gt; the keys starting with &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;my.translations&lt;/span&gt;&lt;span&gt; are&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;span&gt;added&lt;/span&gt;&lt;span&gt; to the json object. Now we can get a translation as &lt;span style="font-weight: bold;"&gt;myBundle.trans1&lt;/span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-5404568059488123584?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/5404568059488123584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=5404568059488123584' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5404568059488123584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5404568059488123584'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2009/01/internationalization-for-javascript-on.html' title='Internationalization for javascript on top of a Java  web application'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-163615335170985493</id><published>2008-12-31T11:24:00.004+01:00</published><updated>2009-01-03T14:03:03.548+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Derby'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaSE'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Derby database using hibernate in JavaSE</title><content type='html'>I found only bits and pieces about how to configure persistence for a standalone application (or a junit test as what I needed) using a simple database (Derby is delivered with JavaSE 6).&lt;br /&gt;&lt;br /&gt;You will need the following jars:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;derby.jar : delivered with javaSE 6 in the db folder or downloaded &lt;a href="http://db.apache.org/derby/"&gt;here&lt;/a&gt;. Another good candidate would be &lt;a href="http://hsqldb.org/"&gt;hsqldb &lt;/a&gt;that can also be used in memory (this will need a different connection-url).&lt;/li&gt;&lt;li&gt;hibernate-entitymanager.jar and all the jars it needs.&lt;/li&gt;&lt;/ul&gt;The persistence.xml that needs to be placed in the META-INF folder should look like this:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"&lt;br /&gt;xsi:schemaLocation="http://java.sun.com/xml/ns/persistence&lt;br /&gt;              http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"&amp;gt;&lt;br /&gt;&amp;lt;persistence-unit name="HibernateApp"&amp;gt;&lt;br /&gt;&amp;lt;provider&amp;gt;org.hibernate.ejb.HibernatePersistence&amp;lt;/provider&amp;gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.archive.autodetection" value="class" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.format_sql" value="true" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.show_sql" value="true" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.hbm2ddl.auto" value="create-drop" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.connection.url" value="jdbc:derby:target/database/jpa-test-database;create=true" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.connection.username" value="user" /&amp;gt;&lt;br /&gt; &amp;lt;property name="hibernate.connection.password" value="password" /&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&amp;lt;/persistence-unit&amp;gt;&lt;br /&gt;&amp;lt;/persistence&amp;gt;&lt;br /&gt;&lt;/pre&gt;The entity manager can then be retrieved as follows:&lt;br /&gt;&lt;pre name="code" class="java"&gt;EntityManagerFactory emf = Persistence.createEntityManagerFactory("HibernateApp");&lt;br /&gt;EntityManager entityManagerToUse = emf.createEntityManager();&lt;br /&gt;&lt;/pre&gt;If anyone has a good hsqldb  example, it would be a nice addition to this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-163615335170985493?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/163615335170985493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=163615335170985493' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/163615335170985493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/163615335170985493'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/derby-database-using-hibernate-in.html' title='Derby database using hibernate in JavaSE'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-527224179602190839</id><published>2008-12-17T13:34:00.017+01:00</published><updated>2008-12-19T13:48:01.426+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest URI'/><title type='text'>URI Design for REST</title><content type='html'>&lt;h4&gt;Introduction&lt;/h4&gt;After making the example to fit a restful design in struts 1.x, I began investigating which rules exist to create a URI. A URI should be a simple representation but as I we all know, making things simple is the hardest thing to do.&lt;br /&gt;I found some blogposts talking about this topic:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It started with &lt;a href="http://pragdave.blogs.pragprog.com/pragdave/2007/03/the_radar_archi.html"&gt;Dave Thomas&lt;/a&gt;,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;then  &lt;a href="http://blog.roberthahn.ca/articles/2007/04/06/url-design"&gt;Robert Hahn&lt;/a&gt; responded to it and&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://evang.eli.st/blog/2007/4/11/edit-considered-harmless"&gt;Pat Maddox&lt;/a&gt; didn't fully agree.&lt;/li&gt;&lt;/ul&gt;The initial take is how Ruby handles the URI design because there seems to be discussion about using &lt;span style="font-weight: bold;"&gt;GET /resource/1;edit&lt;/span&gt; or &lt;span style="font-weight: bold;"&gt;GET /resource/1/edit&lt;/span&gt;.&lt;br /&gt;I also think there are more cases that need to be handled, for example&lt;br /&gt;&lt;ul&gt;&lt;li&gt;doing a search for a resource,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;performing a calculation,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;showing partial information of a resource,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;showing an aggregated view of multiple resources,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;...&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Also, a URI should always be accompanied with its http method to know what the function is (the function should be a sentence where the http method is the verb and the URI the &lt;a href="http://en.wikipedia.org/wiki/Object_%28grammar%29"&gt;direct object&lt;/a&gt; an example would be "&lt;span style="font-style: italic;"&gt;I get resource 1&lt;/span&gt;").&lt;br /&gt;In this blog post I won't take in account that a normal browser request can't change the Accept header and can't send any thing else than GET and POST. These shortcomings will need to be emulated in some way.&lt;br /&gt;&lt;h4&gt;Identified resources&lt;/h4&gt;&lt;span style="font-weight: bold;"&gt;GET /resource/1&lt;/span&gt; : Showing a single resource with identifier 1.  We could also do &lt;span style="font-weight: bold;"&gt;GET /resources/1 &lt;/span&gt;which would be more of a search but since it only returns one item I agree with Robert Hahn that the first representation is the best.Using the different http methods we get:&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;POST /resource/1&lt;/span&gt; : Add a resource and use identifier 1 (in a lot of cases, this will make no sense since the identifier will be created by the server or database)&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;PUT /resource/1&lt;/span&gt; : Update the resource with identifier 1&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;DELETE /resource/1&lt;/span&gt; : Delete the resource with identifier 1&lt;/li&gt;&lt;/ul&gt;Now we get to the difficult one. How do we get to the page where we will update the attributes of the resource. The links I provided above give the following solutions for this: &lt;span style="font-weight: bold;"&gt;GET /resource/1;edit&lt;/span&gt; (apparently from Ruby), &lt;span style="font-weight: bold;"&gt;GET /resource/editable/1&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;GET /resource/1.form&lt;/span&gt;. All of these just don't seem to feel right. I think the editable representation is just a representation as another and should be handled as such. Thus giving an Accept header as &lt;span style="font-weight: bold;"&gt;text/form&lt;/span&gt;.&lt;br /&gt;&lt;h4&gt;A newly created resource&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;GET /resource&lt;/span&gt; : Get the input form to create a new resource&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;POST /resource&lt;/span&gt; : Create a new resource. The result should be a redirect to GET /resource/new_id&lt;/li&gt;&lt;/ul&gt;Put and delete do not make sense for resources that do not yet exist, thus an identifier should be given in that case.&lt;br /&gt;&lt;h4&gt;Searching a resource&lt;/h4&gt;&lt;span style="font-weight: bold;"&gt;GET /resource?field=searchvalue&amp;amp;field2=searchvalue2&lt;/span&gt; : Searching is why request parameters exist so use them for this. A very complex search could be handled in the same way as a calculation.&lt;br /&gt;&lt;h4&gt;Multiple representations of the same resource&lt;/h4&gt;Multiple representations should be retrieved using a different Accept header. Problem is that in the browser, the &lt;a href="http://stackoverflow.com/questions/374885/can-i-change-the-headers-of-the-http-request-send-by-the-browser"&gt;request header can only be set when doing an AJAX request&lt;/a&gt;. For links, you are stuck with what the browser provides.&lt;br /&gt;&lt;h4&gt;Aggregated view of multiple resources&lt;/h4&gt;I think this is just a different view (=Accept Header) for a resource. Thus information of a person with his address would be &lt;span style="font-weight: bold;"&gt;GET /person/1/address&lt;/span&gt; with an Accept header text/vnd.app.person+address.&lt;br /&gt;What if you want to see or edit a person with his address and orders on one screen? I assume something of the following: &lt;span style="font-weight: bold;"&gt;GET /person/1/address+orders&lt;/span&gt; would do. The address and the orders are related to the person and not to each other thus &lt;span style="font-weight: bold;"&gt;GET /person/1/address/orders &lt;/span&gt;would be wrong.&lt;br /&gt;&lt;h4&gt;Calculation&lt;/h4&gt;Calculations are a two step process. This first is creation of the calculation, the second retrieval of the result. Thus a &lt;span style="font-weight: bold;"&gt;POST /calculation&lt;/span&gt; would be redirected to return a &lt;span style="font-weight: bold;"&gt;GET /calculation/123&lt;/span&gt; . If this calculation is long running, the GET could be polled to check if the result is already available. The nice thing of this is that you could bookmark the result or send it to someone else without redoing the calculation.&lt;br /&gt;This solution also has its impact on the server side. The result of the calculation will need to be stored somewhere or a 410 Gone should be returned (this could also be a 404 if there was no result with the given id but how are you going to know this?)&lt;br /&gt;&lt;h4&gt; Other REST issues to think about&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Governance of URI's: As for SOAP web services, REST web services should be reusable. A certain amount of governance is needed to achieve this across projects. I found the &lt;a href="http://www.infoq.com/articles/subbu-allamaraju-rest"&gt;following nice article on infoq&lt;/a&gt;. It doesn't give any satisfying solution but still a nice read.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;How to get links in your response in an easy manner?&lt;/li&gt;&lt;li&gt;Maybe I should see REST less as "returning a presentation" and more as "providing a service".  It needs a smart client to talk to services, a dumb client (=browser) can only show a representation. In this, I follow the article of  &lt;a href="http://pragdave.blogs.pragprog.com/pragdave/2007/03/the_radar_archi.html"&gt;Dave Thomas&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Circumvent the problem that in a browser could can't set the Accept header (or any other header) in the request. Same for PUT and DELETE, this is supported by google with a hidden field in a POST request that is on the serverside translated.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add your own ...&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;URI design is not that easy. Once you make a decision on how each function is represented by a URI, you should stick with that style for your entire site. Having a clear set of guidelines to create URI's is more important than selecting THE BEST style.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-527224179602190839?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/527224179602190839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=527224179602190839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/527224179602190839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/527224179602190839'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/uri-design-for-rest.html' title='URI Design for REST'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-5284039616638692059</id><published>2008-12-16T15:09:00.015+01:00</published><updated>2008-12-17T16:48:45.413+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='struts1'/><title type='text'>Restful design with Struts 1.x</title><content type='html'>I did some more research when following up a&lt;a href="http://jwyseur.blogspot.com/2008/12/restful-design-and-struts-1x.html"&gt; previous blogpost&lt;/a&gt;. Apparently there is no real guide to use REST with struts 1.x. There exists &lt;a href="http://struts.apache.org/2.0.14/docs/rest-plugin.html"&gt;REST plugin for struts 2.x&lt;/a&gt;. This makes sense since Struts 1.x is considered to be end of life.&lt;br /&gt;When trying to fit a restful design in the old struts, I came to the following class. A lot of pieces should be generalized in a helper class or in a common superclass (maybe RestAction ?).&lt;br /&gt;&lt;blockquote&gt;&lt;pre name="code" class="java"&gt;public ActionForward execute(ActionMapping mapping, ActionForm form,&lt;br /&gt;         HttpServletRequest request, HttpServletResponse response)&lt;br /&gt;         throws Exception {&lt;br /&gt;&lt;br /&gt;     if (request.getMethod().equals("GET")){&lt;br /&gt;         String extraPath = request.getPathInfo();&lt;br /&gt;         String[] groups = extraPath.split("/");&lt;br /&gt;         if (groups.length == 3){&lt;br /&gt;             // URI /resource/{id}&lt;br /&gt;             request.setAttribute("id", groups[2]);&lt;br /&gt;&lt;br /&gt;             String acceptHeader = request.getHeader("Accept");&lt;br /&gt;             System.out.println("Accept: " + acceptHeader);&lt;br /&gt;             int htmlIndex = acceptHeader.indexOf("text/html");&lt;br /&gt;             int xmlIndex = acceptHeader.indexOf("application/xml");&lt;br /&gt;             System.out.println("Indexes " + htmlIndex + "*" + xmlIndex);&lt;br /&gt;             if (htmlIndex &amp;gt;= 0){&lt;br /&gt;                if (htmlIndex &amp;lt; xmlIndex){&lt;br /&gt;                    return mapping.findForward("resourceHTML");&lt;br /&gt;                }else{&lt;br /&gt;                    return mapping.findForward("resourceXML");&lt;br /&gt;                }&lt;br /&gt;             }&lt;br /&gt;             if (xmlIndex &amp;gt;= 0){&lt;br /&gt;                 return mapping.findForward("resourceXML");&lt;br /&gt;             }&lt;br /&gt;         }else if (groups.length == 2){&lt;br /&gt;             // URI : /resource&lt;br /&gt;             return mapping.findForward("newResourceHTML");&lt;br /&gt;         }&lt;br /&gt;     }else if (request.getMethod().equals("POST")){&lt;br /&gt;         // Create a new resource element and redirect to the view&lt;br /&gt;         response.sendRedirect("/restStruts/rest/resource/NEW_ID");&lt;br /&gt;         return null;&lt;br /&gt;     }&lt;br /&gt;     response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);&lt;br /&gt;     return null;&lt;br /&gt; }&lt;/pre&gt;&lt;/blockquote&gt;And the struts-config.xml looks like:&lt;br /&gt;&lt;blockquote&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;struts-config&amp;gt;&lt;br /&gt;&amp;lt;form-beans&amp;gt;&lt;br /&gt;    &amp;lt;form-bean name="resourceForm" type="be.struts.rest.ResourceForm"&amp;gt;&lt;br /&gt;&amp;lt;/form-bean&amp;gt;&lt;br /&gt;&amp;lt;action-mappings&amp;gt;&lt;br /&gt;    &amp;lt;action path="/resource**" type="be.struts.rest.ResourceAction" name="resourceForm" scope="request"&amp;gt;&lt;br /&gt;        &amp;lt;forward name="resourceXML" path="/pages/resourceXML.jsp"&amp;gt;&lt;br /&gt;        &amp;lt;forward name="resourceHTML" path="/pages/resourceHTML.jsp"&amp;gt;&lt;br /&gt;        &amp;lt;forward name="newResourceHTML" path="/pages/newResourceHTML.jsp"&amp;gt;&lt;br /&gt;    &amp;lt;/forward&amp;gt;&lt;br /&gt;&amp;lt;/forward&amp;gt;&lt;br /&gt;&amp;lt;/forward&amp;gt;&amp;lt;/action&amp;gt;&amp;lt;/action-mappings&amp;gt;&lt;br /&gt;&amp;lt;/form-beans&amp;gt;&lt;br /&gt;&amp;lt;/struts-config&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;Now let us look how good this adheres to a restful design:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;1. Have nice URI's with good ids&lt;/span&gt;&lt;br /&gt;The path for the action is &lt;span style="font-style: italic;"&gt;"/resource**"&lt;/span&gt; what means everything what starts with /resource is passed to that action. The rest of the URI has to be parsed as shown in the ResourceAction class. The following URI's are supported in this action:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;/resource : Shows a form to create a new resource or creates a new resource depending on the HTTP method.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;/resource/{id} : Shows the resource with given id.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Supporting other URI's that start with /resource could easily be resolved by parsing the pathInfo in the request. This would be a good candidate for generalization.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2. Use the HTTP methods&lt;/span&gt;&lt;br /&gt;Depending on GET or POST on the /resource path, an input screen is shown or a new resource is created (with a redirect to the representation of that resource).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3. Use the ACCEPT header&lt;/span&gt;&lt;br /&gt;Reading the headers of a request is provided by struts. Depending on the value of the ACCEPT header, a HTML representation or a XML representation. To test retrieving the XML representation I've written a small application. (I did not find a way to change the Accept header used by the browser using HTML or javascript. It can be done through about:config in firefox by changing the network.http.accept.default key)&lt;br /&gt;&lt;blockquote&gt;&lt;pre name="code" class="java"&gt;public static void main(String[] args) throws Exception {&lt;br /&gt;        URL url = new URL("http://localhost:8080/restStruts/rest/resource");&lt;br /&gt;        HttpURLConnection conn = (HttpURLConnection) url.openConnection();&lt;br /&gt;        conn.addRequestProperty("Accept", "application/xml");&lt;br /&gt;        InputStream content = (InputStream) conn.getContent();&lt;br /&gt;        BufferedReader postBufferedReader = new BufferedReader(new InputStreamReader(content));&lt;br /&gt;        String postline = null;&lt;br /&gt;        while((postline = postBufferedReader.readLine()) != null) {&lt;br /&gt;            System.out.println(postline);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;/blockquote&gt;Any &lt;a href="http://stackoverflow.com/questions/374885/can-i-change-the-headers-of-the-http-request-send-by-the-browser"&gt;suggestions&lt;/a&gt; to do this in the browser are appreciated.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;4. Use HTTP response codes&lt;/span&gt;&lt;br /&gt;Sending an HTTP response code in struts is quite easy. Just set the error code in the reponse object:&lt;br /&gt;&lt;blockquote&gt;&lt;pre name="code" class="java"&gt;response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);&lt;br /&gt;return null;&lt;/pre&gt;&lt;/blockquote&gt;&lt;span style="font-size:130%;"&gt;5. Use links in the response&lt;/span&gt;&lt;br /&gt;Since the response is a JSP, putting links in there is as you wish. A &lt;a href="https://jsr311.dev.java.net/nonav/javadoc/javax/ws/rs/core/UriBuilder.html"&gt;URIBuilder&lt;/a&gt; like in &lt;a href="https://jersey.dev.java.net/"&gt;Jersey&lt;/a&gt; would be nice though.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;6. Stateless communication&lt;/span&gt;&lt;br /&gt;Again this is a best practice that you should try to implement. Put all the forms in the request scope would be a good step. There is nothing is struts 1.x that keeps you from doing stateless communication.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;7. Use ETag&lt;/span&gt;&lt;br /&gt;The same way as the Accept header is read, the ETag header can be read. It should also be added to the response. I would use a form like ID-LAST_MODIFICATION_DATE and then check if the resource with given id was updated after the given modifcation date. If not, the right response code can be returned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-5284039616638692059?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/5284039616638692059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=5284039616638692059' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5284039616638692059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5284039616638692059'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/restful-design-with-struts-1x.html' title='Restful design with Struts 1.x'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-5022139285889473743</id><published>2008-12-16T08:38:00.004+01:00</published><updated>2008-12-16T10:37:17.383+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><title type='text'>Devoxx lessons learned</title><content type='html'>As I look look back to devoxx, I see three important trends:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;REST: The session about &lt;a href="http://www.innoq.com/blog/st/2008/12/devoxx_08_talk.html"&gt;Restful design&lt;/a&gt; showed that using HTTP correctly makes live simple. Instead of needing to know basic HTTP and a whole bunch of stuff above it, try to use the basic tool to its fullest. Other sessions like &lt;a href="https://jersey.dev.java.net/"&gt;JAX-RS&lt;/a&gt; and &lt;a href="http://blog.springsource.com/2008/12/05/spring-framework-30-m1-released/"&gt;Spring 3.0&lt;/a&gt; made it clear that it is now possible to really achieve a restful design.&lt;/li&gt;&lt;li&gt;WebSockets: HTML5 is only scheduled for &lt;a href="http://ishtml5readyyet.com/"&gt;2022 &lt;/a&gt;but using the &lt;a href="http://www.kaazing.org/confluence/display/KAAZING/Home"&gt;kaazing.org&lt;/a&gt; emulation, you can already use it now cross-browser. Some browsers are already implementing parts but the rest of the needed stack is emulated. The promise of having a TCP socket in your browser opens a lot of possibilities.&lt;/li&gt;&lt;li&gt;Developer productivity: Agile becomes a de facto standard but without the right tools and without using them in the right way, the productivity of a regular developer is still too low. For example, using &lt;a href="https://glassfish.dev.java.net/downloads/v3-techPreview-1.html"&gt;Glassfish V3&lt;/a&gt; (fast startup due to modular design)  and &lt;a href="http://www.zeroturnaround.com/javarebel/"&gt;javarebel&lt;/a&gt; (replace classes without redeploy) the development cycle is shortened considerably.&lt;/li&gt;&lt;/ol&gt;I didn't follow too much of the other hot stuff like RIA and scripting. They are interesting but getting approval to use them in a corporate environment is hard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-5022139285889473743?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/5022139285889473743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=5022139285889473743' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5022139285889473743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/5022139285889473743'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/devoxx-lessons-learned.html' title='Devoxx lessons learned'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-2372698259321033203</id><published>2008-12-11T11:57:00.003+01:00</published><updated>2008-12-11T16:36:13.376+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rest'/><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><category scheme='http://www.blogger.com/atom/ns#' term='struts1'/><title type='text'>Restful design and struts 1.X</title><content type='html'>Yesterday, I followed the session about restful design of &lt;a href="http://www.innoq.com/blog/st/"&gt;Stefan Tilkov&lt;/a&gt;. You can find his articles &lt;a href="http://www.innoq.com/blog/st/publications/"&gt;here&lt;/a&gt;. Using the web as it should be used with good URI's and GET/POST/PUT/DELETE methods seems very natural. The anti-patterns and patterns made it more clear what was meant with that.&lt;br /&gt;&lt;br /&gt;I just want to figure out how to apply this when the company forces you to use struts 1.X. Apparently &lt;a href="http://glenpeterson.blogspot.com/2008/03/searching-for-restful-solution-with.html"&gt;somebody else&lt;/a&gt; already tried to find this out. I have to try this!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-2372698259321033203?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/2372698259321033203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=2372698259321033203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2372698259321033203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2372698259321033203'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/restful-design-and-struts-1x.html' title='Restful design and struts 1.X'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-8601360741097087739</id><published>2008-12-10T12:01:00.001+01:00</published><updated>2008-12-10T12:04:52.730+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaFX'/><title type='text'>Devoxx keynote JavaFX</title><content type='html'>JavaFX, the next cool rich internet application, has come out last week so it wasn't a surprise that the keynote was about that. I already played with the preview before and what I saw that they provide for the designers, I think it will be a real contender for flex and silverlight.&lt;br /&gt;&lt;br /&gt;The only thing that Sun still needs to make this a succes, is a motivated and inspiring speaker. Choosing you chief software architect to present it may not be a good idea ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-8601360741097087739?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/8601360741097087739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=8601360741097087739' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/8601360741097087739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/8601360741097087739'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/devoxx-keynote-javafx.html' title='Devoxx keynote JavaFX'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-7109567549203090117</id><published>2008-12-09T13:05:00.002+01:00</published><updated>2008-12-09T13:10:38.663+01:00</updated><title type='text'>HTML5 websockets</title><content type='html'>The session about WebSockets (misnamed as being about Comet) was interesting to see where all the new web standards are going.  The people of &lt;a href="http://www.kaazing.org"&gt;Kaazing&lt;/a&gt; are emulating them since not much is implemented yet. As they get implemented, they will be used.&lt;br /&gt;WebSockets give a tcp socket to the browser client allowing all kinds of communication to many types of servers. Sounds promising and thanks to the emulation it is here now instead of 2022 (releasedate HTML5).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-7109567549203090117?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/7109567549203090117/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=7109567549203090117' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/7109567549203090117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/7109567549203090117'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/html5-websockets.html' title='HTML5 websockets'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-2996277240680615920</id><published>2008-12-09T12:57:00.002+01:00</published><updated>2008-12-09T13:04:47.288+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaEE'/><title type='text'>Developer productivity</title><content type='html'>Yesterday I followed the session "10 reasons why JavaEE development doesn't have to be painful". This Sun sponsored session talked a lot about how tools and fast appservers enhance developer productivity. This is the same as "Keep the developer in his stream of thoughts". A constant interruption of this thought stream because of restarts or waiting for the IDE to respond, is&lt;br /&gt;&lt;div style="text-align: left;" id="result_box" dir="ltr"&gt;disastrous for productivity.&lt;br /&gt;&lt;br /&gt;I talked at the &lt;a href="http://www.zeroturnaround.com/javarebel/"&gt;javarebel &lt;/a&gt;stand about this talk and there take was, what good is a fast starting appserver is deployment still takes long. By avoiding need to redeploy, they can make it still faster.&lt;br /&gt;&lt;br /&gt;It's more a  message to managers. If you want your developers to be productive, &lt;span style="font-weight: bold;"&gt;give them good tools on fast machines.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-2996277240680615920?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/2996277240680615920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=2996277240680615920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2996277240680615920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/2996277240680615920'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/developer-productivity.html' title='Developer productivity'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-4063784178452309379</id><published>2008-12-08T16:49:00.002+01:00</published><updated>2008-12-08T16:51:36.452+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='servlets'/><title type='text'>Servlet 3.0/JSF 2.0</title><content type='html'>Servlet 3.0 doesn't add that much (unless a lot was not told about in the session). The most mportant is making the web.xml easier to handle by having modularization (merging multiple web.xml's from different libraries), annotations and being able to add artifacts programmatically during deployment.&lt;br /&gt;The only other big addition is asynchronous requests. This makes it possible to have less thread usage when doing a long call (e.g. database call) or an asynchronous call (e.g. JMS message exchange). Another use case is keeping a connection open.&lt;br /&gt;&lt;br /&gt;JSF2 has a lot of changes with built-in facelets and AJAX, better exception handling, resource handling and state saving. Less XML is possible by using annotations and they still think about adding REST support. The conversation scope was moved to the webbeans proposal.&lt;br /&gt;&lt;br /&gt;My feeling is that JSF is way too complicated but maybe that is because of my lack of experience on it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-4063784178452309379?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/4063784178452309379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=4063784178452309379' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4063784178452309379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/4063784178452309379'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/servlet-30jsf-20.html' title='Servlet 3.0/JSF 2.0'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-3323094075991438206</id><published>2008-12-08T11:39:00.005+01:00</published><updated>2008-12-08T16:49:16.129+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Cancelled sessions</title><content type='html'>The two session is was going to follow were cancelled. The first "From XML to Java and back again" was replaced by a more general JPA session and a short bit about eclipse tooling for it (more specifically hibernate tooling but the DALI part was also interesting to see).&lt;br /&gt;&lt;br /&gt;I still picked up some things of the more general JPA session that was given by Alex Snaps who I know of the project I'm currently working on.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Understand the ORM tool you are using. This is a valuable lesson because otherwise you'll end up with strange behavior you don't understand. For example, that you have to maintain your bidirectional mapping yourself or more hibernate specific, that a filter is allowing you to only get back results from one specific database partition (happened to me and costed me a long debugging session). Another one is that bulk operations do not update the entity manager.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The @MapKey annotation I did not remember but seems useful if you want to find back a relationship using a specific key. I'm just wondering how this works when there is more than one object for a key. Can you use a Map&lt;key,&gt; object to put them in then? &lt;span style="font-weight: bold;"&gt;Apparently currently you can't. Maybe JPA2?&lt;/span&gt;&lt;br /&gt;&lt;/key,&gt;&lt;/li&gt;&lt;li&gt;Usage of @Version for optomistic locking.&lt;/li&gt;&lt;li&gt;Listeners for validation (pre), setting calculated values (post) or auditing (post). What other usage scenarios are possible?&lt;/li&gt;&lt;/ul&gt;The EM goes to the database if the transaction ends or when you flush inside a transaction. Thus when you make changes outside a transaction but with an open persistence context (still managed entities instead of detached entities), you have to open and close a connection to have these updates reflected in the database. If you close the persistence context, all updates after&lt;br /&gt;the last transaction end will be lost when the entity becomes detached. (You will have to merge the enities to still save the changes)&lt;br /&gt;&lt;br /&gt;The tools seem very useful providing validation, code completion en with hibernate tooling also query validation and testing. Also the integration with eclipse DTP  is well done.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-3323094075991438206?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/3323094075991438206/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=3323094075991438206' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3323094075991438206'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/3323094075991438206'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/cancelled-sessions.html' title='Cancelled sessions'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5962243442399061945.post-6062970255221899456</id><published>2008-12-05T13:08:00.004+01:00</published><updated>2008-12-05T15:44:21.994+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devoxx08'/><title type='text'>Devoxx next week</title><content type='html'>I'm going to &lt;a href="http://www.devoxx.be/display/JV08/Home"&gt;devoxx&lt;/a&gt; next week and I hope to kickstart this blog with all the interesting things I'll see there. It'll be my fourth visit in a row to what was JavaPolis but is now Devoxx. That's the advantage of actually living in Belgium.&lt;br /&gt;&lt;br /&gt;I still remember the first visit when it was a new world going open for me. I saw and learned a lot of new things back then. A whole difference with last year when I saw a lot of the same things of the year before. Hopefully this year will be different again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5962243442399061945-6062970255221899456?l=jwyseur.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jwyseur.blogspot.com/feeds/6062970255221899456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5962243442399061945&amp;postID=6062970255221899456' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6062970255221899456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5962243442399061945/posts/default/6062970255221899456'/><link rel='alternate' type='text/html' href='http://jwyseur.blogspot.com/2008/12/devoxx-next-week.html' title='Devoxx next week'/><author><name>Jeroen Wyseur</name><uri>http://www.blogger.com/profile/10361004799996836980</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='21' height='32' src='http://4.bp.blogspot.com/_ye7OBxEm_Ow/STl2BKiwfWI/AAAAAAAABF8/w7ZgRuQFy1Y/S220/pasfoto.jpg'/></author><thr:total>0</thr:total></entry></feed>
