Update of /cvsroot/xdoclet/xdoclet/xdocs
In directory sc8-pr-cvs1:/tmp/cvs-serv11916

Added Files:
        valueobjects.xml 
Log Message:
checkins on behalf of pazu


--- NEW FILE: valueobjects.xml ---
<?xml version="1.0"?>
<document>
        <properties>
                <author email="[EMAIL PROTECTED]">Marcus Brito</author>
                <title>Using Value Objects</title>
        </properties>
<body>

<section name="Motivation">
<p>
        The &lt;valueobject&gt; task is the xdoclet embodiement of the Value
        Object pattern, as described in <em>Core J2EE Patterns</em>.
        This pattern is also published in many other books and community sites
        around the world, and has proven to be an essential pattern to solve
        some EJB shortcomings.
</p>
<p>
        Every remote enterprise bean call may go through the network,
        implying a heavy performance penalty. For entity beans this is specially
        dangerous: every entity bean has a getter and a setter for its
        properties, and each of these calls would incur a remote, networked
        call. If your application is filling a form using the bean properties it
        would make a remote call for each property. No, no good.
</p>
<p>
        The solution is to create a coarse-grained object that contains some
        or all the bean properties and provide a method to create this object
        from the bean properties and another method to set the bean properties
        from such an object. This object is what we call the Value Object, a
        POJO (plain old java object) containing the enterprise bean property
        values. The following diagram illustrates this approach.
</p>
<p>
        {{{@todo: INSERT UML DIAGRAM HERE}}}
</p>
        <subsection name="Multiple Value Objects Strategy">
        <p>
                Suppose you have defined a <code>Customer</code> entity with properties
                such as id, name, birth date, full address, number of children, 
prefered
                TV series, wheather s/he likes fruit loops or cheerios and oodles of
                other information. You need them in different parts of your 
application.
                However, sometimes you just need the customer ID and name. It would be 
a
                waste of bandwidth and CPU to create a value object with all properties
                and pass it to your application, specially if you got thousands or
                millions of them.
        </p>
        <p>
                In a scenario like the one above, it would be useful to define
                multiple value objects, each one containing a different set of
                properties. You could have a <code>CustomerFull</code> VO containing 
all
                properties and a <code>CustomerLight</code> VO containing just the
                customer ID and name.
        </p>
        <p>
                Your entity bean would provide methods to obtain both value objects,
                and perhaps methods to update the entity from both of them.The 
following
                diagram illustrates this approach.
        </p>
        <p>{{{INSERT UML DIAGRAM HERE}}}</p>
        </subsection>
</section>

<section name="Using Value Objects in XDoclet">
<p>
        XDoclet helps you to define and create your value objects. Below you
        can see a xdoclet-taged Entity Bean source code, with @tags related to
        Value Object generation. Let's take a look at a bean marked up to
        generate Value Objects. Please note that this is note a complete
        example: there are many tags missing, only the ones related to Value
        Objects are presented here.
</p>
<source>
package example.ejb;

import javax.ejb.EntityBean;
import java.util.Collection;
import java.util.Date;

/**
 * This is a Value Object usage example for XDoclet. It demonstrates the use
 * of most value object features like property selection, aggregation and
 * composition.
 *
 * @ejb.bean
 *   type="CMP"
 *   name="Customer"
 *
 * @ejb.value-object
 *   name="Customer"
 *   match="*"
 *
 * @ejb.value-object
 *   name="CustomerLight"
 *   match="light"
 */
public abstract class CustomerEJB implements EntityBean {

        /**
         * @ejb.value-object match="light"
         * @ejb.persistent-field
         */
        public abstract String getId();
        public abstract void setId(String id);

        /**
         * @ejb.value-object match="light"
         * @ejb.persistent-field
         */
        public abstract String getName();
        public abstract void setName(String name);

        /**
         * @ejb.value-object
         *   aggregate="example.vo.ProductValue"
         *   aggregate-name="PreferedProducts"
         *   members="example.interfaces.Product"
         *   members-name="PreferedProduct"
         *   relation="external"
         *   type="Collection"
         * @ejb.relation
         *   name="Customer-Product"
         *   role-name="customer-prefers-products"
         */
        public abstract Collection getPreferedProduts();
        public abstract void setPreferedProducs(Collection products);

        /**
         * @ejb.value-object
         *   compose="example.vo.AddressValue"
         *   compose-name="Addresses"
         *   members="example.interfaces.Address"
         *   members-name="Address"
         *   relation="external"
         *   type=Collection"
         * @ejb.relation
         *   name="Customer-Address"
         *   role-name="customer-has-addresses"
         */
        public abstract Collection getAddresses();
        public abstract void setAddresses();

