Hello,
The biggest deficiency (IMHO) in EJB specification is that it doesn't
define component inheritance. The EJB component consists of remote
interface, home factory, bean implementation, xml descriptor, vendor
specific xml descriptors and primary key. With current specification one
can easily inherit from remote interface, bean implementation and
primary key since they are just plain Java classes. The problem is with
xml descriptors and home factory.

One great advantage of Xdoclet is that it can provide "a poor man's
component inheritance" for XML descriptors. It does it by inheriting the
Xdoclet tags of the superclass and by generating "an expanded" XML
descriptor element for class that inherits the tags. However, I found
something which I am not sure if it's a non implemented feature, my
misunderstanding or a bug. Let's say that we have three components
(entity beans): User, CatalogItem and Product. In ASCII UML:

+--------+  1      *   +----------------+
|  User  | ----------> |  <<abstract>>  |
|        |             |   CatalogItem  |
+--------+             +----------------+
                               ^
                               |
                       +----------------+
                       |    Product     |
                       +----------------+

So, User has one-many CMR for abstract CatalogItem and Product extends
CatalogItem. "The poor man's component inheritance" works well with CMP
fields. All the CMP fields defined in CatalogItem are inherited in
Product's <entity>-element. Also, CatalogItem is correctly not declared
in ejb-jar.xml because I use  @ejb:bean generate="false". The problem is
with <relationships>-declaration:

   <relationships >
      <ejb-relation >
         <ejb-relation-name>UserCatalogItems</ejb-relation-name>
         <!-- bidirectional -->
         <ejb-relationship-role >
           
<ejb-relationship-role-name>UserOwnsCatalogItems</ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source >
               <ejb-name>User</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>catalogItems</cmr-field-name>
            </cmr-field>
         </ejb-relationship-role>
         <ejb-relationship-role >
           
<ejb-relationship-role-name>CatalogItemHasOwner</ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source >
               <ejb-name>test.CatalogItem</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>owner</cmr-field-name>
            </cmr-field>
         </ejb-relationship-role>
      </ejb-relation>
   </relationships>

The <ejb-name> of the second part of the relationship is:
test.CatalogItem. However, there's no bean deployed by that name since
test.CatalogItem is abstract. If the <ejb-name> would be Product, then
"the poor man's component inheritance" would work. Any comments?

I attached a sample implementation of this case and the ejb-jar.xml
which was generated by Xdoclet.

PS. Thanks for making a wonderful J2EE productivity tool! 

-- 
Joni
[EMAIL PROTECTED]
http://www.shiftcontrol.com
package test;

import javax.ejb.EntityBean;

/**
 * An abstract base for real catalog items.
 *
 * @ejb:bean        type="CMP" 
 *                  view-type="local" 
 *                  primkey-field="id"
 *                  generate="false"
 *
 * @ejb:pk          class="java.lang.Integer"
 *
 * @ejb:transaction type="Required"
 */
public abstract class CatalogItemEJB implements EntityBean {
    /**
     * Id of a catalog item.
     *
     * @ejb:pk-field
     * @ejb:persistent-field
     * @ejb:interface-method view-type="local"
     */
    public abstract Integer getId();
    public abstract void setId(Integer id);

    /**
     * The owner of this item.
     * Bidirectional many-one.
     *
     * @ejb:interface-method   view-type="local"
     * @ejb:relation           name="UserCatalogItems" 
     *                         role-name="CatalogItemHasOwner"
     *
     */
    public abstract UserLocal getOwner();
    public abstract void setOwner(UserLocal user);
}
package test;

import javax.ejb.EntityBean;

/**
 * @ejb:bean        type="CMP" 
 *                  name="Product" 
 *                  local-jndi-name="ejb/Product" 
 *                  view-type="local" 
 *                  primkey-field="id"
 *
 * @ejb:transaction type="Required"
 */
public abstract class ProductEJB extends CatalogItemEJB 
                                 implements EntityBean {

    /**
     * Name of a product.
     *
     * @ejb:persistent-field
     * @ejb:interface-method view-type="local"
     */
    public abstract String getName();
    public abstract void setName(String name);
}
package test;

import javax.ejb.EntityBean;


/**
 * Represents a user in a system.
 *
 * @ejb:bean         type="CMP" 
 *                   name="User" 
 *                   local-jndi-name="ejb/User" 
 *                   view-type="local" 
 *                   primkey-field="id"
 *
 * @ejb:pk           class="java.lang.Integer"
 *
 * @ejb:transaction  type="Required"
 */
