Discussions

EJB programming & troubleshooting: InstantiationException creating CMP entity bean from session

  1. I've built a very simple CMP entity bean called StatisticsBean. It has two fields name and value. They are both of type java.lang.String and the name field is the primary key. I'm using xdoclet to generate the related files from the bean. The bean deploys without warnings or errors. From my session bean I execute the following:

    StatisticLocalHome statHome = StatisticBeanUtil.getLocalHome();
    StatisticLocal stat = statHome.create("foo-cnt", "0");

    When I do, I get the following exception and stack trace:

    10:32:58,576 ERROR [LogInterceptor] TransactionRolledbackLocalException in method: public abstract sample.StatisticLocal sample.StatisticLocalHome.create(java.l
    ang.String,java.lang.String) throws javax.ejb.CreateException, causedBy:
    java.lang.InstantiationException
     at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
     at java.lang.Class.newInstance0(Class.java:308)
     at java.lang.Class.newInstance(Class.java:261)
     at org.jboss.ejb.plugins.jaws.JAWSPersistenceManager.createBeanClassInstance(JAWSPersistenceManager.java:165)
     at org.jboss.ejb.plugins.CMPPersistenceManager.createBeanClassInstance(CMPPersistenceManager.java:114)
     at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.createBeanClassInstance(CachedConnectionInterceptor.java:250)
     at org.jboss.ejb.EntityContainer.createBeanClassInstance(EntityContainer.java:221)
     at org.jboss.ejb.plugins.AbstractInstancePool.get(AbstractInstancePool.java:168)
     at org.jboss.ejb.plugins.EntityInstanceInterceptor.invokeHome(EntityInstanceInterceptor.java:78)
    ...


    I cannot see what I'm doing wrong. I'm sure it's something very small.

    Here's my bean:

    package sample;

    import javax.ejb.EntityBean;
    import javax.ejb.EntityContext;
    import javax.ejb.RemoveException;
    import javax.ejb.CreateException;
    import javax.ejb.FinderException;
    import java.lang.String;

    /**
     *
     * @ejb.bean
     * name="StatisticBean"
     * jndi-name="ejb/StatisticBeanRemote"
     * local-jndi-name="ejb/StatisticBeanLocal"
     * cmp-version="2.x"
     * primkey-field="name"
     * schema="StatSchema"
     *
     * @ejb.interface
     * remote-class="sample.Statistic"
     * local-class="sample.StatisticLocal"
     *
     * @ejb.home
     * remote-class="sample.StatisticHome"
     * local-class="sample.StatisticLocalHome"
     *
     * @ejb.pk
     * class="java.lang.String"
     * generate="false"
     *
     * @ejb.util generate="physical"
     *
     * @jboss.container-configuration name="Standard CMP EntityBean"
     *
     * @jboss.persistence
     * datasource="default"
     *
     */

    public abstract class StatisticBean implements EntityBean
    {
    /**
     * @ejb.create-method
     * @return Primary Key
     * @throws CreateException
     */
    public String ejbCreate(String name, String value) throws CreateException
    {
            setName(name);
            setValue(value);
            
            return null;
    }

    public void ejbPostCreate(String name, String value) throws CreateException
    {
    }

    /**
      * @ejb.select query="select o.name from Stats o where o.name = ?1"
      * @param s Name we are searching with
      * @return Set of Primary Keys with that name
      * @throws FinderException
      */
    public abstract String ejbSelectByName(String name) throws FinderException;

    /**
      * @ejb.interface-method
      * @ejb.persistence jdbc-type="VARCHAR" sql-type="VARCHAR"
      * @ejb.pk-field
      * @return the name of this bean
      */
    public abstract String getName();
    /**
     * @ejb.interface-method
     * @param s Set the name of this bean
     */
    public abstract void setName(String s);

    /**
     * @ejb.interface-method
     * @ejb.persistence jdbc-type="VARCHAR" sql-type="VARCHAR"
     * @return the value of this bean
     */
    public abstract String getValue();
    /**
     * @ejb.interface-method
     * @param s Set the value of this bean
     */
    public abstract void setValue(String s);

    }

    Here's the bean implementation class, derived from this that is generated by xdoclet:

    /*
     * Generated by XDoclet - Do not edit!
     */
    package sample;

    /**
     * CMP layer for StatisticBean.
     */
    public abstract class StatisticBeanCMP
       extends sample.StatisticBean
       implements javax.ejb.EntityBean
    {

       public void ejbLoad()
       {
       }

       public void ejbStore()
       {
       }

       public void ejbActivate()
       {
       }

       public void ejbPassivate()
       {

       }

       public void setEntityContext(javax.ejb.EntityContext ctx)
       {
       }

       public void unsetEntityContext()
       {
       }

       public void ejbRemove() throws javax.ejb.RemoveException
       {

       }

       public abstract java.lang.String getName() ;

       public abstract void setName( java.lang.String name ) ;

       public abstract java.lang.String getValue() ;

       public abstract void setValue( java.lang.String value ) ;

    }

    Here's StatisticLocal generate by xdoclet:

    /*
     * Generated by XDoclet - Do not edit!
     */
    package sample;

    /**
     * Local interface for StatisticBean.
     */
    public interface StatisticLocal
       extends javax.ejb.EJBLocalObject
    {

       public java.lang.String getName( ) ;

       public void setName( java.lang.String s ) ;

       public java.lang.String getValue( ) ;

       public void setValue( java.lang.String s ) ;

    }

    Here's StatisticLocalHome generated by xdoclet:

    /*
     * Generated by XDoclet - Do not edit!
     */
    package sample;

    /**
     * Local home interface for StatisticBean.
     */
    public interface StatisticLocalHome
       extends javax.ejb.EJBLocalHome
    {
       public static final String COMP_NAME="java:comp/env/ejb/StatisticBeanLocal";
       public static final String JNDI_NAME="ejb/StatisticBeanLocal";

       public sample.StatisticLocal create(java.lang.String name , java.lang.String value)
          throws javax.ejb.CreateException;

       public sample.StatisticLocal findByPrimaryKey(java.lang.String pk)
          throws javax.ejb.FinderException;

    }

    Here's the utility class generate by xdoclet for looking up home interfaces:

    /*
     * Generated file - Do not edit!
     */
    package sample;

    /**
     * Utility class for StatisticBean.
     */
    public class StatisticBeanUtil
    {
       /** Cached remote home (EJBHome). Uses lazy loading to obtain its value (loaded by getHome() meth
    ods). */
       private static sample.StatisticHome cachedRemoteHome = null;

       /** Cached local home (EJBLocalHome). Uses lazy loading to obtain its value (loaded by getLocalHo
    me() methods). */
       private static sample.StatisticLocalHome cachedLocalHome = null;

       // Home interface lookup methods

       /**
        * Obtain remote home interface from default initial context
        * @return Home interface for StatisticBean. Lookup using JNDI_NAME
        */
       public static sample.StatisticHome getHome() throws javax.naming.NamingException
       {
          if (cachedRemoteHome == null) {
             // Obtain initial context
             javax.naming.InitialContext initialContext = new javax.naming.InitialContext();
             try {
                java.lang.Object objRef = initialContext.lookup(sample.StatisticHome.JNDI_NAME);
                cachedRemoteHome = (sample.StatisticHome) javax.rmi.PortableRemoteObject.narrow(objRef,
    sample.StatisticHome.class);
             } finally {
                initialContext.close();
             }
          }
          return cachedRemoteHome;
       }

       /**
        * Obtain remote home interface from parameterised initial context
        * @param environment Parameters to use for creating initial context
        * @return Home interface for StatisticBean. Lookup using JNDI_NAME
        */
       public static sample.StatisticHome getHome( java.util.Hashtable environment ) throws javax.naming
    .NamingException
       {
          // Obtain initial context
          javax.naming.InitialContext initialContext = new javax.naming.InitialContext(environment);
          try {
             java.lang.Object objRef = initialContext.lookup(sample.StatisticHome.JNDI_NAME);
             return (sample.StatisticHome) javax.rmi.PortableRemoteObject.narrow(objRef, sample.Statisti
    cHome.class);
          } finally {
             initialContext.close();
          }
       }

       /**
        * Obtain local home interface from default initial context
        * @return Local home interface for StatisticBean. Lookup using JNDI_NAME
        */
       public static sample.StatisticLocalHome getLocalHome() throws javax.naming.NamingException
       {
          // Local homes shouldn't be narrowed, as there is no RMI involved.
          if (cachedLocalHome == null) {
             // Obtain initial context
             javax.naming.InitialContext initialContext = new javax.naming.InitialContext();
             try {
                cachedLocalHome = (sample.StatisticLocalHome) initialContext.lookup(sample.StatisticLoca
    lHome.JNDI_NAME);
             } finally {
                initialContext.close();
             }
          }
          return cachedLocalHome;
       }

    }

    Here's the ejb-jar.xml generate by xdoclet:

    <?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 >
       <display-name>IdsEJB</display-name>
       <enterprise-beans>

          <!-- Entity Beans -->
          <entity >
        
             <ejb-name>StatisticBean</ejb-name>

             <home>sample.StatisticHome</home>
             <remote>sample.Statistic</remote>
             <local-home>sample.StatisticLocalHome</local-home>
             <local>sample.StatisticLocal</local>

             <ejb-class>sample.StatisticBeanCMP</ejb-class>
             <persistence-type>Container</persistence-type>
             <prim-key-class>java.lang.String</prim-key-class>
             <reentrant>False</reentrant>
             <cmp-version>2.x</cmp-version>
             <abstract-schema-name>StatSchema</abstract-schema-name>
             <cmp-field >
                <description><![CDATA[]]></description>
                <field-name>name</field-name>
             </cmp-field>
             <cmp-field >
                <description><![CDATA[]]></description>
                <field-name>value</field-name>
             </cmp-field>
             <primkey-field>name</primkey-field>

             <query>
                <description><![CDATA[]]></description>
                <query-method>
                   <method-name>ejbSelectByName</method-name>
                   <method-params>
                      <method-param>java.lang.String</method-param>
                   </method-params>
                </query-method>
                <ejb-ql><![CDATA[select o.name from Stats o where o.name = ?1]]></ejb-ql>
             </query>
              <!-- Write a file named ejb-finders-StatisticBean.xml if you want to define extra finders. -->
          </entity>


       </enterprise-beans>

       <!-- Relationships -->

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

       <!-- finder permissions -->


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

    </ejb-jar>

    Here's the jboss.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd">

    <jboss>

       <enterprise-beans>
          <entity>
             <ejb-name>StatisticBean</ejb-name>
             <jndi-name>ejb/StatisticBeanRemote</jndi-name>
             <local-jndi-name>ejb/StatisticBeanLocal</local-jndi-name>
             <configuration-name>Standard CMP EntityBean</configuration-name>

          </entity>

       </enterprise-beans>

       <resource-managers>
       </resource-managers>

    </jboss>

    Finally, here's the jbosscmp-jdbc.xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN" "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd">

    <jbosscmp-jdbc>
       <defaults>
       </defaults>

       <enterprise-beans>
          <entity>
             <ejb-name>StatisticBean</ejb-name>
                     <datasource>default</datasource>
                     <datasource-mapping></datasource-mapping>

             <cmp-field>
                <field-name>name</field-name>

                <jdbc-type>VARCHAR</jdbc-type>
                <sql-type>VARCHAR</sql-type>

            </cmp-field>
             <cmp-field>
                <field-name>value</field-name>

                <jdbc-type>VARCHAR</jdbc-type>
                <sql-type>VARCHAR</sql-type>

            </cmp-field>

          </entity>

       </enterprise-beans>

    </jbosscmp-jdbc>


    For brevity, I've removed elements not related to the entity bean in question.

    Any help would be greatly appreciated.
  2. InstantiationException in JBoss[ Go to top ]

    Hello!
    I'm fairly new with that EJB business, but I got the same message while running some examples from the Monson-Haefel book. It turned out I needed to switch to JBoss 4 and J2EE 1.4 (the one with schemas). Which version of JBoss do you run? If you're running 4.x you need to switch back to 3.x and J2EE 1.3 (the one with DTDs). Hope it helps... Al
  3. Even though you are using a local interface, you still must define a ejb-local-ref to the CMP in the deployment descriptor for your session bean, and you still must do a JNDI lookup of the CMP in your session bean, using the resource reference name.

    ejb-jar.xml:

    ...
    <ejb-local-ref id="EJBLocalRef_Stat">
     <description>
     </description>
     <ejb-ref-name>ejb/StatisticLocalRef</ejb-ref-name>
       <ejb-ref-type>Entity</ejb-ref-type>
       <local-home>sample.StatisticLocalHome</local-home>
       <local>sample.StatisticLocal</local>
       <ejb-link>Statistic</ejb-link>
    </ejb-local-ref>
    ...

    Through an application server specific method, the local reference is bound to the JNDI name. I don't know how this is done in JBoss, but the local reference name (ejb/StatisticLocalRef) needs to be associated with the JNDI name (ejb/sample/StatisticLocalHome).


    In your session bean, you access the CMP something like this:

    try {
      javax.naming.Context ctx = new javax.naming.InitialContext();
      StatisticLocalHome statHome = (StatisticLocalHome)ctx.lookup("java:comp/env/ejb/StatisticLocalRef");
      StatisticLocal stat = statHome.create("foo-cnt",0);
    } catch (javax.naming.NamingException ne) {
      // handle this
    } catch (javax.ejb.CreateException ce) {
      // and handle this
    }

    Bill Lasley
    Versant Corp.
    http://www.versant.com