Hi,
I am having a problem using XDoclet to geterate methods into the local interface. The remote interface is working fine.
Either I am missing something, or there are serious performance gains to be made using XDoclet and
EJB.
The generated Local interface looks (IMHO) like a useless extension of the HOME interface!! :-)
On a live bean, deployed in
JBoss, about 99% of the time is spent in the getXXX() and setXXX() methods of remote bean. This is acceptible when I access a few beaans individually, but useless if I want to findall() 20000 beans of 50Kb each and do some work on them.
I want to be able to delegate this task to the EE container so everything runs locally, and get rid of the RMI calls.
Using a value object doesnt help since the data must be streamed between the EE container and the web (
tomcat) containers.
My thinking is to have a number of Stateless Session beans, that run in the EE container and have the form
public
String method() {
// Use JNDI to find Local Business bean
StringBuffer sb = new StringBuffer();
Collection c = bean.findAll();
// Iterate over collection
while (it.hasNext()) {
// get Bean or its attributes
// using REMOTE about 99% of the time is spent HERE
// do something
// log to sb;
// perhaps create some other beans
// can also take substantial time in setXXX) or ejbCreate() methods
}
return sb.toString();
}
Any ideas. or help will be much appreciated.
----------Here is the EJBsource code ---------------------------------------
package natis.ejb;
import java.io.UnsupportedEncodingException;
import java.rmi.*;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.ejb.*;
/**
*
* @ejb.bean
* name="TestBean"
* jndi-name="ejb/TestBeanRemote"
* local-jndi-name="ejb/TestBeanLocal"
* view-type="both"
* type="CMP"
* cmp-version="2.x"
* primkey-field="id"
* local-business-interface="natis.interfaces.TestBeanLocalHome"
* business-interface="natis.interfaces.TestBeanRemoteHome"
*
* @ejb.home
* local-class="natis.interfaces.TestBeanLocalHome"
* remote-class="natis.interfaces.TestBeanRemoteHome"
* @ejb.interface
* local-class="natis.interfaces.TestBeanLocal"
* remote-class="natis.interfaces.TestBeanRemote"
*
* @ejb.finder
* signature="Collection findAll()"
* role-name="Administrator"
* transaction-type="NotSupported"
* unchecked="true"
*
* @ejb.persistence
* read-time-out="10000"
* fetch-size="20"
* table-name="TestBean_001"
*
* @ejb.pk
* generate="true"
* unchecked="true"
*
* @jboss.ejb-external-ref-jndi
* jndi-name="/UUIDKeyGeneratorFactory"
* ref-name="comp:env/keygenerator"
*
*
* @jboss.create-table "${jboss.create.table}"
* @jboss.remove-table "${jboss.remove.table}"
* @jboss.tuned-updates "${jboss.tuned.updates}"
* @jboss.read-only "${jboss.read.only}"
* @jboss.read-ahead strategy="on-load"
* page-size="50"
* eager load group = "TestBeanIndex"
*
* @jboss.persistence
* datasource="java:/DefaultDS"
* datasource-mapping="Hypersonic SQL"
* create-table="true"
* remove-table-"false"
* fetch-size="10"
*
* @ejb.security-identity
* run-as="sa"
*
* @ejb.value-object
* match="*"
*
* @struts.form
* name="Entry"
* include-all="true"
*
* @struts.action
* name="TestSaveAction"
* path="/natis/action/saveTest"
* scope="request"
* roles="*"
*
* @version $Revision: 1.17 $
* @author <a href="mailto:chris@forthtree.co.za@forthtree.co.za">
Chris@forth.co.za</a>
*/
public abstract class TestBean implements EntityBean {
EntityContext entityContext;
/**
* EJBCREATE
* @return pk primary key set to null
*
* @ejb.create-method
*/
public String ejbCreate() throws CreateException {
return null;
}
public void ejbPostCreate() throws CreateException {
}
/**
* Id of this TestBean.
*
* @ejb.pk-field
* class="java.lang.String"
* @ejb.persistent-field
* @ejb.interface-method view-type="both"
*
* @ejb.persistence column-name="TestBean_id"
* @ejb.permission
* role-name="Administrator"
*
* @jboss.unknown-pk
* class="java.lang.String"
* readonly="true"
* column-name="TestBean_id"
* sql-type="char(32)"
* //jboss.auto-increment
*
* @jonas.cmp-field-jdbc-mapping
* field-name="id"
* jdbc-field-name="TestBean_id"
*/
public abstract String getId();
/**
* No interface method for setId(..). See page 130 of the EJB 2.0 specification:
* "Once the primary key for an entity bean has been set, the Bean Provider must
* not attempt to change it by use of set accessor methods on the primary key
* cmp-fields. The Bean provider should therefore not expose the set accessor
* methods for the primary key cmp-fields in the component interface of the
* entity bean.". A work around would be to remove and then an re-create the bean.
*/
protected abstract void setId(String id);
/**
* @ejb.permission
* role-name="Administrator"
* @ejb.transaction
* type="Supports"
* @ejb.value-object
* exclude="false"
* match="*"
* @ejb.persistent-field
* @ejb.persistence
* column-name="mfData"
* sql-type="text(500)"
* @ejb.interface-method
* view-type="both"
*
* @struts.form-field
* form-name="Entry"
*
* @jonas.cmp-field-jdbc-mapping
* field-name="mfData"
* jdbc-field-name="mfData"
*/
public abstract String getData();
/**
* @ejb.permission
* role-name="Administrator"
* @ejb.transaction
* type="Supports"
* @ejb.value-object
* exclude="false"
* match="*"
* @ejb.persistent-field
* @ejb.interface-method
* view-type="both"
*
* @struts.form-field
* form-name="Entry"
*
*/
public abstract void setData(String mfData);
/** * @ejb.interface-method
* view-type="local"
*/
public String toIx() {
return getId() + "|" + getData();
}
/**
* Gets the EntityContext. To be used by classes extending this.
* @return the EntityContext of the EJB
*/
protected EntityContext getEntityContext() {
return entityContext;
}
/** Required to implement EntityBean. Sets the EntityContext. */
public void setEntityContext(EntityContext entityContext) throws EJBException {
this.entityContext = entityContext;
}
/** Required to implement EntityBean. Sets the EntityContext to null. */
public void unsetEntityContext() throws EJBException {
entityContext = null;
}
/** Required to implement EntityBean. Not implemented. */
public void ejbActivate() throws EJBException { }
/** Required to implement EntityBean. Not implemented. */
public void ejbPassivate() throws EJBException { }
/** Required to implement EntityBean. Not implemented. */
public void ejbLoad() throws EJBException { }
/** Required to implement EntityBean. Not implemented. */
public void ejbStore() throws EJBException { }
/** Required to implement EntityBean. Not implemented. */
public void ejbRemove() throws RemoveException, EJBException { }
}
---------- Here is the EJBDOCLET tag --------------------------------------
<target depends="prepare" name="ejbdoclet">
<echo>+---------------------------------------------------+</echo>
<echo>| |</echo>
<echo>| R U N N I N G E J B D O C L E T |</echo>
<echo>| |</echo>
<echo>+---------------------------------------------------+</echo>
<!--
-->
<ejbdoclet
destdir="${project.gen-src.dir}"
mergedir="${project.merge.dir}"
excludedtags="@version,@author,@todo"
addedtags="@xdoclet-generated at ${TODAY},@copyright The Forthtree,@author Chris Rowse, @version ${version}"
ejbspec="2.0"
force="${project.xdoclet.force}"
verbose="true"
>
<fileset dir="${project.java.dir}">
<include name="${project}/ssb/*Bean.java"/>
<include name="${project}/ejb/*Bean.java"/>
<include name="${project}/ejb/*BeanMS.java"/>
<include name="${project}/ejb/${project}*.java"/>
<include name="${project}/ejb/*Error.java"/>
<exclude name="${project}/ejb/Base*.java"/>
</fileset>
<fileset dir="${project.tmp.dir}">
<include name="${project}/**/*Bean.java"/>
<include name="${project}/ejb/*BeanMS.java"/>
<include name="${project}/**/*Error.java"/>
</fileset>
<!--
<fileset dir="${project.java.dir}">
<include name="${project}/ssb/*Bean.java"/>
</fileset>
-->
<packageSubstitution packages="ejb" substituteWith="interfaces"/>
<packageSubstitution packages="absbeans" substituteWith="interfaces"/>
<session/>
<remoteinterface/>
<localinterface/>
<homeinterface/>
<localhomeinterface/>
<!--
<dataobject/>
-->
<valueobject/>
<entitypk/>
<entitycmp/>
<entitybmp/>
<dao>
<packageSubstitution packages="ejb" substituteWith="dao"/>
</dao>
<utilobject cacheHomes="true" includeGUID="true"/>
<deploymentdescriptor
description="${project} Deployment"
destdir="${project.target.dir}/META-INF"
mergedir="${project.merge.dir}"
validatexml="true">
<configParam name="clientjar" value="${project}Client.jar"/>
</deploymentdescriptor>
<jboss
version="3.2"
unauthenticatedPrincipal="nobody"
xmlencoding="UTF-8"
destdir="${project.target.dir}/META-INF"
validatexml="true"
preferredrelationmapping="relation-table"
/>
<!--
<weblogic
version="6.1"
xmlencoding="UTF-8"
destdir="${project.target.dir}/META-INF"
validatexml="true"
datasource="java:/${project}DataSource"
mergedir="${project.merge.dir}"
persistence="weblogic"
/>
<jrun
version="4.0"
xmlencoding="UTF-8"
destdir="${project.target.dir}/MNETA-INF"
validatexml="true"
/>
<webSphere destdir="${project.target.dir}/META-INF"/>
-->
<!--
<jonas
version="2.5"
xmlencoding="UTF-8"
destdir="${project.target.dir}/META-INF"
validatexml="false"
mergedir="${project.merge.dir}"
/>
<orion destdir="${project.target.dir}/META-INF"/>
<apachesoap destdir="${project.target.dir}/META-INF"/>
-->
<strutsform/>
<castormapping destdir="${project.target.dir}/META-INF" validatexml="false"/>
</ejbdoclet>
</target>
---------- Here is the generated Remote interface ------------------
/*
* Generated by XDoclet - Do not edit!
*/
package natis.interfaces;
/**
* Remote interface for TestBean.
* @xdoclet-generated at 2-08-04
* @copyright The Forthtree
* @author Chris Rowse
* @version ${version}
*/
public interface TestBeanRemote
extends javax.ejb.EJBObject
{
/**
* Id of this TestBean.
*/
public java.lang.String getId( )
throws java.rmi.RemoteException;
public java.lang.String getData( )
throws java.rmi.RemoteException;
public void setData( java.lang.String mfData )
throws java.rmi.RemoteException;
}
---------- Here is the generated LOCAL interface
/*
* Generated by XDoclet - Do not edit!
*/
package natis.interfaces;
/**
* Local interface for TestBean.
* @xdoclet-generated at 2-08-04
* @copyright The Forthtree
* @author Chris Rowse
* @version ${version}
*/
public interface TestBeanLocal
extends javax.ejb.EJBLocalObject, natis.interfaces.TestBeanLocalHome
{
}