<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">

<chapter id="groovy">
    <title>Groovy integration</title>

    <para>One aspect of JBoss Seam is its RAD (Rapid Application Development) capability. While not synonymous with RAD,
        one interesting tool in this space is dynamic languages. Until recently, choosing a dynamic language was
        required choosing a completely different development platform (a development platform with a set of APIs and a
        runtime so great that you would no longer want to use you old legacy Java [sic] APIs anymore, which would be
        lucky because you would be forced to use those proprietary APIs anyway). Dynamic languages built on top of the
        Java Virtual Machine, and <ulink url="http://groovy.codehaus.org">Groovy</ulink> in particular broke this
        approach in silos.</para>

    <para>JBoss Seam now unites the dynamic language world with the Java EE world by seamlessly integrating both static
        and dynamic languages. JBoss Seam lets the application developer use the best tool for the task, without context
        switching. Writing dynamic Seam components is exactly like writing regular Seam components. You use the same
        annotations, the same APIs, the same everything.</para>
        
    <note>
        <title>Technology preview </title>    
    	<para>Groovy integration in Seam is marked as technology preview, so standard support is not guaranteed.</para>     
    </note>

    <section>
        <title id="groovy-intro">Groovy introduction</title>

        <para>Groovy is an agile dynamic language based on the Java language but with additional features inspired by
            Python, Ruby and Smalltalk. The strengths of Groovy are twofold:</para>

        <itemizedlist>
            <listitem>
                <para>Java syntax is supported in Groovy: Java code is Groovy code, making the learning curve very
                    smooth</para>
            </listitem>

            <listitem>
                <para>Groovy objects are Java objects, and Groovy classes are Java classes: Groovy integrates smoothly
                    with existing Java libraries and frameworks.</para>
            </listitem>
        </itemizedlist>

        <para>TODO: write a quick overview of the Groovy syntax add-on</para>
    </section>

    <section>
        <title>Writing Seam applications in Groovy</title>

        <para>There is not much to say about it. Since a Groovy object is a Java object, you can virtually write any
            Seam component, or any class for what it worth, in Groovy and deploy it. You can also mix Groovy classes and
            Java classes in the same application.</para>

        <section>
            <title>Writing Groovy components</title>

            <para>As you should have noticed by now, Seam uses annotations heavily. Be sure to use Groovy 1.1 or
                above for annotation support. Here are some example of groovy code used in a Seam application.</para>

            <section>
                <title>Entity</title>

                <programlisting role="JAVA">    @Entity
    @Name("hotel")
    class Hotel implements Serializable
    {
        @Id @GeneratedValue
        Long id

        @Length(max=50) @NotNull
        String name

        @Length(max=100) @NotNull
        String address

        @Length(max=40) @NotNull
        String city

        @Length(min=2, max=10) @NotNull
        String state

        @Length(min=4, max=6) @NotNull
        String zip

        @Length(min=2, max=40) @NotNull
        String country

        @Column(precision=6, scale=2)
        BigDecimal price

        @Override
        String toString()
        {
            return "Hotel(${name},${address},${city},${zip})"
        }
    }</programlisting>

                <para>Groovy natively support the notion of properties (getter/setter), so there is no need to
                    explicitly write verbose getters and setters: in the previous example, the hotel class can be
                    accessed from Java as <code>hotel.getCity()</code>, the getters and setters being generated by the
                    Groovy compiler. This type of syntactic sugar makes the entity code very concise.</para>

            </section>

            <section>
                <title>Seam component</title>

                <para>Writing Seam components in Groovy is in no way different than in Java: annotations are used to
                    mark the class as a Seam component.</para>

                <programlisting role="JAVA">@Scope(ScopeType.SESSION)
@Name("bookingList")
class BookingListAction implements Serializable
{
    @In EntityManager em
    @In User user
    @DataModel List&lt;Booking&gt; bookings
    @DataModelSelection Booking booking
    @Logger Log log