        /**
         * @ejb.pesistent-field
         */
        public abstract int getNumberOfChildren();
        public abstract void setNumberOfChildren(int nof);

        /**
         * @ejb.persistent-field
         */
        public abstract boolean getLikesFruitLoops();
        public abstract void setLikesFruitLoops(boolean loops);

        /**
         * @ejb.persistent-field
         */
        public abstract boolean getLikesCheerios();
        public abstract void setLikesCheerios(boolean cheerios);

        /**
         * @ejb.interface-method
         */
        public abstract CustomerValue getCustomerValue();

        /**
         * @ejb.interface-method
         */
        public abstract CustomerLightValue getCustomerLightValue();

        /**
         * @ejb.interface-method
         */
        public abstract void setCustomerValue(CustomerValue value);
}
</source>
<p>
        As you can see, there is only one tag you need to write to instruct
        xdoclet to generate value objects: <code>@ejb.value-object</code>.
        However, there ane many places and uses for this tag. Let's go through
        the basic steps to mark your bean until you get everything generated by
        xdoclet.
</p>
        <subsection name="Value Object Declaration">
        <p>
                The first thing to do is to inform xdoclet which value objects it
                will generated for your bean. At class level, introduce the
                <code>@ejb.value-object</code> tag and supply at least the
                <code>name</code> and <code>match</code> parameter. The name
                parameter will tell xdoclet how to name the generated class for that
                value object. XDoclet will apply the pattern task parameter to the
                supplied name to determine the class name. The default pattern is
                <code>{0}Value</code>, so in this example we get two classes
                generated: <code>CustomerValue</code> and 
<code>CustomerLightValue</code>.
        </p>
        <p>
                The <code>match</code> parameter will tell xdoclet which entity
                properties will be included in the generated value object. It's just
                an identifier that you will have to repeat at each property getter
                you want included in the value object. The <code>*</code> is a special
                value, meaning that all properties will be included. So, in this
                example the <code>CustomerValue</code> will have the same properties
                as the entity bean and the <code>CustomerLightValue</code> will have
                only the <code>id</code> and <code>name</code> properties.
        </p>
        </subsection>
        <subsection name="Aggregation and Composition">
        <p>
                Value objects can have <code>composite</code> and 
<code>aggregate</code>
                properties. These are multivalued properties that map an EJB 
relationship.
                In this example we've got both aggregate and composite properties,
                those being <code>preferedProduts</code> and <code>addresses</code>,
                respectively.
        </p>
        <p>
                Aggregation should be used when the related object is not directly
                dependant on the one we're declaring the value object.
                <code>Product</code> has no direct dependency to <code>Customer</code>,
                so the <code>preferedProducts</code> relationship is just an
                aggregation. This means that the generated accessor methods for this
                relationship will lookup <code>Product</code> entities when adding
                them via the generated <code>addPreferredProduct()</code> method.
        </p>
        <p>
                Composition should be used when the related object is directly
                dependent on the one we're declaring the value object, and cannot
                exist without it. The creation of the related object is
                responsibility of the entity we're coding. <code>Address</code> is
                dependent on <code>Customer</code>, so the addresses relationhsip is
                a composition. This means that the generated accessor methods for
                this relationship will create and remove <code>Address</code>
                entities when adding and removing them via the generated
                <code>addAddress()</code> and <code>removeAddress()</code> methods.
        </p>
        <p>
                Aggregation and composition may be confusing at first. As a rule of
                thumb, considers object creation responsibility: if the entity we're
                coding isn't responsible for creating the related entity, then it's
                aggregation. If it is responsible for this, then it's composition. We
                ask you to take a look at the generated code so you can really grasp 
the
                difference between the two.
        </p>
        <p>
                Now let's break down the many parameters that are needed to
                accomplish a multivalued property on a value object. The
                <code>type</code> parameter tells xdoclet what should be the type of
                the property in the value object. The possible values for this
                parameter are <code>Collection</code> and <code>Set</code>, in
                accordance with the EJB specification. In this example, both our
                multivalued properties uses <code>Collection</code> as type.
        </p>
        <p>
                The <code>aggregate-name</code> (or <code>composite-name</code>)
                parameter tells xdoclet how the accessor methods to this property in
                the value object should be called. The value of this paremeter should 
