<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tapestry 5 Blog</title>
	<atom:link href="http://blog.tapestry5.de/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tapestry5.de</link>
	<description>Thoughts on coding, technology and occasional stuff.</description>
	<lastBuildDate>Wed, 25 Jan 2012 18:00:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Hello, Kotlin!</title>
		<link>http://blog.tapestry5.de/index.php/2012/01/25/hello-kotlin/</link>
		<comments>http://blog.tapestry5.de/index.php/2012/01/25/hello-kotlin/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 21:09:48 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Kotlin]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2800</guid>
		<description><![CDATA[Last year JetBrains announced Kotlin &#8211; a statically-typed JVM-targeted programming language. The web-based Kotlin preview has been launched recently. Check out this demo to get the first impression. I got curious about the Kotlin programming language and attended a talk by Andrey Breslav at Devoxx 2011. Today I&#8217;m one of the lucky guys who got [...]]]></description>
			<content:encoded><![CDATA[<p>Last year <a title="JetBrains" href="http://www.jetbrains.com/">JetBrains</a> announced <a title="Kotlin Documentation" href="http://confluence.jetbrains.net/display/Kotlin/">Kotlin</a> &#8211; a statically-typed JVM-targeted programming language. The web-based Kotlin preview has been launched recently. Check out <a title="Kotlin Demo" href="http://kotlin-demo.jetbrains.com/">this demo</a> to get the first impression.</p>
<p>I got curious about the Kotlin programming language and attended a talk by Andrey Breslav at Devoxx 2011. Today I&#8217;m one of the lucky guys who got the access to the private EAP. After experimenting with Kotlin I decided to write a series of articles about this language in order to share with you my experience. This article is the first one and covers a basic &#8220;Hello, world&#8221; example. Let&#8217;s dive in.</p>
<h2>Initial Java program</h2>
<p>First we will create a Java program that we later convert into Kotlin. Here is our &#8220;Hello, world!&#8221; example in Java.</p>
<pre class="brush: kotlin;">package hello;

public class HelloWorld {
    private String name;

    public HelloWorld(String name) {
        this.name = name;
    }

    public String greet() {
        return "Hello, " + name;
    }

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld("Kotlin");

        System.out.println(helloWorld.greet());
    }
}</pre>
<h2>An equivalent Kotlin program</h2>
<p>Now let&#8217;s convert this example into a Kotlin program.</p>
<pre class="brush: kotlin;">package hello

class HelloWorld(var name: String){

    fun greet(): String {
        return "Hello, $name"
    }
}

fun main(args: Array&lt;String&gt;) {
    var helloWorld = HelloWorld("Kotlin")

    System.out?.println(helloWorld.greet())
}</pre>
<p>This tiny Kotlin program demonstrates a couple of Kotlin features. Let&#8217;s start with the constructor.</p>
<h3>Primary constructors</h3>
<p>In Kotlin you may declare constructors immediately in the class declaration. Note that the constructor in the example above initializes class properties without having a body. Such constructors are called <em>primary constructors</em>. </p>
<h3>Properties</h3>
<p>Do properties in Kotlin have the same meaning as in Java? In contrast to Java, Kotlin classes don&#8217;t have fields that are read/written using getters and setters. Instead Kotlin classes have properties: mutable properties are declared with the <strong>var</strong> (for variable) keyword and read-only properties are declared with the <strong>val</strong> (for value) keyword. In the example above the <em>HelloWorld</em> class has a mutable property named <em>name</em>. Note that the property is declared directly in the constructor. Because the property has been declared with <strong>var</strong> keyword, we can alter its value, as shown in the following example.</p>
<pre class="brush: kotlin;">var helloWorld = HelloWorld("Kotlin")
helloWorld.name = "Kotlin again"</pre>
<p>The value of the property may be changed by assigning it directly to the property. If we would have declared the property using then <strong>val</strong> keyword, assigning a new value would result in a compiler error. Also please note that there&#8217;s no <strong>new</strong> keyword in Kotlin.</p>
<h3>Functions</h3>
<p>Kotlin classes have functions that are declared with the <strong>fun</strong> keyword. A function may have parameters and may have a return type. The return type <em>Unit</em> is what <em>void</em> is in Java. If a function is not a &#8220;Single-expression functions&#8221; (to be covered in a later article) and returns <em>Unit</em>, then the return type may be omitted.</p>
<p>The <em>greet()</em> function in the example above returns a String value. Note that the returned String contains a  <em>template expression</em> that allows you to avoid ugly String concatenation using <em>+</em> operator. A template expression starts with a dollar sign ($). The value after <em>$</em> represents a named placeholder that is evaluated at runtime. In this example the expression refers to the <em>name</em> property.</p>
<h3>Null-Safety</h3>
<p>Did you notice the question mark (<em>?</em>) in the <em>System.out?.println</em> statement? Kotlin distinguishes between nullable and non-nullable references. The <strong>?.</strong> operator is called a <em>safe call</em>. It&#8217;s Kotlin&#8217;s way to avoid <em>NullPointerException</em>. If the expression on the left hand side refers to <em>null</em>, the expression on the right hand side is not executed. More on Null-Safety in some of the next articles about Kotlin.</p>
<p>And last but not least, did you notice that we didn&#8217;t use any semicolons?</p>
<h2>IDE support</h2>
<p>Does Kotlin have IDE support? Well, JetBrains is the company behind IDEA which is the best IDE for Java. But also Groovy and Scala support in IDEA is excellent. It&#8217;s natural that JetBrains provides IDE support for its own language. I played around with the Kotlin plugin for IDEA. It needs some final polishing but it is already quite usable. Here is a screenshot.</p>
<p><a href="http://blog.tapestry5.de/wp-content/uploads/2012/01/kotlin-autocompletion.png"><img class="aligncenter size-full wp-image-2829" title="kotlin-autocompletion" src="http://blog.tapestry5.de/wp-content/uploads/2012/01/kotlin-autocompletion.png" alt="" width="577" height="241" /></a></p>
<p>That&#8217;s it for now. In this article we cover a few basic Kotlin features. I hope you enjoyed it. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2012/01/25/hello-kotlin/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>JavaDoc Plugin For Component Reference Documentation</title>
		<link>http://blog.tapestry5.de/index.php/2011/11/09/javadoc-plugin-for-component-reference-documentation/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/11/09/javadoc-plugin-for-component-reference-documentation/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 18:24:54 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2773</guid>
		<description><![CDATA[Tapestry 5.3 release candidate is out and the final release is approaching. That&#8217;s why I want to share with you a new cool feature which will make your life easier. As a Tapestry user you surely know Tapestry&#8217;s component reference documentation. This documentation is generated using Tapestry&#8217;s Maven plugin. Many of Tapestry users, who are [...]]]></description>
			<content:encoded><![CDATA[<p>Tapestry 5.3 release candidate is out and the final release is approaching. That&#8217;s why I want to share with you a new cool feature which will make your life easier.</p>
<p>As a Tapestry user you surely know <a title="Component reference documentation" href="http://tapestry.apache.org/tapestry5.1/tapestry-core/ref/" target="_blank">Tapestry&#8217;s component reference documentation</a>. This documentation is generated using Tapestry&#8217;s Maven plugin. Many of Tapestry users, who are also Maven users, are using this plugin for their custom components. Unfortunately there was no solution for non-Maven users before Tapestry 5.3.</p>
<p>Starting with version 5.3 Tapestry provides a JavaDoc plugin which can be used to generate a component reference documentation as part of JavaDoc. An example is demonstrated in the following screenshot.</p>
<p style="text-align: center;"><a href="http://blog.tapestry5.de/wp-content/uploads/2011/08/component_ref.png"></a><a href="http://blog.tapestry5.de/wp-content/uploads/2011/08/component_ref.png"><img class="aligncenter size-large wp-image-2709" title="component_ref" src="http://blog.tapestry5.de/wp-content/uploads/2011/08/component_ref-1024x536.png" alt="" width="574" height="300" /></a></p>
<p>&nbsp;</p>
<p>Check out <a href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/BeanEditForm.html" target="_blank">this JavaDoc </a>to see what is possible with the new JavaDoc plugin.</p>
<p>What is needed to integrate a component reference into the JavaDoc? You just need to place <em>@tapestrydoc</em> on the component&#8217;s classes, as shown in the following example.</p>
<pre class="brush: java;">/**
 *  Here comes your JavaDoc...
 *
 * @tapestrydoc
 */
public class MyComponent {
   ...
}</pre>
<p>Additionally you need to use Tapestry&#8217;s taglet when generating the JavaDoc. For more details on JavaDoc Taglets see <a title="JavaDoc Taglets" href="http://download.oracle.com/javase/1.5.0/docs/guide/javadoc/taglet/overview.html" target="_blank">here</a>.</p>
<h2>Integration with Maven</h2>
<p>Now let&#8217;s see how to tell Maven&#8217;s JavaDoc plugin to use Tapestry&#8217;s taglet.</p>
<pre class="brush: xml;">&lt;project&gt;
  ...
  &lt;reporting&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-javadoc-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.8&lt;/version&gt;
        &lt;configuration&gt;
          ...
          &lt;taglet&gt;org.apache.tapestry5.javadoc.TapestryDocTaglet&lt;/taglet&gt;
          &lt;tagletArtifact&gt;
             &lt;groupId&gt;org.apache.tapestry&lt;/groupId&gt;                       
             &lt;artifactId&gt;tapestry-javadoc&lt;/artifactId&gt;                       
             &lt;version&gt;5.3-rc-3&lt;/version&gt;                   
          &lt;/tagletArtifact&gt;
          ...
        &lt;/configuration&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
    ...
  &lt;/reporting&gt;
  ...
&lt;/project&gt;</pre>
<p>That&#8217;s all. Tapestry&#8217;s JavaDoc plugin will do the rest and generate kickass JavaDocs.</p>
<h2>Integration with Gradle</h2>
<p>If you are interested how to generate the component reference with Gradle, please check out Tapestry&#8217;s <a title="build.gradle" href="http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/build.gradle?view=markup" target="_blank">build script</a>.</p>
<h2>Integration with Ant</h2>
<p>Honestly I have no idea how to do that as I didn&#8217;t use Ant for years. I&#8217;m pretty sure it is possible. Please read the <a title="Ant's JavaDoc plugin" href="http://ant.apache.org/manual/Tasks/javadoc.html" target="_blank">documentation for Ant&#8217;s JavaDoc plugin</a> for more details.</p>
<p>Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/11/09/javadoc-plugin-for-component-reference-documentation/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wanted: New Title For The Tapestry Book</title>
		<link>http://blog.tapestry5.de/index.php/2011/10/04/wanted-new-title-for-the-tapestry-book/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/10/04/wanted-new-title-for-the-tapestry-book/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 21:43:25 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2763</guid>
		<description><![CDATA[As already announced here, I&#8217;ll be publishing my Tapestry 5 book on my own. Because &#8220;Tapestry 5 in Action&#8221; sounds like a book published by Manning, I decided to choose another title. Coming up with a cool title is a challenge. That&#8217;s why I decided to ask the community for a new title for the [...]]]></description>
			<content:encoded><![CDATA[<p>As already announced <a href="http://blog.tapestry5.de/index.php/2011/09/23/publishing-tapestry-5-in-action-book-on-my-own/">here</a>, I&#8217;ll be publishing my Tapestry 5 book on my own. Because &#8220;Tapestry 5 in Action&#8221; sounds like a book published by Manning, I decided to choose another title.</p>
<p>Coming up with a cool title is a challenge. That&#8217;s why I decided to ask the community for a new title for the book. If you have a proposal, please drop me a line or comment on this post. Please post any idea you have (with or without subtitle), no matter how crazy it is. The author of the chosen title will be rewarded by a free PDF copy when the book is published.</p>
<p>Looking forward to see your ideas.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/10/04/wanted-new-title-for-the-tapestry-book/feed/</wfw:commentRss>
		<slash:comments>53</slash:comments>
		</item>
		<item>
		<title>Publishing Tapestry 5 in Action Book On My Own</title>
		<link>http://blog.tapestry5.de/index.php/2011/09/23/publishing-tapestry-5-in-action-book-on-my-own/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/09/23/publishing-tapestry-5-in-action-book-on-my-own/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 23:03:28 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2680</guid>
		<description><![CDATA[Some weeks ago I have been informed by Manning Publications that the Tapestry 5 in Action book is canceled. Based on MEAP sales Manning did a sales forecast. It looks like the book is financially not attractive enough. As you can imagine, this news made me upset. I was working on the book for about 8 [...]]]></description>
			<content:encoded><![CDATA[<p>Some weeks ago I have been informed by Manning Publications that the Tapestry 5 in Action book is canceled. Based on MEAP sales Manning did a sales forecast. It looks like the book is financially not attractive enough.</p>
<p>As you can imagine, this news made me upset. I was working on the book for about 8 month now. The half of the book (almost 250 pages) is already finished and I was looking forward to see the book in a final shape. After the MEAP has been started, I&#8217;ve got a lot of positive feedback regarding the book. It looks like the readers like the book&#8217;s content very much. </p>
<p>Manning&#8217;s decision was more than a surprise for me. After being upset for a couple of days I changed my opinion about Manning&#8217;s decision. Now I believe that this cancelation is the best thing that could happen to the book. I decided to publish the book on my own (probably on lulu.com). First of all, it is much more financially attractive for me. Secondly, I&#8217;ll be able to publish as many editions as I wish. I can update the book&#8217;s content every time a new Tapestry version is released. The only disadvantage is that lulu.com doesn&#8217;t provide something like an &#8220;early access program&#8221; so that the readers will need to wait until the book is finished.</p>
<p>If you was one of the MEAP customers who bought the Tapestry 5 in Action book, there is no reason to be sad. The book is going to be published. I promise you. </p>
<p>Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/09/23/publishing-tapestry-5-in-action-book-on-my-own/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Scheduling Jobs With Tapestry</title>
		<link>http://blog.tapestry5.de/index.php/2011/09/18/scheduling-jobs-with-tapestry/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/09/18/scheduling-jobs-with-tapestry/#comments</comments>
		<pubDate>Sun, 18 Sep 2011 10:24:02 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2744</guid>
		<description><![CDATA[Frequently web applications have a requirement to execute some business logic which is not bound to any HTTP request. For example, you might want to execute some periodic maintenance job to cleanup the database or a job sending messages to your users. In this article I&#8217;ll show you how to register jobs to be executed by Tapestry without [...]]]></description>
			<content:encoded><![CDATA[<p>Frequently web applications have a requirement to execute some business logic which is not bound to any HTTP request. For example, you might want to execute some periodic maintenance job to cleanup the database or a job sending messages to your users. In this article I&#8217;ll show you how to register jobs to be executed by Tapestry without blocking any incoming HTTP request.</p>
<h2>Interval Jobs</h2>
<p>Imagine you have a <em>CleanupService</em> service to be executed for database cleanup. The service&#8217;s interface is shown in the following example. The service implementation details are not interesting for this article as they are very specific to your application.</p>
<pre class="brush: java;">public interface CleanupService {
    void clean();
}</pre>
<p>Now let&#8217;s schedule a periodic execution of the cleanup at application&#8217;s startup. This is accomplished by contributing to the <em>RegistryStartup</em> service&#8217;s configuration, as shown in the following example.</p>
<pre class="brush: java;">public class AppModule {

    @Startup
    public static void scheduleJobs(
                   PeriodicExecutor executor,
                   final CleanupService cleanupService) {

        executor.addJob(
            new IntervalSchedule(300000L),
            "Cleanup Job",
            new Runnable() {
                public void run() {
                    cleanupService.clean();
                }
            });
    }
}</pre>
<p>As of Tapestry 5.3 the <em>PeriodicExecutor</em> service can be used to schedule jobs. In the example above, this service is injected into a startup method. The service&#8217;s <em>addJob</em> method is used to register jobs to be executed.This method takes three parameters:</p>
<ol>
<li>Instance of <em>Schedule</em>: defines when to execute the next job</li>
<li>Name used in debugging output related to the job</li>
<li>Instance of <em>Runnable</em> that represents the work to be done</li>
</ol>
<p>In the example above, a <em>IntervalSchedule</em> instance is used to schedule a job to be executed every 300000 milliseconds (5 minutes). Note that the <em>Runnable</em> is just a wrapper around the <em>CleanupService</em>.</p>
<h2>Using CRON expressions</h2>
<p>Instead of defining intervals for job executions, Tapestry also allows you to use CRON expressions, such as described <a title="Quartz" href="http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger">here</a>. Note that Tapestry uses the CRON parser from the <a title="Quartz" href="http://www.quartz-scheduler.org/">Quartz Scheduler</a> without depending on it.</p>
<p>The following example demonstrates how to use CRON expressions.</p>
<pre class="brush: java;">public class AppModule {

    @Startup
    public static void scheduleJobs(
                   PeriodicExecutor executor,
                   final CleanupService cleanupService) {

        executor.addJob(
            new CronSchedule("0 0/5 14 * * ?"),
            "Cleanup Job",
            new Runnable() {
                public void run() {
                    cleanupService.clean();
                }
            });
    }
}</pre>
<p>In the example above, a job is registered to be executed every 5 minutes starting at 2pm and ending at 2:55pm, every day.</p>
<p>Happy scheduling.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/09/18/scheduling-jobs-with-tapestry/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tapestry 5.3 Preview</title>
		<link>http://blog.tapestry5.de/index.php/2011/08/22/tapestry-5-3-preview/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/08/22/tapestry-5-3-preview/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 08:37:08 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2689</guid>
		<description><![CDATA[The Tapestry team has been very busy in the last months and it looks like Tapestry 5.3 goes Beta. While we are working on fixing last minor issues before version 5.3 becomes generally available, I want to share with you some of the new upcoming features. From the user perspective Tapestry 5.3 will be the [...]]]></description>
			<content:encoded><![CDATA[<p>The Tapestry team has been very busy in the last months and it looks like Tapestry 5.3 goes Beta. While we are working on fixing last minor issues before version 5.3 becomes generally available, I want to share with you some of the new upcoming features.</p>
<p>From the user perspective Tapestry 5.3 will be the most attractive release since 5.0. This article gives you a short overview.</p>
<h2>New Components</h2>
<p>Several components has been added to the core library:</p>
<ul>
<li><em>Kaptcha / KaptchaField</em>: Allow you to protect your forms from spam.</li>
<li><em>Tree</em>: Used to render a recursive tree structure, with expandable/collapsable/selectable nodes.</li>
<li><em>Dynamic</em>: An awesome component allowing a component to render itself differently at different times, by making use of an external template file. More details on this component follow in the next post</li>
<li><em>Checklist</em>: Multiple selection component. Generates a UI consisting of a list of check boxes. This component is used as alternative to the <em>Palette</em> component.</li>
<li><em>Alerts</em>: Used to display alerts.</li>
</ul>
<h2>Alerts</h2>
<p>In the past the only way to present some messages to the user was to persist some page properties using the <em>flash</em> strategy. Now Tapestry provides a central mechanism for handling user alerts: the <em>AlertManager</em> service and the Alerts component. Using <em>AlertManager</em> service you can add alerts which are presented to the user using the <em>Alerts</em> component. Alerts can be added during both traditional and Ajax requests, and may be transient (displayed for a few seconds), normal, or sticky (persist until the user expressly dismisses them). Alerts support three severities: info, warn(ing) and error; the look and feel can be customized by overriding Tapestry&#8217;s default CSS rules.</p>
<h2>Template Skinning</h2>
<p>I discussed template skinning feature in <a href="http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/" target="_blank">this article</a>.</p>
<h2>Improved Exception Reporting</h2>
<p>Tapestry is known to provide excellent messages when something goes wrong. In version 5.3, the exception reporting has been improved for Ajax requests. Please watch <a href="http://tapestry.apache.org/2011/08/16/tapestry-53-exception-reporting.html" target="_blank">this screencast</a> for more details.</p>
<h2>New JavaScript Abstraction Layer</h2>
<p>As you probably know, Tapestry is stuck with using <a href="http://www.prototypejs.org/" target="_blank">Prototype</a> and <a href="http://script.aculo.us/" target="_blank">Scriptaculous</a> for backward compatibility reasons. A lot of Tapestry users has been complaining about missing support of <a href="http://jquery.com/" target="_blank">jQuery</a>. Those of you, how can&#8217;t live without jQuery are probably using <a href="https://github.com/got5/tapestry5-jquery" target="_blank">this Tapestry/jQuery</a> library which allows you to get rid of <a href="http://www.prototypejs.org/" target="_blank">Prototype</a> and <a href="http://script.aculo.us/" target="_blank">Scriptaculous</a>.</p>
<p>Breaking backward compatibility with existing apps just by rewriting the client-side code to jQuery is not an option. Also tying Tapestry to jQuery wouldn&#8217;t be a good decision. If yet another JavaScript library will become successful next year and everybody starts to migrate, you are stuck again. A much better solution is to provide an abstraction layer which allows you to use any JavaScript library you like just by replacing a couple of files. Some work has already been done in Tapestry 5.3. The transition is done gradually and will be finalized in version 5.4.</p>
<h2>Improved Ajax</h2>
<p>The <em>MultiZoneUpdate</em> class has been deprecated in favor of <em>AjaxResponseRenderer</em> service. This service manages the rendering of a partial page render as part of an Ajax response. Let&#8217;s see a simple example.</p>
<pre class="brush: java;">public class AjaxDemo {
    @Inject
    private Block block;

    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @Inject
    @Path("MultiZoneUpdateDemo.js")
    private Asset library;

    Object onActionFromUpdate() {
        ajaxResponseRenderer.addRender("zone", block);

        ajaxResponseRenderer.addCallback(
                    new JavaScriptCallback() {
            public void run(JavaScriptSupport support) {

                support.importJavaScriptLibrary(library);
                support.addInitializerCall(
                     "writeMessageTo",
                     new JSONObject("id", "message",
                                    "message", "Updated"));
         }
        });
    }
}</pre>
<p>As you can see, the new API allows us to update a zone with the content from a renderer (such as a <em>Block</em>, <em>Component</em> or other object that can be coerced to <em>RenderCommand</em>). It is also possible to queue a <em>JavaScriptCallback</em> to be executed during the partial markup render. In this example the callback is used to import a JavaScript library as part of the rendered page and to add a call to a client-side function inside the <em>Tapestry.Initializer</em> namespace.</p>
<h2>JSR 330 Integration</h2>
<p>Starting from Tapestry 5.3, it&#8217;s possible to use JSR-330 annotations for injection. Using the standard annotations, your code in the service layer doesn&#8217;t need to depend on Tapestry. Please read <a href="http://tapestry.apache.org/using-jsr-330-standard-annotations.html" target="_blank">this article</a> for more details.</p>
<h2>JPA 2 Integration</h2>
<p>Finally, Tapestry provides a native JPA 2 integration. How does it differ from <a href="http://tynamo.org/tapestry-jpa+guide" target="_blank">Tynamo&#8217;s JPA integration</a>? First of all, it is maintained by the Tapestry team, that will ensure the backward compatibility with future releases. Secondly, it provides some features that were not available in Tynamo. For example, you can have multiple persistence units in the same application. Furthermore, Tapestry allows you to configure JPA without XML. Read <a href="http://tapestry.apache.org/integrating-with-jpa.html" target="_blank">this article</a> for more details.</p>
<h2>JavaScript and CSS Compression</h2>
<p>A module integrating Yahoo&#8217;s <a href="http://developer.yahoo.com/yui/compressor/" target="_blank">YUI Compressor</a> has been added. This library allows you to compress your JavaScript and CSS.</p>
<h2>Component Reference</h2>
<p>Great news for component developers. Starting with Tapestry 5.3 generating a component reference will be as easy as writing JavaDoc. You no longer need to use Maven. Instead you just need to place <em>@tapestrydoc</em> in the component&#8217;s class JavaDoc. That&#8217;s all. The following screenshot demonstrates the result.</p>
<p style="text-align: center;"><a href="http://blog.tapestry5.de/wp-content/uploads/2011/08/component_ref.png"><img class="aligncenter size-full wp-image-2709" title="component_ref" src="http://blog.tapestry5.de/wp-content/uploads/2011/08/component_ref.png" alt="" width="634" height="332" /></a></p>
<h2>Scheduling Jobs</h2>
<p>The <em>PeriodicExecutor</em> service has been introduced to allow execution of scheduled jobs. The following example demonstrates how to schedule a job to be executed every 5 minutes.</p>
<pre class="brush: java;">public class PeriodicExecutorDemo {

    public PeriodicExecutorDemo(PeriodicExecutor executor) {

       executor.addJob(
          new IntervalSchedule(300000L),
          "MyJob",
           new Runnable () { void run() { ... }; } );
    }
}</pre>
<p>&nbsp;</p>
<h2>Plastic</h2>
<p>Plastic is a bytecode transformation library based on ASM. Plastic is designed to simplify the run-time transformation of Java classes. The most parts of the internal API using Javassist has been rewritten to use Plastic. The Javassist-based API has been deprecated and will be removed in Tapestry 5.4. Starting from version 5.4 Tapestry will not longer depend on Javassist. Yay!</p>
<p>&nbsp;</p>
<p>Have fun with Tapestry and stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/08/22/tapestry-5-3-preview/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Template Skinning</title>
		<link>http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 13:14:46 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2646</guid>
		<description><![CDATA[In this article I want to share with you a new awesome Tapestry feature introduced in 5.3. This feature allows you to provide different skins for a single page by creating several templates. These different templates are used by Tapestry to render the same page in a special way for different clients. For example, when [...]]]></description>
			<content:encoded><![CDATA[<p>In this article I want to share with you a new awesome Tapestry feature introduced in 5.3. This feature allows you to provide different skins for a single page by creating several templates. These different templates are used by Tapestry to render the same page in a special way for different clients. For example, when developing a web application for both standard and mobile clients you might need to render the same page different depending on the current client. So, you need to create two different templates for each page and choose one of them depending on the user agent sent by the client.</p>
<p>In the <a href="http://blog.tapestry5.de/index.php/2010/08/06/extending-template-lookup-mechanism/" target="_blank">Extending Template Lookup Mechanism</a> article I described how to accomplish that in Tapestry 5.2. The described approach was not ideal because of the issue with Tapestry&#8217;s template cache.  Anyway, the new API in Tapestry 5.3 is cool. Let&#8217;s see it in action. First, let me show you how the template cache works.</p>
<h2>Template cache</h2>
<p>As you probably know the structure of Tapestry&#8217;s pages is static. I don&#8217;t want to cover the reasons for the static structure in this article; please read Tapestry&#8217;s documentation for more details. Because of the static structure the instances of Tapestry pages can be cached. You can imagine the page cache as a multidimensional coordinate system. By default the cache is two-dimensional; one of the axes is for page classes, the other for locales. If you have <em>n</em> pages in your application and you configured Tapestry to support <em>m</em> locales, then there might be maximal <em>n * m</em> page instances in the cache, as illustrated in the following figure.<br />
<a href="http://blog.tapestry5.de/wp-content/uploads/2011/06/page_cache.png"><img class="aligncenter size-full wp-image-2648" title="page_cache" src="http://blog.tapestry5.de/wp-content/uploads/2011/06/page_cache.png" alt="" width="352" height="288" /></a></p>
<p>The new API in Tapestry 5.3 allows you to add additional dimensions to the cache matrix. For example, a new dimension might be the client. Let&#8217;s say we have two different clients: standard and mobile. In this case the maximal number of page instances is <em>n * m * 2</em>, as shown in the following example.</p>
<p><a href="http://blog.tapestry5.de/wp-content/uploads/2011/06/page_cache_3d.png"><img class="aligncenter size-full wp-image-2651" title="page_cache_3d" src="http://blog.tapestry5.de/wp-content/uploads/2011/06/page_cache_3d.png" alt="" width="451" height="427" /></a></p>
<p>Now let&#8217;s explore how to provide client-specific templates for pages and how to add additional dimensions to the page cache.</p>
<h2>Locating component resources</h2>
<p>The <em>ComponentResourceLocator</em> interface is the central service for locating resources for components. The<em> </em>interface defines two methods:</p>
<ul>
<li>locateTemplate: Locates the template for a component (including pages and base classes).</li>
<li>locateMessageCatalog: Locates the message catalog for a component.</li>
</ul>
<p>Both methods take a <em>ComponentResourceSelector</em> parameter. Briefly speaking, <em>ComponentResourceSelector</em> defines the axes to be used by the page cache.</p>
<p>The default implementation of the <em>ComponentResourceLocator</em> interface reads only the <em>Locale</em> from the passed  <em>ComponentResourceSelector </em>instance, so that the cache is 2-dimensional. Let&#8217;s create our own implementation of <em>ComponentResourceSelector </em>interface which will make use of a third dimension. The following example demonstrates how to accomplish that.</p>
<pre class="brush: java;">public class CustomComponentResourceLocator
              implements ComponentResourceLocator {

    private final ComponentResourceLocator delegate;

    private final Resource contextRoot;

    private final ComponentClassResolver resolver;

    public CustomComponentResourceLocator(
          ComponentResourceLocator delegate,
          Resource contextRoot,
          ComponentClassResolver resolver) {

        this.delegate = delegate;
        this.contextRoot = contextRoot;
        this.resolver = resolver;
    }

    @Override
    public Resource locateTemplate(
              ComponentModel model,
              ComponentResourceSelector selector) {

        if(!model.isPage()) {
            return null;
        }

        String className = model.getComponentClassName();

        String logicalName =
              resolver.resolvePageClassNameToPageName(className);

        Client client = selector.getAxis(Client.class);

        if (client == Client.MOBILE) {
            String path = String.format("mobile/%s.%s",
                     logicalName,
                     TapestryConstants.TEMPLATE_EXTENSION);

            Resource resource = contextRoot.forFile(path);

            if (resource.exists()) {
                return resource.forLocale(selector.locale);
            }
        }

        return delegate.locateTemplate(model, selector);
    }

    @Override
    public List&lt;Resource&gt; locateMessageCatalog(
              Resource baseResource,
              ComponentResourceSelector selector) {

        return delegate.locateMessageCatalog(
                               baseResource, selector);
    }
}</pre>
<p>As you can see, our implementation is a decorator for the original <em>ComponentResourceLocator</em> implementation. Inside the <em>locateTemplate()</em> method the passed <em>ComponentResourceSelector</em> instance is used to retrieve the third axis which is of type <em>Client</em>. If the current client is <em>Client.MOBILE</em>, we try to locate a special template from the <em>mobile</em> sub-folder. If a page template exists in this sub-folder, it is returned. Otherwise we delegate to the original <em>ComponentResourceLocator </em>implementation in order to return the default template.</p>
<p>Next, we need to decorate the built-in <em>ComponentResourceLocator</em> by providing a <em>decorate</em> method in the <em>AppModule</em> class.</p>
<pre class="brush: java;">public class AppModule {

   @Decorate(serviceInterface = ComponentResourceLocator.class)
   public static Object customComponentResourceLocator(
           ComponentResourceLocator delegate,
           @ContextProvider AssetFactory assetFactory,
           ComponentClassResolver componentClassResolver) {

        return new CustomComponentResourceLocator(
                      delegate,
                      assetFactory.getRootResource(),
                      componentClassResolver);
    }
}</pre>
<p>Where does the <em>Client</em> axes come from? This is where the <em>ComponentRequestSelectorAnalyzer</em> service comes into play. This service has been introduced in Tapestry 5.3 and is responsible for determining the <em>ComponentResourceSelector</em> for the current request. The default implementation of the interface creates a 2-dimensional <em>ComponentResourceSelector</em> instance; the axes are page class and <em>Locale</em> for the current request. Let&#8217;s implement our own <em>ComponentRequestSelectorAnalyzer </em>implementation which will return a 3-dimensional <em>ComponentResourceSelector</em>. The following example demonstrates how to accomplish that.</p>
<pre class="brush: java;">public class CustomComponentRequestSelectorAnalyzer
                implements ComponentRequestSelectorAnalyzer {

    private final ThreadLocale threadLocale;

    private ClientService clientService;

    public CustomComponentRequestSelectorAnalyzer(
          ThreadLocale threadLocale,
          ClientService clientService) {

        this.threadLocale = threadLocale;
        this.clientService = clientService;
    }

    @Override
    public ComponentResourceSelector buildSelectorForRequest() {

       Locale locale = threadLocale.getLocale();
       Client client = clientService.getCurrentClient();

        return new ComponentResourceSelector(locale)
                      .withAxis(Client.class, client);
    }
}</pre>
<p>As you can see, we create a <em>ComponentResourceSelector</em> by passing the current <em>Locale</em> to the constructor. Then we add an additional axis of type <em>Client</em>. The current <em>Client</em> is retrieved from <em>ClientService</em> which is your custom service. Probably you would implement such a service by examining the <em>User-Agent</em> HTTP header. Anyway, the implementation details of <em>ClientService</em> are not interesting for this article.</p>
<p>Finally, we need to override the original implementation of <em>ComponentRequestSelectorAnalyzer</em> service by contributing to the <em>ServiceOverride</em> service&#8217;s configuration, as shown in the following example.</p>
<pre class="brush: java;">public class AppModule {

    public static void bind(ServiceBinder binder) {
        binder.bind(ClientService.class,
                    ClientServiceImpl.class);

        binder.bind(ComponentRequestSelectorAnalyzer.class,
                    CustomComponentRequestSelectorAnalyzer.class)
             .withId("CustomComponentRequestSelectorAnalyzer");
    }

     @Contribute(ServiceOverride.class)
    public static void overrideSelectorAnalyzer(
           MappedConfiguration&lt;Class, Object&gt; cfg,

          @InjectService("CustomComponentRequestSelectorAnalyzer")
          ComponentRequestSelectorAnalyzer analyzer){

           cfg.add(ComponentRequestSelectorAnalyzer.class, analyzer);
    }
}</pre>
<p>That&#8217;s all. Whenever you ClientService determines that the current client is a mobile devices and returns Client.MOBILE, Tapestry will look for a template in the <em>mobile</em> sub-folder in the context root. If found it is used to render the response for the mobile device. If not found, the default template is used.</p>
<p>Have fun with Tapestry and stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/06/24/template-skinning/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>On Tapestry&#8217;s Performance</title>
		<link>http://blog.tapestry5.de/index.php/2011/06/14/on-tapestrys-performance/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/06/14/on-tapestrys-performance/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 07:07:35 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2595</guid>
		<description><![CDATA[Tapestry claims to be performant and scalable. You want a proof? Than read this great post. The author compares the performance of Rails, Wicket, Grails, Play, Tapestry, Lift, JSP, Context. It is not a surprise that Tapestry outperformed the most of the competitors. Here are the results: For more details on the benchmark please read the original article. [...]]]></description>
			<content:encoded><![CDATA[<p>Tapestry claims to be performant and scalable. You want a proof? Than read <a href="http://www.jtict.com/blog/rails-wicket-grails-play-lift-jsp/" target="_blank">this great post</a>. The author compares the performance of Rails, Wicket, Grails, Play, Tapestry, Lift, JSP, Context. It is not a surprise that Tapestry outperformed the most of the competitors. Here are the results:</p>
<p style="text-align: center;"><a href="http://blog.tapestry5.de/wp-content/uploads/2011/06/results_numbers.jpg"><img class="size-full wp-image-2601 aligncenter" title="results_numbers" src="http://blog.tapestry5.de/wp-content/uploads/2011/06/results_numbers.jpg" alt="" width="511" height="445" /></a></p>
<p style="text-align: center;"><a href="http://blog.tapestry5.de/wp-content/uploads/2011/06/conc_users_graph.jpg"><img class="size-full wp-image-2597 aligncenter" title="conc_users_graph" src="http://blog.tapestry5.de/wp-content/uploads/2011/06/conc_users_graph.jpg" alt="" width="604" height="363" /></a></p>
<p>For more details on the benchmark please read <a href="http://www.jtict.com/blog/rails-wicket-grails-play-lift-jsp/" target="_blank">the original article</a>.</p>
<p>Two years ago Peter Thomas made a <a href="http://ptrthomas.wordpress.com/2009/09/14/perfbench-update-tapestry-5-and-grails/" target="_blank">similar comparison</a> and the result was not that good for Tapestry. It seems like two year ago Wicket was ahead of  Tapestry and Grails. But the recent comparison shows that Wicket&#8217;s performance is the worst. What could be the reason for such different results? First of all, I believe that Peter Thomas&#8217; comparison was not accurate. Peter is known to be a Wicket lover. When the comparison is made by an unbiased person, then the results look completely different. Another possible reason could be that Tapestry improved in the last two years a lot. Removal of page pooling and other important changes might be the reason for that. However, seeing that Tapestry&#8217;s performance just rocks is a satisfaction.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/06/14/on-tapestrys-performance/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>XML-less JPA configuration</title>
		<link>http://blog.tapestry5.de/index.php/2011/05/26/xml-less-jpa-configuration/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/05/26/xml-less-jpa-configuration/#comments</comments>
		<pubDate>Thu, 26 May 2011 07:31:36 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2551</guid>
		<description><![CDATA[In the last post I gave you a short preview of the Tapestry/JPA integration library in the upcoming 5.3 release. In this post I&#8217;m going to show a new feature that I added yesterday. You will see that configuring JPA with Tapestry is much more simple than defined in the JPA specification. The persistence.xml file [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a title="JPA support in Tapestry" href="http://blog.tapestry5.de/index.php/2011/05/25/jpa-support-in-tapestry/" target="_blank">last post</a> I gave you a short preview of the Tapestry/JPA integration library in the upcoming 5.3 release. In this post I&#8217;m going to show a new feature that I added yesterday. You will see that configuring JPA with Tapestry is much more simple than defined in the JPA specification.</p>
<p>The <em>persistence.xm</em>l file is the standard configuration file in JPA used to define the persistence units. Let&#8217;s explore the following persistence descriptor using a non-JTA data source.</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"
             version="2.0"&gt;
   &lt;persistence-unit name="Blue"
                     transaction-type="RESOURCE_LOCAL"&gt;

      &lt;non-jta-data-source&gt;
         jdbc/JPATest
      &lt;/non-jta-data-source&gt;

      &lt;properties&gt;
         &lt;property name="eclipselink.ddl-generation"
                   value="create-tables"/&gt;
         &lt;property name="eclipselink.logging.level"
                   value="fine"/&gt;
      &lt;/properties&gt;
   &lt;/persistence-unit&gt;

&lt;/persistence&gt;</pre>
<p>Now let&#8217;s see how to provide an equivalent JPA configuration without using any XML descriptors. This can be accomplished by making a contribution to the <em>EntityManagerSource</em> service.</p>
<pre class="brush: java;">public class AppModule {

   @Contribute(EntityManagerSource.class)
   public static void configurePersistenceUnitInfos(
      MappedConfiguration&lt;String,PersistenceUnitConfigurer&gt;
      cfg) {

      PersistenceUnitConfigurer configurer
                 = new PersistenceUnitConfigurer() {

         public void configure(
                  TapestryPersistenceUnitInfo unitInfo) {

            unitInfo.nonJtaDataSource("jdbc/JPATest")
               .addProperty("eclipselink.ddl-generation",
                            "create-tables")
               .addProperty("eclipselink.logging.level",
                            "fine");
         }
     };

     cfg.add("Blue", configurer);
   }
}</pre>
<p>The <em>EntityManagerSource</em> service’s configuration is a map in which the keys are persistence unit names and the values are <em>PersistenceUnitConfigurer</em> instances. In other words, a <em>PersistenceUnitConfigurer</em> instance is associated with a persistence unit to be configured. The <em>TapestryPersistenceUnitInfo</em> instance passed to the <em>PersistenceUnitConfigurer</em> holds the persistence unit metadata for use by the persistence provider. It may represent a persistence unit defined in the  <em>persistence.xml</em> file or an empty persistence unit. Confused? Let me clarify it.</p>
<p>If the contribution key matches a persistence unit defined in the <em>persistence.xml</em> file, then the passed <em>TapestryPersistenceUnitInfo</em> instance is pre-filled with the metadata from <em>persistence.xml</em>. This metadata can be modified programmatically inside a <em>PersistenceUnitConfigurer</em>. If <em>persistence.xml</em> file is not present or the contribution key doesn&#8217;t match any persistence unit, the passed <em>TapestryPersistenceUnitInfo</em> instance is empty. This way Tapestry allows you to configure JPA without writing XML descriptor files.</p>
<p>Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/05/26/xml-less-jpa-configuration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JPA support in Tapestry</title>
		<link>http://blog.tapestry5.de/index.php/2011/05/25/jpa-support-in-tapestry/</link>
		<comments>http://blog.tapestry5.de/index.php/2011/05/25/jpa-support-in-tapestry/#comments</comments>
		<pubDate>Tue, 24 May 2011 21:15:12 +0000</pubDate>
		<dc:creator>Igor Drobiazko</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://blog.tapestry5.de/?p=2479</guid>
		<description><![CDATA[In this article I&#8217;m going to describe the Tapestry/JPA 2 Integration library that provides out-of-the-box support for using JPA 2 as the back end for normal CRUD style Tapestry applications. I added this library to Tapestry&#8217;s trunk some weeks ago but didn&#8217;t have any time to write an article about it. Now that we are [...]]]></description>
			<content:encoded><![CDATA[<p>In this article I&#8217;m going to describe the Tapestry/JPA 2 Integration library that provides out-of-the-box support for using JPA 2 as the back end for normal CRUD style Tapestry applications. I added this library to Tapestry&#8217;s trunk some weeks ago but didn&#8217;t have any time to write an article about it. Now that we are close to a first 5.3 release, I would like to give you a preview of this library.</p>
<h2>Configuring JPA</h2>
<p>The <em>persistence.xml</em> file is the standard configuration file in JPA used to define the persistence units. By default, this file is expected to be located on the classpath in the <em>META-INF</em> directory. Tapestry reads this file to create the <em>EntityManagerFactory</em>. The following example demonstrates a <em>persistence.xml</em> file.</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"
             version="2.0"&gt;
   &lt;persistence-unit name="Red"
                     transaction-type="RESOURCE_LOCAL"&gt;
       &lt;properties&gt;
          &lt;property name="javax.persistence.jdbc.driver"
                    value="org.h2.Driver" /&gt;
          &lt;property name="javax.persistence.jdbc.url"
                    value="jdbc:h2:mem:test" /&gt;
          &lt;property name="javax.persistence.jdbc.username"
                    value="sa" /&gt;
          &lt;property name="eclipselink.ddl-generation"
                    value="create-tables"/&gt;
          &lt;property name="eclipselink.logging.level"
                    value="fine"/&gt;
      &lt;/properties&gt;
   &lt;/persistence-unit&gt;

   &lt;persistence-unit name="Blue"
                     transaction-type="RESOURCE_LOCAL"&gt;
      &lt;non-jta-data-source&gt;
         jdbc/JPATest
      &lt;/non-jta-data-source&gt;
   &lt;/persistence-unit&gt;

&lt;/persistence&gt;</pre>
<p>Note that you need to provide unique names for persistence units. In the example above we defined two persistence units named <em>Red</em> and <em>Blue</em>.</p>
<p>If you want to place the <em>persistence.xml</em> file in an other directory or name it arbitrarily, you can make a contribution to the <em>SymbolProvider</em> service, as shown in the following example. This is a quite useful feature if you want to use a different persistence descriptor for tests.</p>
<pre class="brush: java;">public class AppModule {

   @Contribute(SymbolProvider.class)
   @ApplicationDefaults
   public static void provideFactoryDefaults(
       MappedConfiguration&lt;String, String&gt; configuration) {

      configuration.add(
            JpaSymbols.PERSISTENCE_DESCRIPTOR,
            "/jndi-datasource-persistence-unit.xml");
   }
}</pre>
<p>For each of the persistence units defined in the <em>persistence.xml</em> file Tapestry creates a <em>TapestryPersistenceUnitInfo</em>. The interface <em>TapestryPersistenceUnitInfo</em> is mutable extension of the <em>PersistenceUnitInfo</em> interface which allows you to configure a persistence unit programmatically. This can be accomplished by making a contribution to the <em>EntityManagerSource</em> service, as shown in the following example.</p>
<pre class="brush: java;">public class AppModule {

   @Contribute(EntityManagerSource.class)
   public static void configurePersistenceUnitInfos(
            MappedConfiguration&lt;String,PersistenceUnitConfigurer&gt;
            cfg) {

      PersistenceUnitConfigurer configurer
                 = new PersistenceUnitConfigurer() {

         public void configure(
                  TapestryPersistenceUnitInfo unitInfo) {
            unitInfo.addManagedClass(User.class);
         }
      };

      cfg.add("Blue", configurer);
   }
}</pre>
<p>The <em>EntityManagerSource</em> service&#8217;s configuration is a map in which a persistence unit name is associated with a <em>PersistenceUnitConfigurer</em> instance. A <em>PersistenceUnitConfigurer</em> is used to configure a <em>TapestryPersistenceUnitInfo</em> that has been read from the <em>persistence.xml</em> file.</p>
<h2>Automatically adding managed classes</h2>
<p>If only a single persistence unit is defined, Tapestry scans the  <em>application-root-package.entities</em> package. The classes in that package are automatically added as managed classes to the defined persistence unit.</p>
<p>If you have additional packages containing entities, you may contribute them to the <em>JpaEntityPackageManager</em> service configuration.</p>
<pre class="brush: java;">public class AppModule {

   @Contribute(JpaEntityPackageManager.class)
   public static void providePackages(
            Configuration&lt;String&gt; configuration) {
      configuration.add("org.example.myapp.domain");
   }
}</pre>
<p>You may add as many packages as you wish.</p>
<h2>Injecting the EntityManager into page and component classes</h2>
<p>The created entity managers can be injected into page and component classes.  Depending on whether more than one persistence unit has been defined, the way to inject <em>EntityManager</em> varies slightly.</p>
<p>Let&#8217;s start with a simple scenario, where only a single persistence unit is defined. In this case, an <em>EntityManager</em> can be injected using the <em>@Inject</em> annotation.</p>
<pre class="brush: java;">public class CreateAddress {

   @Inject
   private EntityManager entityManager;

   @Property
   private Address address;

   @CommitAfter
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
<p>Alternatively, you can use the <em>@PersistenceContext</em> annotation to get the <em>EntityManager</em> injected into a page or component.</p>
<pre class="brush: java;">public class CreateAddress {

   @PersistenceContext
   private EntityManager entityManager;

   @Property
   private Address address;

   @CommitAfter
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
<p>If you have multiple instances of persistence-unit defined in the same application, you need to explicitly tell Tapestry which persistence unit you want to get injected. So,  just placing <em>@Inject</em> annotation on the injection place is not sufficient.</p>
<pre class="brush: java;">public class CreateAddress {

   @PersistenceContext(unitName = "Blue")
   private EntityManager entityManager;

   @Property
   private Address address;

   @CommitAfter
   @PersistenceContext(unitName = "Blue")
   void onSuccess() {
      entityManager.persist(address);
   }
}</pre>
<p>In the example above, the <em>@PersistenceContext</em> annotation&#8217; s <em>name</em> attribute is used to explicitly define the name of the unit to inject.</p>
<h2>Injecting EntityManager into services</h2>
<p>While component injection occurs only on fields, the injection in the IoC layer may be triggered by a  field or a constructor. The following example demonstrates field injection, when a single persistence unit is defined in the persistence descriptor.</p>
<pre class="brush: java;">public class UserDAOImpl implements UserDAO {
   @Inject
   private EntityManager entityManager;

   ...
}</pre>
<p>The constructor injection is demonstrated in the following example.</p>
<pre class="brush: java;">public class UserDAOImpl implements UserDAO {

   private EntityManager entityManager;

   public UserDAOImpl(EntityManager entityManager) {
      this.entityManager = entityManager;
   }

   ...
}</pre>
<p>Because <em>@PersistenceContext</em> annotation must not be placed on constructor parameters, you can&#8217;t use constructor injection if multiple persistence units are defined in the same application. In such a case, only field injection is supported, as shown in the following example.</p>
<pre class="brush: java;">public class UserDAOImpl implements UserDAO {
   @Inject
   @PersistenceContext(unitName = "Blue")
   private EntityManager entityManager;

   ...
}</pre>
<h2>Transaction management</h2>
<p>As you already know from the Hibernate integration library, Tapestry automatically manages transactions for you. The JPA integration library defines the <em>@CommitAfter</em> annotation, which acts as the correspondent annotation from the Hibernate integration library. Let&#8217;s explore the <em>UserDAO</em> interface to see the annotation in action.</p>
<pre class="brush: java;">public interface UserDAO {

   @CommitAfter
   @PersistenceContext(unitName = "Blue")
   void add(User user);

   List&lt;User&gt; findAll();

   @CommitAfter
   @PersistenceContext(unitName = "Blue")
   void delete(User... users);
}</pre>
<p>As you can see, the annotation may be placed on service method in order to mark that method as transactional. Any method marked with <em>@CommitAfter</em> annotation will have a transaction started before, and committed after it is called. Runtime exceptions thrown by by a transactional method will abort the transaction. Checked exceptions are ignored and the transaction will be committed anyway.</p>
<p>Note that <em>EntityTransaction</em> interface does not support two phase commit. Committing transactions of multiple EntityManagers in the same request might result in data consistency issues. That&#8217;s why <em>@CommitAfter</em> annotation must be accompanied by the <em>@PersistenceContext</em> annotation if multiple persistence unit are defined in an application. This way you can only commit the transaction of a single persistence unit. You should be very carefully, if you are committing multiple transactions manually in the same request.</p>
<p>After placing the <em>@CommitAfter</em> annotation on methods, you need to tell Tapestry to advise those methods. This is accomplished by adding the transaction advice, as shown in the following example.</p>
<pre class="brush: java;">public class AppModule {

   @Match("*DAO")
   public static void adviseTransactionally(
         JpaTransactionAdvisor advisor,
         MethodAdviceReceiver receiver) {

      advisor.addTransactionCommitAdvice(receiver);
   }
}</pre>
<p>That&#8217;s it for the first part of the article on JPA 2 support in Tapestry. In the next article I&#8217;ll cover some further interesting features of the JPA integration library like providing <em>ValueEncoder</em> for managed classes, using <em>@Persist</em> and <em>@SessionState</em> annotations with entities and JPA-enabled <em>Grid</em> component.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.tapestry5.de/index.php/2011/05/25/jpa-support-in-tapestry/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