    @Factory public void getBookings()
    {
        bookings = em.createQuery('''
                select b from Booking b
                where b.user.username = :username
                order by b.checkinDate''')
            .setParameter("username", user.username)
            .getResultList()
    }
    
    public void cancel()
    {
        log.info("Cancel booking: #{bookingList.booking.id} for #{user.username}")
        Booking cancelled = em.find(Booking.class, booking.id)
        if (cancelled != null) em.remove( cancelled )
        getBookings()
        FacesMessages.instance().add("Booking cancelled for confirmation number #{bookingList.booking.id}", new Object[0])
    }
}</programlisting>

                <para/>
            </section>
        </section>

        <section>
            <title>seam-gen</title>

            <para>Seam gen has a transparent integration with Groovy. You can write Groovy code in seam-gen backed
                projects without any additional infrastructure requirement. When writing a Groovy entity, simply place
                your <filename>.groovy</filename> files in <filename>src/model</filename>. Unsurprisingly, when writing
                an action, simply place your <filename>.groovy</filename> files in
            <filename>src/action</filename>.</para>
        </section>
    </section>

    <section>
        <title>Deployment</title>

        <para>Deploying Groovy classes is very much like deploying Java classes (surprisingly, no need to write nor
            comply with a 3-letter composite specification to support a multi-language component framework).</para>

        <para>Beyond standard deployments, JBoss Seam has the ability, at development time, to redeploy JavaBeans Seam
            component classes without having to restart the application, saving a lot of time in the development / test
            cycle. The same support is provided for GroovyBeans Seam components when the <filename>.groovy</filename>
            files are deployed.</para>

        <section>
            <title>Deploying Groovy code</title>

            <para>A Groovy class <emphasis>is</emphasis> a Java class, with a bytecode representation just like a Java
                class. To deploy, a Groovy entity, a Groovy Session bean or a Groovy Seam component, a compilation step
                is necessary. A common approach is to use the <literal>groovyc</literal> ant task. Once compiles, a
                Groovy class is in no way different than a Java class and the application server will treat them
                equally. Note that this allow a seamless mix of Groovy and Java code.</para>
        </section>

        <section>
            <title>Native .groovy file deployment at development time</title>

            <para>JBoss Seam natively supports the deployment of <literal>.groovy</literal> files (ie without
                compilation) in incremental hotdeployment mode (development only). This enables a very fast edit/test
                cycle. To set up .groovy deployments, follow the configuration at <xref
                    linkend="gettingstarted-hotdeployment"/> and deploy your Groovy code (<filename>.groovy</filename>
                files) into the <filename>WEB-INF/dev</filename> directory. The GroovyBean components will be picked up
                incrementally with no need to restart the application (and obviously not the application server either).</para>

            <para>Be aware that the native .groovy file deployment suffers the same limitations as the regular Seam
                hotdeployment:</para>

            <itemizedlist>
                <listitem>
                    <para>The components must be JavaBeans or GroovyBeans. They cannot be EJB3 bean</para>
                </listitem>

                <listitem>
                    <para>Entities cannot be hotdeployed</para>
                </listitem>

                <listitem>
                    <para>The hot-deployable components will not be visible to any classes deployed outside of
                            <literal>WEB-INF/dev</literal></para>
                </listitem>

                <listitem>
                    <para>Seam debug mode must be enabled</para>
                </listitem>
            </itemizedlist>

            <para/>
        </section>

        <section>
            <title>seam-gen</title>

            <para>Seam-gen transparently supports Groovy files deployment and compilation. This includes the native
                    <filename>.groovy</filename> file deployment in development mode (compilation-less). If you create a
                seam-gen project of type WAR, Java and Groovy classes in <filename>src/action</filename> will
                automatically be candidate for the incremental hot deployment. If you are in production mode, the Groovy
                files will simply be compiled before deployment.</para>

            <para>You will find a live example of the Booking demo written completely in Groovy and supporting
                incremental hot deployment in <filename>examples/groovybooking</filename>.</para>
        </section>
    </section>
</chapter>
