Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences

Edit this page


Referenced by
AppFuseXSnapshotBase
Articles




JSPWiki v2.2.33

[RSS]


Hide Menu

AppFuseXSnapshot


DTO in AppFuse using XSnapshot

Part I: Integrating XSnapshot in AppFuse - A HowTo for integrating the XSnapshot framework in AppFuse

About this Tutorial

This tutorial will show you how to integrating the XSnapshot framework into Appfuse. By default, in Appfuse, the forms and generated by the XDoclet task @struts.form, and the data transfert used the jakarta commons beanutils.

With XSnapshot, the form is always generated by a set of xdoclet tasks which generate a snapshot and a helper class that convert data between model and form classes.

Table of Contents

  • [1] Download the latest version Xsnapshot
  • [2] Integrate the libraries in AppFuse
  • [3] Integrate new gen-xsnapforms ANT-Task in the build.xml
  • [4] Add Xsnapshot files in the WAR
  • [5] Declaring XSnapshot Beans in the Spring container

Download the latest version Xsnapshot[#1]

First of all we need to Download the XSnapshot framework. Howerer, the "official" framework can't be integrated in the Struts version of AppFuse for a simple raison :

generated Struts form contain not the doclet @struts.form name="..."


/**
 * This is the "projectForm" snapshot auto-generated from the 
 * Project class.
 <p> 
 * Please see the documentation for the original Project
 * class for documentation of each individual attribute.
 @see org.appfuse.model.Project
 *
 */

public  class ProjectForm 
  extends org.apache.struts.action.ActionForm 
  implements Serializable {

In this form generated example, for AppFuse, it should have a doclet @struts.form name="personForm".

In this case, appfuse tasks would not be able to generate the struts-config.xml. So I have modifie the XSnapshot sources, in particular the net/sf/xsnapshot/ressources/snapshot.xdt to add the doclet.

NOTE: xsnapshot form generation does not write the struts validator doclet write in the model classes sources so you can not use Struts validator :-(. I am looking to modifie xsnapshot sources...

So download this version of xsnapshot(info)

Integrate the libraries in AppFuse[#2]

  • Extract the archive in le lib directory
  • Add the following part to the lib/lib.properties file:
      #
      # xsnapshot - http://xsnapshot.sourceforge.net
      #
      xsnapshot.version=1.1-beta2
      xsnapshot.dir=${lib.dir}/xsnapshot-${xsnapshot.version}
      xsnapshot.jar=${xsnapshot.dir}/xsnapshot.jar
  • Add the common configuration declaration.

So the commons part would be like that

    
      #
      # Commons - http://jakarta.apache.org/commons
      #
      commons.dir=${lib.dir}/jakarta-commons
      commons-beanutils.jar=${commons.dir}/commons-beanutils.jar
      commons-collections.jar=${commons.dir}/commons-collections.jar

      # New for XSnapshot
      commons-configuration.jar=${commons.dir}/commons-configuration.jar

      commons-digester.jar=${commons.dir}/commons-digester.jar
      commons-fileupload.jar=${commons.dir}/commons-fileupload.jar
      commons-lang.jar=${commons.dir}/commons-lang.jar
      commons-logging.jar=${commons.dir}/commons-logging.jar
      commons-validator.jar=${commons.dir}/commons-validator.jar
      jakarta-oro.jar=${commons.dir}/jakarta-oro.jar

  • You have to add the reference to the xsnaphost classpath. It need, of course the two jar and others like In order to do this, you have to edit your properties.xml file


  <path id="xsnapshot.classpath">
    <fileset dir="${xsnapshot.dir}" includes="*.jar"/>
    <fileset dir="${xdoclet.dir}">
      <include name="*.jar"/>
      </fileset>
    <pathelement location="${j2ee.dir}/lib/j2ee.jar"/>
    <pathelement location="${ant.home}/lib/ant.jar"/>
    <pathelement location="${commons-collections.jar}"/>
    <pathelement location="${commons-logging.jar}"/>
    <pathelement location="${commons-lang.jar}"/>
  </path>

  • Finally, add xsnapshot jar in classpath for compiling web classes (Actions and forms)

Add this line in your properties.xml file at the end of definition

  <pathelement location="${xsnapshot.jar}"/>

Integrate new XSnapshot ANT-Tasks in the build.xml [#3]

In order to use cobertura with your junit tests, you have to add the cobertura ANT-tasks to your build.xml

  • Open your build.xml and add the following target :
        <target name="gen-snapshotforms" description="Builds xsnapshots files, if necessary" depends="">
          <taskdef name="xsnapshotdoclet" classname="net.sf.xsnapshot.ant.XSnapshotDocletTask" classpathref="xsnapshot.classpath"/>
          <xsnapshotdoclet destdir="${build.dir}/web/gen" verbose="true"  mergedir="${xdoclet.merge.dir}" >
            <fileset dir="src/dao" includes="**/*.java"/>
              <packageSubstitution packages="model" substituteWith="webapp.form"/>
              <snapshot/>
              <helper/>
          </xsnapshotdoclet>

          <xsnapshotdoclet destdir="${build.dir}/web/gen" verbose="true"  mergedir="${xdoclet.merge.dir}" >
            <fileset dir="src/dao" includes="**/*.java"/>
            <packageSubstitution packages="model" substituteWith="webapp.form"/>
            <properties/>
          </xsnapshotdoclet>
        </target>

The first line defines the xsnapshot doclet task, using the classpath defined before. The xsnapshotdoclet task defines three subtasks, , ,
and to generate the snapshots, helpers and the configuration file respectively. because you will generally want the output from the former two to go to a different place than the latter, you will need to run xsnapshotdoclet twice.

Best practice is to have the and output classes to a generated-src directory somewhere under your build directory. The above example shows the two executions
of . Mergedir refers to the directory where xsnapshot will look for merge files.the element specifies the classes on which to run xsnapshot.

the element allows you to define an automatic package replacement that should take place when xsnapshot encounters non fully qualified classnames. Normally, xsnapshot qualifies them, with the package of the class in which they are found; the package substitution modifies that.

source XSnapshot quickstart guide

  • add the following part the the gen-forms target:
          <antcall target="gen-snapshotforms" />

Add XSnapshot files in the WAR [#4]

  • add the following part the the package-web target in the war task:
        <lib file="${xsnapshot.jar}"/>
        <lib file="${commons-configuration.jar}" />

        <webinf file="${build.dir}/web/gen/xsnapshot.properties" />

Declare XSnapshot Beans in the Spring container [#5]

  • We start by declaring XSnapshot transformers.

A transformer specify how to transform a value of a property in a model to the value the matching property should have in a snapshot, or the reverse transformation. We will see later a Date-to-Input transformer for transforming Date into String.

Add the following into src/service/org/appfuse/service/applicationContext-service.xml

        <!-- SPECIAL DAO for transforming IDs to entities of arbitrary class -->
        <bean id="id-to-entity" parent="dao"
          class="net.sf.xsnapshot.hibernate3.IdToEntityTransformer"/>

The id-to-entity transformer is used to retrieve a Object by is id using a dao

  • To convert model objects in forms (and inversement), xsnapshot need to create a registry which contains configuration.

Add the following part

        <!-- ======================== XSNAPSHOT SETUP ========================= -->
        <bean id="xsnapshotRegistry" class="net.sf.xsnapshot.spring.XSnapshotRegistryFactoryBean">
          <property name="configLocations">
            <list>
              <value>/WEB-INF/xsnapshot.properties</value>
            </list>
          </property>    
          <property name="helperMappings">
            <map>
            </map>
          </property>
          <property name="transformerMappings">
            <map>
              <!-- invoked indirectly by xsnapshot -->
              <entry key="inverse-nested-property" value-ref="id-to-entity"/>
            </map>
          </property>
        </bean>

  • Declaring a XsnapshotUtils bean.

The XsnapshotUtils class contains methods for working with XSnapshot at runtime

        <bean id="xsnapshotUtils" class="net.sf.xsnapshot.XSnapshotUtils">
          <property name="registry" ref="xsnapshotRegistry"/>
        </bean>
  • run ant

Everything should run normaly....

like would say Matt
Yeah Baby, Yeah: BUILD SUCCESSFUL
Total time: 1 minute 22 seconds

You are ready to use Xsnapshot in our Appfuse Project


Next Up: Part II: Implementing the example

Attachments:


Go to top   Edit this page   More info...   Attach file...
This page last changed on 06-Nov-2006 13:53:00 MST by DavidRouchy.