public abstract class UserEJB implements EntityBean {
    /**
     * Id of the user.
     *
     * @ejb:persistent-field
     * @ejb:pk-field
     * @ejb:interface-method view-type="local"
     */
    public abstract Integer getId();
    public abstract void setId(Integer id);

    /**
     * A user can have items in a catalog.
     * Bidirectional one-many.
     *
     * @ejb:interface-method   view-type="local"
     * @ejb:relation           name="UserCatalogItems" 
     *                         role-name="UserOwnsCatalogItems"
     *
     */
    public abstract Collection getCatalogItems();
    public abstract void setCatalogItems(Collection items);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd";>

<ejb-jar >

   <description>No Description.</description>
   <display-name>Generated by XDoclet</display-name>

   <enterprise-beans>

      <!-- Session Beans -->

     <!--
       To add session beans that you have deployment descriptor info for, add
       a file to your merge directory called session-beans.xml that contains
       the <session></session> markup for those beans.
     -->

      <!-- Entity Beans -->
      <entity >
         <description><![CDATA[Represents a user in a system.]]></description>

         <ejb-name>User</ejb-name>

         <local-home>test.UserLocalHome</local-home>
         <local>test.UserLocal</local>

         <ejb-class>test.UserCMP</ejb-class>
         <persistence-type>Container</persistence-type>
         <prim-key-class>java.lang.Integer</prim-key-class>
         <reentrant>False</reentrant>
         <cmp-version>2.x</cmp-version>
         <abstract-schema-name>User</abstract-schema-name>
         <cmp-field >
            <description><![CDATA[Id of the user.]]></description>
            <field-name>id</field-name>
         </cmp-field>
         <primkey-field>id</primkey-field>

      </entity>

      <entity >
         <description><![CDATA[No Description.]]></description>

         <ejb-name>Product</ejb-name>

         <local-home>test.ProductLocalHome</local-home>
         <local>test.ProductLocal</local>

         <ejb-class>test.ProductCMP</ejb-class>
         <persistence-type>Container</persistence-type>
         <prim-key-class>java.lang.Integer</prim-key-class>
         <reentrant>False</reentrant>
         <cmp-version>2.x</cmp-version>
         <abstract-schema-name>Product</abstract-schema-name>
         <cmp-field >
            <description><![CDATA[Name of a product.]]></description>
            <field-name>name</field-name>
         </cmp-field>
         <cmp-field >
            <description><![CDATA[Id of a catalog item.]]></description>
            <field-name>id</field-name>
         </cmp-field>
         <primkey-field>id</primkey-field>

      </entity>

     <!--
       To add entity beans that you have deployment descriptor info for, add
       a file to your merge directory called entity-beans.xml that contains
       the <entity></entity> markup for those beans.
     -->

      <!-- Message Driven Beans -->
     <!--
       To add message driven beans that you have deployment descriptor info for, add
       a file to your merge directory called message-driven-beans.xml that contains
       the <message-driven></message-driven> markup for those beans.
     -->

   </enterprise-beans>

   <!-- Relationships -->
   <relationships >
      <ejb-relation >
         <ejb-relation-name>UserCatalogItems</ejb-relation-name>
         <!-- bidirectional -->
         <ejb-relationship-role >
            <ejb-relationship-role-name>UserOwnsCatalogItems</ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source >
               <ejb-name>User</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>catalogItems</cmr-field-name>
            </cmr-field>
         </ejb-relationship-role>
         <ejb-relationship-role >
            <ejb-relationship-role-name>CatalogItemHasOwner</ejb-relationship-role-name>
            <multiplicity>One</multiplicity>
            <relationship-role-source >
               <ejb-name>test.CatalogItem</ejb-name>
            </relationship-role-source>
            <cmr-field >
               <cmr-field-name>owner</cmr-field-name>
            </cmr-field>
         </ejb-relationship-role>
      </ejb-relation>
   </relationships>

   <!-- Assembly Descriptor -->
   <assembly-descriptor >

   <!-- finder permissions -->

   <!-- finder permissions -->

   <!-- transactions -->
   <container-transaction >
      <method >
         <ejb-name>User</ejb-name>
         <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction >
      <method >
         <ejb-name>Product</ejb-name>
         <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>

   <!-- finder transactions -->
   </assembly-descriptor>

</ejb-jar>

Reply via email to