be
                the method name, sans <code>get</code> or <code>set</code>. In this
                example, we will have methods called <code>getPreferedProducts()</code>
                and <code>setPreferedProducts()</code>, because PreferedProducts was
                the aggregate-name for the relationship.
        </p>
        <p>
                The <code>aggregate</code> (or <code>composite</code>) parameter
                tells xdoclet which should be the type of itens contained in
                the multivalued property. This should be a fully qualified class name.
                In this example, the <code>getAddresses()</code> method of the value
                object will return a <code>Collection</code> of
                <code>example.vo.AddressValue</code> objects. Thing should be
                starting to make sense, no?
        </p>
        <p>
                The <code>members</code> parameter tells xdoclet the fully qualified
                type of the related objects. This should be the type of the objects
                returned by the entity getter. Please note that <code>aggregate</code>
                and <code>aggregate-name</code> (or <code>composite</code> and
                <code>composite-name</code>) relate to names and types in the value
                object, while <code>members</code> and <code>members-name</code>
                relate to names and types in the entity bean. In this example, the
                <code>getPreferedProducts()</code> method returns a
                <code>Collection</code> of <code>example.interfaces.Product</code>
                objects, so this should be the value of the <code>members</code>
                parameter.
        </p>
        <p>
                The <code>members-name</code> parameter should be the name of the
                method in the related object that xdoclet should use to get the
                object that will be put in the multivalued value object property,
                without <code>get</code> or <code>set</code>. In this example,
                xdoclet needs to call a <code>Product.getProductValue()</code> method
                to obtain the <code>ProductValue</code>that will be put in the value
                <code>preferedProducts</code> property. Are you still with me?
        </p>
        <p>
                Last, the <code>relation</code> parameter, which only accepts the
                <code>external</code> value tells xdoclet that this property can be
                updated outside of the scope of this value object, so the generated
                method should always retrieve the property value. For relations,
                this is a no brainer: always include the 
<code>relation="external"</code>
                parameter.
        </p>
        </subsection>
        <subsection name="Exposing Generated Methods">
        <p>
                Please notice the last three methods in this example. The Bean
                implementation class generated by xdoclet will contains them, but by
                default they won't be included in the remote or local interface for the
                bean. If you need to change that, you should declare them as abstract
                in your beans an tag them as you wish. In this example, we want the
                methods exposed in the remote interface, so we tag them with
                @ejb.interface-method. We don't want the
                <code>setCustomerLightValue()</code> method exposed, so we don't
                declare them here -- it will be in the generated implementation,
                however.
        </p>
        </subsection>
</section>
<section name="Customizing the &amp;lt;valueobject&amp;gt; task">
<p>
        The <code>&amp;lt;valueobject&amp;gt;</code> task can be customized to
        your liking, to change things like the name of the package where the
        generated classes go and the name of the generated value objects.
</p>
<p>
        You can change the target package using a nested
        <a
        
href="ant/xdoclet/tagshandler/PackageTagsHandler.PackageSubstitution.html"><code>&amp;lt;packageSubstitution&amp;gt;</code></a>
        element. For example, suppose we want all our value objecs generated
        under the <code>example.valueobjects</code> package.
</p>
<source><![CDATA[<valueobject>
        <packageSubstitution packages="ejb" substituteWith="valueobjects"/>
</valueobject>]]>
</source>
<p>
        This tells xdoclet to substitute all packages names ending in "ejb" with
        a package name ending in "valueobject". The
        <code>&amp;lt;packageSubstitution&amp;gt;</code> element is common to all
        xdoclet subtasks, so it's a good thing to understand how to use it.
</p>
<p>
        Now, if you don't like the default naming pattern for value objects, you
        can change it by setting the <code>pattern</code> attribute for the
        <code>&amp;lt;valueobject&amp;gt;</code> task. The value must contain
        <code>{0}</code> in the name, which xdoclet will substitute with the
        bean name. In the above example, if we want our value objects to be
        named <code>CustomerVO</code> and <code>CustomerLightVO</code>, in the
        <code>examples.valueobject</code> package, this would be the task
        declaration:
</p>
<source><![CDATA[<valueobject pattern="{0}VO">
        <packageSubstitution packages="ejb" substituteWith="valueobjects"/>
</valueobject>]]>
</source>

        <subsection name="Modifying the generated value object">
        <p>
                XDoclet provides merge points in the value object template that you
                can use to add custom code to the generated value objects. If you
                don't know about merge points, you should <a href="merge.html">read
                about them now</a>.
        </p>
        <p>
                The merge point is just before the closing brace of the generated
                class and is called <code>valueobject-custom.xdt</code>. Please note
                that the merge file can contain any java code and can use the
                xdoclet template language. You can use this merge point to add
                new methods or inner classes to the generated value object. If
                you're <em>really</em> unhappy with the generated value object, you
                can completely replace the template used by xdoclet to generate it.
                Please refer to further documentation to learn about the template
                language.
        </p>
        </subsection>
</section>
</body>
</document>



-------------------------------------------------------
This sf.net email is sponsored by:
With Great Power, Comes Great Responsibility 
Learn to use your power at OSDN's High Performance Computing Channel
http://hpc.devchannel.org/
_______________________________________________
Xdoclet-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/xdoclet-devel

Reply via email to