User: vharcq
Date: 01/06/22 15:16:54
Modified: src/docs cmp.xml
Log:
Compliance 2.2
Revision Changes Path
1.10 +353 -361 manual/src/docs/cmp.xml
Index: cmp.xml
===================================================================
RCS file: /cvsroot/jboss/manual/src/docs/cmp.xml,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- cmp.xml 2001/05/20 19:24:56 1.9
+++ cmp.xml 2001/06/22 22:16:54 1.10
@@ -7,23 +7,30 @@
</author>
<email>[EMAIL PROTECTED]</email>
</para>
+ <para>JBoss 2.2 compliance checked by:<author>
+ <firstname>Vincent</firstname>
+ <surname>Harcq</surname>
+ </author>
+ <email>[EMAIL PROTECTED]</email>
+ </para>
+
<section>
<title>Introduction</title>
<section>
<title>What this article is about</title>
- <para>This article presensts a step-by-step example of
creating, deploying and
+ <para>This article presents a step-by-step example of
creating, deploying and
testing an Entity JavaBean that uses
- `container-managed persistence' with the JBoss EJB server. This
+ "container-managed persistence" with the JBoss EJB server. This
example is very simple, and is a variation of
- the old favourite `music CD' case study. I have chosen this example
+ the old favourite "music CD" case study. I have chosen this example
because the application is likely to be
- familiar to most people without much explanation. In short, the `CD'
+ familiar to most people without much explanation. In short, the "CD"
EJB models a music CD. Applications
will want to add and delete CDs to a collection, and search the collection
for specific CDs. There is also a
- `CDCollection' EJB that lists and searches collections of CDs.</para>
+ "CDCollection" EJB that lists and searches collections of CDs.</para>
<para>
The full source code to accompany this chapter can be found
in either zip (cdEJB.zip) or tar/gzip (cdEJB.tar.gz) format
@@ -33,12 +40,6 @@
contains the Java source code, JavaDoc documentation, and a text file of test
data (CDs.txt) to initialize the
database.</para>
- <para>
-Although I will occasionally make reference to Linux, this is only because
-that's what I use for EJB
-development; most of the material in this article will work with any Unix
-version, and even with Windows NT
-if the directory structure is adjusted accordingly.</para>
</section>
<section>
<title>Pre-requisites</title>
@@ -54,33 +55,19 @@
might want to look at the chapter titled <quote>First Steps</quote> first.</para>
</section>
<section>
- <title>JBoss hints</title>
- <para>JBoss is written entirely in Java, as is the
`Hypersonic' database with
-which it is supplied. Searching a database
-requires lots of repetitive operations, and an interpreting Java system will
-be extremely slow if the database is
-large. If you are using the Sun JDK, you will need to ensure that it is
-configured to use the `Hotspot' virtual
-machine, to achieve anything close to acceptable performance. For the purposes
-of study, you could get along
-by ensuring that the database size is kept small, but with even a hundred
-objects you will find it too slow to use.
-</para>
- </section>
- <section>
<title>Persistence: review</title>
<para>There are, in essence, two kinds of Enterprise JavaBean:
session and entity.
Entity EJBs contain information
that is persistent across different client-Bean interactions, while session
EJBs don't. For example, a class
-called `Customer' that represents the customers of a particular service will
+called "Customer" that represents the customers of a particular service will
contain persistent information
-(about the customer). A class called `CustomerFinder', say, that finds
+(about the customer). A class called "CustomerFinder", say, that finds
Customer instances that match certain
criteria is likely to be a session EJB, because it does not require
information that is maintained between
different client-server interactions.</para>
- <para> Session EJBs can be further divided into
`stateless' and `stateful'. A
+ <para> Session EJBs can be further divided into
"stateless" and "stateful". A
stateful session EJB has a state that is
persistent between invocations of its methods. A stateless EJB does not even
have to retain its state between
@@ -93,13 +80,11 @@
correspondence between instances of an entity EJB and rows of a database
table. In practice, all EJB servers
implement entity instances as table rows. This correspondence is so strong
-that the notion of a `primary key'
-is relevant to an entity EJB. Of course, a primary key is a database concept,
-not an object-orientation concept
-at all.</para>
+that the database notion of a "primary key"
+is relevant to an entity EJB. </para>
<para> The persistence of an entity EJB may be managed
by the Bean itself, or
by the server (technically by the
-`container'). The latter technique is called `Container-managed persistence',
+"container"). The latter technique is called "Container-managed persistence",
and is the subject of the rest of
this article.</para>
</section>
@@ -114,7 +99,7 @@
accessing the database is left to the generated classes. </para>
<para>The breed of CMP that has most value is the "real CMP"
or a CMP where you let
the container manage the
-persistent representation of your beans entirerly. This might not work right
+persistent representation of your beans entirely. This might not work right
now for you if your object are
complex but should work in most simple cases. EJB2.0 also goes the extra
length to make the persistent
@@ -129,10 +114,10 @@
<section>
<title>Determine the persistent classes</title>
<para>In this simple example we will use two Enterprise
JavaBeans. The first, called
-`CD' models a music CD.
+"CD" models a music CD.
It contains attributes (instance variables) that store the title ID code and
various other
-properties of a music CD. The second is called `CDCollection', and models a
+properties of a music CD. The second is called "CDCollection", and models a
collection of such CDs.
This bean acts as a simple interface between the client and the CD Bean;
technically we could
@@ -176,10 +161,8 @@
the persistent attributes. </para>
<para>
In this example, I will assume that the persistent fields are all Java
-`String' values representing
-the ID, title, artist, type and notes. You could, of course, add other
-information you feel to be
-important. </para>
+Primitive type values representing
+the ID, title, artist, type and notes. </para>
</section>
</section>
<section>
@@ -190,214 +173,201 @@
present the full code
for this Bean below; the code for the CDCollection Bean will not be discussed
further because it
-is not interesting in the context of container-managed persistence. Remember
-that the full source code is available to download as an archive
named<quote>cdEJB.zip</quote>. You can get it from the files area in the
-documentation section on www.jboss.org.</para>
- <para>CD.java: remote interface for the `CD' Bean</para>
+is not interesting in the context of container-managed persistence. </para>
+ <para>CD.java: remote interface for the "CD" Bean</para>
<para>
- <programlisting>package com.web_tomorrow.cd;
+ <programlisting><![CDATA[
+package org.jboss.docs.cmp.cd.interfaces;
+import javax.ejb.EJBObject;
import java.rmi.RemoteException;
-import javax.ejb.*;
/**
-This interface defines the remote interface to the `CD' EJB
-*/
-public interface CD extends EJBObject
+ * This interface defines the remote interface for the CD Bean
+ */
+public interface CD
+extends EJBObject
{
-/**
-Get CD title
-*/
-public String getTitle() throws RemoteException;
+ public Integer getId() throws RemoteException;
-/**
-Set CD title
-*/
-public void setTitle(String title) throws RemoteException;
+ public void setId(Integer id) throws RemoteException;
-/**
-Set CD ID code
-*/
-public String getId() throws RemoteException;
+ public String getTitle() throws RemoteException;
-/**
-Get CD ID code
-*/
-public void setId(String id) throws RemoteException;
+ public void setTitle(String title) throws RemoteException;
-/**
-Get artist
-*/
-public String getArtist() throws RemoteException;
+ public String getArtist() throws RemoteException;
-/**
-Set artist
-*/
-public void setArtist(String artist) throws RemoteException;
+ public void setArtist(String artist) throws RemoteException;
-/**
-Get type (rock, classical, chamber music, etc)
-*/
-public String getType() throws RemoteException;
-
-/**
-Set type
-*/
-public void setType(String type) throws RemoteException;
+ public String getType() throws RemoteException;
-/**
-Get notes (comments, not musical notes!)
-*/
-public String getNotes() throws RemoteException;
+ public void setType(String type) throws RemoteException;
-/**
-Set notes
-*/
-public void setNotes(String type) throws RemoteException;
-}</programlisting>
+ public String getNotes() throws RemoteException;
+
+ public void setNotes(String type) throws RemoteException;
+
+}
+]]></programlisting>
</para>
<para>
The remote interface specifies methods to get and set the attributes of the
object.
-That's all it needs to do in this example. Note that, as with any Java Bean,
+That's all it needs to do in this example. Note that, as with any JavaBean,
the
-names of these methods must follow the standard convention; that is, if an
+names of these methods follow the standard convention; that is, if an
attribute
-is called `String X' then the `get' and `set' methods must be defined as
+is called "String X" then the "get" and "set" methods should be defined as
follows: </para>
<programlisting>String getX();
-void setX(String);</programlisting>
- <para>CDHome.java: home interface for the `CD' Bean</para>
- <programlisting>package com.web_tomorrow.cd;
+void setX(String x);</programlisting>
+ <para>However you can declare any methods that return information on
+the state of the entity bean. These methods must be implemented by the programmer
+in the implementation class of the entity bean.</para>
+ <para>CDHome.java: home interface for the "CD" Bean</para>
+ <programlisting><![CDATA[
+package org.jboss.docs.cmp.cd.interfaces;
+import javax.ejb.EJBHome;
+import javax.ejb.CreateException;
+import javax.ejb.FinderException;
import java.rmi.RemoteException;
-import javax.ejb.*;
import java.util.Collection;
/**
-This interface defines the home interface for the `CD' EJB
-*/
-public interface CDHome extends EJBHome
+ * This interface defines the home interface for the CD Bean
+ */
+public interface CDHome
+extends EJBHome
{
-/**
-Create a new CD instance
-*/
-public CD create(String id) throws RemoteException, CreateException;
-
-/**
-Find the CD with the specified ID. This method is not implemented by the Bean,
-but by the container
-*/
-public CD findByPrimaryKey (String id) throws RemoteException,
-FinderException;
-/**
-Finds the CD whose `type' attribute matches that specified. This method is
-implemented by the container
-*/
-public Collection findByType (String type) throws RemoteException,
-FinderException;
+ /**
+ * Create a new CD instance
+ */
+ public CD create(Integer id)
+ throws RemoteException, CreateException;
+
+ /**
+ * Find the CD with the specified ID. This method is implemented by the
+ * container
+ */
+ public CD findByPrimaryKey (Integer id)
+ throws RemoteException, FinderException;
+
+ /**
+ * Finds the CD whose "type" attribute matches that specified.
+ * This method is implemented by the container
+ */
+ public Collection findByType (String type)
+ throws RemoteException, FinderException;
+
+ /**
+ * Get all CD instances. This method is implemented by the container
+ */
+ public Collection findAll()
+ throws RemoteException, FinderException;
-/**
-Get all CD instances. This method is
-implemented by the container
-*/
-public Collection findAll() throws RemoteException, FinderException;
-}</programlisting>
+}
+]]></programlisting>
<para>
The important thing to note about this interface is that it specifies methods
that
don't need to be implemented. In this case, findByPrimaryKey(), findByType()
and findAll()
-are all examples of `finder' methods. The EJB specification requires that the
+are all examples of "finder" methods. The EJB specification requires that the
server be able
to provide finder methods for all the persistent attributes in the object. So,
for example,
-if your class has an attribute `X', then the server will provide a `findByX'
+if your class has an attribute "X", then the server will provide a "findByX"
method to search
-on that field. Note that with JBoss the search is `exact'; that is, it won't
+on that field. Note that with JBoss the search is "exact"; that is, it won't
accept wild-card
characters or an incorrect mixture of upper- and lower-case letters. The
findByPrimaryKey()
searches on the primary key field; we will discuss how the primary key is
specified later.</para>
- <para>CDBean.java: implementation of the `CD' Bean</para>
+ <para>CDBean.java: implementation of the "CD" Bean</para>
<para>
- <programlisting>package com.web_tomorrow.cd;
+ <programlisting><![CDATA[
+package org.jboss.docs.cmp.cd.bean;
+import javax.ejb.EntityBean;
+import javax.ejb.EntityContext;
import java.rmi.RemoteException;
-import javax.ejb.*;
/**
-This class contains the implementation for the methods specified in the home
-and remote interfaces for the `CD' EJB
-*/
-public class CDBean implements EntityBean
+ * This class contains the implementation for the methods specified in the home
+ * and remote interfaces for the "CD" EJB
+ */
+public class CDBean
+implements EntityBean
{
-transient private EntityContext ctx;
+ EntityContext ctx;
-public String id;
-public String title;
-public String artist;
-public String type;
-public String notes;
+ public Integer id;
+ public String title;
+ public String artist;
+ public String type;
+ public String notes;
+
+ /**
+ * Create an instance of a CD. Note that this method returns null because the
real
+ * creation is managed by the EJB container.
+ */
+ public Integer ejbCreate (Integer _id)
+ {
+ id = _id;
+ return null;
+ }
+
+ /**
+ * Called when the object has been instantiated; does nothing in this example
+ */
+ public void ejbPostCreate(Integer id) { }
+
+ public String getTitle() { return title; }
+ public void setTitle(String _title) { title = _title; }
+
+ public Integer getId() { return id; }
+ public void setId(Integer _id) { id = _id; }
+
+ public String getArtist() { return artist; }
+ public void setArtist(String _artist) { artist = _artist; }
+
+ public String getType() { return type; }
+ public void setType(String _type) { type = _type; }
+
+ public String getNotes() { return notes; }
+ public void setNotes(String _notes) { notes = _notes; }
+
+ public void setEntityContext(EntityContext ctx) { this.ctx = ctx; }
+
+ public void unsetEntityContext() { ctx = null; }
+
+ public void ejbActivate() { }
+ public void ejbPassivate() { }
+ public void ejbLoad() { }
+ public void ejbStore() { }
+ public void ejbRemove() { }
-/**
-Create an instance of a CD. Note that this method returns null because the real
-creation is managed by the EJB container.
-*/
-public String ejbCreate (String _id)
-{
- id = _id;
- return null;
}
-
-/**
-Called when the object has been instantiated; does nothing in this example
-*/
-public void ejbPostCreate(String id) { }
-
-public String getTitle() { return title; }
-public void setTitle(String _title) { title = _title; }
-
-public String getId() { return id; }
-public void setId(String _id) { id = _id; }
-
-public String getArtist() { return artist; }
-public void setArtist(String _artist) { artist = _artist; }
-
-public String getType() { return type; }
-public void setType(String _type) { type = _type; }
-
-public String getNotes() { return notes; }
-public void setNotes(String _notes) { notes = _notes; }
-
-public void setEntityContext(EntityContext ctx) { this.ctx = ctx; }
-
-public void unsetEntityContext() { ctx = null; }
-
-public void ejbActivate() { }
-public void ejbPassivate() { }
-public void ejbLoad() { }
-public void ejbStore() { }
-public void ejbRemove() { }
-}</programlisting>
+]]></programlisting>
</para>
<para>
The CDBean class provides implementations of the methods that aren't provided
automatically
-by the EJB container. Note that the ejbCreate method returns `null', meaning
+by the EJB container. Note that the ejbCreate method returns "null", meaning
that the
container should take care of initializing the instance in the server's
process space.
Because the CD Bean is essentially passive -- a data repository -- it only has
-a few methods.
-These classes (and the CDCollection classes) can be compiled in the usual way;
-don't forget
-to include the path to the JBoss EJB class library in your classpath, e.g.,</para>
- <para>
- <command>javac -classpath /usr/local/jboss/client/ejb.jar:.
....</command>
- </para>
+a few methods. </para>
+ <para>To be able to compile these classes, you need to add to your classpath
+a jar containing definitions of javax.ejb.*. Usually this is done by ejb.jar or
+j2ee.jar. With JBoss, you have to use instead jboss-client.jar which is a bundle of
+all J2EE API (javax.ejb, javax.jms, javax.resource, javax.transaction).
+ JBoss, you</para>
</section>
<section>
<title>Packaging and deploying the Beans</title>
@@ -406,129 +376,143 @@
for a session bean. This information is provided in the deployment descriptor
ejb-jar.xml</para>
<programlisting><![CDATA[
-<enterprise-beans>
- <entity>
- <description>Models a music CD</description>
- <ejb-name>CDBean</ejb-name>
- <home>com.web_tomorrow.cd.CDHome</home>
- <remote>com.web_tomorrow.cd.CD</remote>
- <ejb-class>com.web_tomorrow.cd.CDBean</ejb-class>
- <persistence-type>Container</persistence-type>
- <prim-key-class>java.lang.String</prim-key-class>
- <reentrant>False</reentrant>
- <cmp-field><field-name>id</field-name></cmp-field>
- <cmp-field><field-name>title</field-name></cmp-field>
- <cmp-field><field-name>artist</field-name></cmp-field>
- <cmp-field><field-name>type</field-name></cmp-field>
- <cmp-field><field-name>notes</field-name></cmp-field>
- <primkey-field>id</primkey-field>
- </entity>
+<?xml version="1.0"?>
-<!-- more beans here -->
+<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans
1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">
-</enterprise-beans>
+<ejb-jar>
+ <display-name>MusicCDs</display-name>
+ <enterprise-beans>
+
+ <entity>
+ <description>Models a music CD</description>
+ <ejb-name>CDBean</ejb-name>
+ <home>org.jboss.docs.cmp.cd.interfaces.CDHome</home>
+ <remote>org.jboss.docs.cmp.cd.interfaces.CD</remote>
+ <ejb-class>org.jboss.docs.cmp.cd.bean.CDBean</ejb-class>
+ <persistence-type>Container</persistence-type>
+ <prim-key-class>java.lang.Integer</prim-key-class>
+ <reentrant>False</reentrant>
+ <cmp-field><field-name>id</field-name></cmp-field>
+ <cmp-field><field-name>title</field-name></cmp-field>
+ <cmp-field><field-name>artist</field-name></cmp-field>
+ <cmp-field><field-name>type</field-name></cmp-field>
+ <cmp-field><field-name>notes</field-name></cmp-field>
+ <primkey-field>id</primkey-field>
+ </entity>
+
+ <session>
+ <description>Models a music CD collection</description>
+ <ejb-name>CDCollectionBean</ejb-name>
+ <home>org.jboss.docs.cmp.cd.interfaces.CDCollectionHome</home>
+ <remote>org.jboss.docs.cmp.cd.interfaces.CDCollection</remote>
+ <ejb-class>org.jboss.docs.cmp.cd.bean.CDCollectionBean</ejb-class>
+ <session-type>Stateless</session-type>
+ <transaction-type>Container</transaction-type>
+ <ejb-ref>
+ <ejb-ref-name>ejb/CD</ejb-ref-name>
+ <ejb-ref-type>Entity</ejb-ref-type>
+ <home>org.jboss.docs.cmp.cd.interfaces.CDHome</home>
+ <remote>org.jboss.docs.cmp.cd.interfaces.CD</remote>
+ <ejb-link>CDBean</ejb-link>
+ </ejb-ref>
+ </session>
+
+ </enterprise-beans>
+
+ <assembly-descriptor>
+ <container-transaction>
+ <method>
+ <ejb-name>CDBean</ejb-name>
+ <method-name>*</method-name>
+ </method>
+ <trans-attribute>Required</trans-attribute>
+ </container-transaction>
+ </assembly-descriptor>
+</ejb-jar>
]]></programlisting>
- <para>The listing above shows the section of ejb-jar.xml that is
relevant to the CD
-Bean. It has the
+ <para>The first part of the listing above shows the section of
ejb-jar.xml that
+is relevant to the CD Bean. It has the
usual information about the classes that consitute the Bean, but it also
specifies the type
and name of the primary key, and the fields that are persistent. Note that in
this case the
-`id' field gets listed twice: once as a persistent field and then again as the
+"id" field gets listed twice: once as a persistent field and then again as the
primary key field.
It might be thought that specifying a field as a primary key would
automatically make it persistent,
-but it doesn't. Leaving out thecmp-field definition for the primary key
-results in this error
-message at deployment time:</para>
- <para>
- <computeroutput>[JAWS] Initializing JAWS plugin for CDBean
-[Container factory] java.lang.NoSuchFieldException:
CASE_INSENSITIVE_ORDER</computeroutput>
- </para>
- <para>The deployment descriptor for the CDCollection class does not
require any
+but it doesn't. </para>
+ <para>The second part of the listing is for the CDCollection session
bean.
+It does not require any
persistence information,
but it does require an ejb-ref section; this indicates that the CDCollection
Bean refers to CD Bean
instances. The ejb-ref section lists the type of the CD Bean, and all its
classes. </para>
- <programlisting><![CDATA[
-
-<session>
- <description>Models a music CD collection</description>
- <ejb-name>CDCollectionBean</ejb-name>
- <home>com.web_tomorrow.cd.CDCollectionHome</home>
- <remote>com.web_tomorrow.cd.CDCollection</remote>
- <ejb-class>com.web_tomorrow.cd.CDCollectionBean</ejb-class>
- <session-type>Stateless</session-type>
- <transaction-type>Container</transaction-type>
- <ejb-ref>
- <ejb-ref-name>ejb/CD</ejb-ref-name>
- <ejb-ref-type>Entity</ejb-ref-type>
- <home>com.web_tomorrow.cd.CDHome</home>
- <remote>com.web_tomorrow.cd.CD</remote>
- <ejb-link>com.web_tomorrow.cd.CDBean</ejb-link>
- </ejb-ref>
-</session>
-]]></programlisting>
- <para>In the JBoss run-time configuration file `jboss.xml' we should
specify the
+ <para>In the JBoss run-time configuration file "jboss.xml" we should
specify the
JNDI names of the
Beans, like this:</para>
<programlisting><![CDATA[
-<entity>
- <ejb-name>CDBean</ejb-name>
- <jndi-name>cd/CD</jndi-name>
-</entity>
-
-<session>
- <ejb-name>CDCollectionBean</ejb-name>
- <jndi-name>cd/CDCollection</jndi-name>
-</session>
+<?xml version="1.0" encoding="Cp1252"?>
+
+<jboss>
+ <secure>false</secure>
+ <container-configurations />
+ <resource-managers />
+ <enterprise-beans>
+ <session>
+ <ejb-name>CDCollectionBean</ejb-name>
+ <jndi-name>cd/CDCollection</jndi-name>
+ <configuration-name></configuration-name>
+ </session>
+ <entity>
+ <ejb-name>CDBean</ejb-name>
+ <jndi-name>cd/CD</jndi-name>
+ <configuration-name></configuration-name>
+ </entity>
+ </enterprise-beans>
+</jboss>
+
]]></programlisting>
- <para>This says the `CDBean' has the JNDI name `cd/CD' and
`CDCollectionBean' has
-the JNDI name `cd/CDCollection'.
-Note that the method of specifying these JNDI names depends on the server.</para>
+ <para>This says the "CDBean" has the JNDI name "cd/CD" and
"CDCollectionBean" has
+the JNDI name "cd/CDCollection". </para>
<para>When packaging these Beans, don't forget to include the files
ejb-jar.xml and
jboss.jar in the
directory META-INF.During deployment (simply copy the packaged beans to the
-`deploy' subdirectory
+"deploy" subdirectory
of the JBoss directory) you should see a message like the following:</para>
<literallayout>
- <computeroutput>[Container factory]
Deploying:file:/usr/lib/jboss/deploy/cd.jar
+ <computeroutput>[Default] JBoss 2.2.2 Started in 0m:5s
+[Auto deploy] Auto deploy of file:/C:/Projects/jbosscvs22/jboss/dist/deploy/cd.jar
+[J2EE Deployer Default] Deploy J2EE application:
file:/C:/Projects/jbosscvs22/jboss/dist/deploy/cd.jar
+[J2EE Deployer Default] Create application cd.jar
+[J2EE Deployer Default] install module cd.jar
+[Container factory]
Deploying:file:/C:/Projects/jbosscvs22/jboss/dist/tmp/deploy/Default/cd.jar
+[Verifier] Verifying
file:/C:/Projects/jbosscvs22/jboss/dist/tmp/deploy/Default/cd.jar/ejb1001.jar
[Container factory] Deploying CDBean
[Container factory] Deploying CDCollectionBean
-[JAWS] Initializing JAWS plugin for CDBean
-[JAWS] Remove:DELETE FROM CDBean WHERE id=?
-[JAWS] Drop:DROP TABLE CDBean
-[JAWS] Create table:CREATE TABLE CDBean (notes VARCHAR(256),title
-VARCHAR(256),artist VARCHAR(256),id VARCHAR(256),type VARCHAR(256))
-[JAWS] Insert:INSERT INTO CDBean (notes,title,artist,id,type) VALUES
-(?,?,?,?,?)
-[JAWS] Select:SELECT notes,title,artist,id,type FROM CDBean WHERE id=?
-[JAWS] Table CDBean exists
-[Container factory] Started: CDBean
-[Container factory] Bind ejb/CD to com.web_tomorrow.cd.CDBean
-[Container factory] Started: CDCollectionBean
-[Container factory] Bound CDBean to cd/CD
-[Container factory] Bound CDCollectionBean to cd/CDCollection
-[Container factory] Deployed application:
file:/usr/lib/jboss/deploy/cd.jar</computeroutput>
+[JAWS] Created table 'CDBean' successfully.
+[Bean Cache] Cache policy scheduler started
+[Container factory] Deployed application:
file:/C:/Projects/jbosscvs22/jboss/dist/tmp/deploy/Default/cd.jar
+[J2EE Deployer Default] J2EE application:
file:/C:/Projects/jbosscvs22/jboss/dist/deploy/cd.jar is deployed.</computeroutput>
</literallayout>
- <para>`JAWS' is the JBoss interface to the database engine. During
deployment JAWS
+ <para>"JAWS" is the JBoss interface to the database engine. During
deployment JAWS
has
-deleted any existing table called `CDBean', then created a new CDBean table
+deleted any existing table called "CDBean", then created a new CDBean table
with
the specified column layout. How does it know to use VARCHAR(256) for each
field?
It doesn't: it's guessing because we haven't provided any other information.
-During deployment, JAWS looks for a file called `jaws.xml'; if this file
+During deployment, JAWS looks for a file called "jaws.xml"; if this file
exists
it is read to configure the names and geometry of the database tables.
VARCHAR(256) is the default for String attributes. The default table name is
the
same as that of the Bean class, which is why we have ended up with a table
called
-`CDBean'. This also can be over-ridden in jaws.xml. In practice, the JAWS
+"CDBean". This also can be over-ridden in jaws.xml. In practice, the JAWS
defaults
-are adequate for most applications. However, there may be speed advantages to
+are adequate during developement. However, there may be speed advantages to
using fixed-length fields (e.g., CHAR(XX) rather than variable-length ones if
at
all possible.</para>
@@ -556,104 +540,112 @@
CDCollection bean
as a mediator. CDCollection is a stateless session bean. In this example, the
client
-calls the `findAll' method to get references to all the CD objects currently
+calls the "findAll" method to get references to all the CD objects currently
in the
system. To run this client, you will first need to get some CD objects
created. You
-can use the `Upload' client for this, to create CD instances from a text
file.</para>
+can use the "Upload" client for this, to create CD instances from a text
file.</para>
<para>To avoid the necessity to specify the URL of the Bean server in
the client
source code,
this client reads the required information from a properties file called
-`cd.properties'.
+"cd.properties".
The file should contain the URL and driver for the naming service, like this:</para>
-
<para><literallayout>java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
-java.naming.provider.url=localhost:1099</literallayout></para>
+
<para><literallayout>java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
+java.naming.provider.url=localhost
+java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces</literallayout></para>
<para>Of course, if your server and client are on different computers,
you will need
to
-change `localhost' to the real location of the server.</para>
- <para>Here is the full listing of the `List' client.</para>
+change "localhost" to the real location of the server. The JNDI protocol prefix
used by JBoss is "jnp:".
+The URL can also take these values:</para>
+<para><literallayout>localhost
+localhost:1099
+jnp://localhost:1099</literallayout></para>
+ <para>Here is the full listing of the "List" client.</para>
<programlisting><![CDATA[
+package org.jboss.docs.cmp.cd;
-package com.web_tomorrow.cd;
-import javax.naming.*;
+import org.jboss.docs.cmp.cd.interfaces.CD;
+import org.jboss.docs.cmp.cd.interfaces.CDHome;
+import org.jboss.docs.cmp.cd.interfaces.CDCollectionHome;
+import org.jboss.docs.cmp.cd.interfaces.CDCollection;
+import javax.rmi.PortableRemoteObject;
+import javax.naming.InitialContext;
import java.util.Hashtable;
-import javax.rmi.PortableRemoteObject;
import java.util.Properties;
import java.io.FileInputStream;
/**
-This is a simple client for the `CD' EJB; it lists (to standard output) all
-the `CD' instances in
-the system. The `main' method allows this class to be run from the command
-line.
-*/
-class List
-{
-public static void main(String[] args)
+ * This is a simple client for the "CD" EJB; it lists (to standard output) all
+ * the "CD" instances in the system. The "main" method allows this class to be
+ * run from the command line.
+ */
+public class List
{
- // Get information about the Bean server from the properties file
- Properties props = new Properties();
- Properties sysProps = System.getProperties();
- try
- {
- props.load (new FileInputStream ("cd.properties"));
- sysProps.putAll(props);
- }
- catch (Exception e)
- {
- System.err.println ("Can't read `cd.proprties'");
- System.exit (-1);
- }
- System.setProperties (sysProps);
-
- // Enclosing the whole process in a single `try' block is not an ideal way
- // to do exception handling, but I don't want to clutter the program up
- // with catch blocks
- try
- {
- // Get a naming context
- InitialContext jndiContext = new InitialContext();
-
- // Get a reference to a CD Bean
- Object ref = jndiContext.lookup("cd/CDCollection");
-
- // Get a reference from this to the Bean's Home interface
- CDCollectionHome home = (CDCollectionHome)
- PortableRemoteObject.narrow (ref, CDCollectionHome.class);
-
- CDCollection cdCollection = home.create();
-
- CD[] cds = cdCollection.findAll();
- for (int i = 0; i < cds.length; i++)
- {
- System.out.println (cds[i].getId() + "\t" + cds[i].getTitle() + "\t" +
- cds[i].getArtist() + "\t" + cds[i].getType());
- }
- }
- catch(Exception e)
- {
- System.out.println(e.toString());
- }
- }
+ public static void main(String[] args)
+ {
+ // Get information about the Bean server from the properties file
+ Properties props = new Properties();
+ Properties sysProps = System.getProperties();
+ try
+ {
+ props.load (new FileInputStream ("cd.properties"));
+ sysProps.putAll(props);
+ }
+ catch (Exception e)
+ {
+ System.err.println ("Can't read cd.properties");
+ System.exit (-1);
+ }
+ System.setProperties (sysProps);
+
+ // Enclosing the whole process in a single "try" block is not an ideal way
+ // to do exception handling, but I don't want to clutter the program up
+ // with catch blocks
+ try
+ {
+ // Get a naming context
+ InitialContext jndiContext = new InitialContext();
+
+ // Get a reference to a CD Bean
+ Object ref = jndiContext.lookup("cd/CDCollection");
+
+ // Get a reference from this to the Bean's Home interface
+ CDCollectionHome home = (CDCollectionHome)
+ PortableRemoteObject.narrow (ref, CDCollectionHome.class);
+
+ CDCollection cdCollection = home.create();
+
+ CD[] cds = cdCollection.findAll();
+ for (int i = 0; i < cds.length; i++)
+ {
+ System.out.println (cds[i].getId() + "\t" + cds[i].getTitle() + "\t" +
+ cds[i].getArtist() + "\t" + cds[i].getType());
+ }
+ }
+ catch(Exception e)
+ {
+ System.out.println(e.toString());
+ }
+ }
+
}
]]></programlisting>
<para>To run this client you will need to specify in the CLASSPATH the
location the
-JBoss client libraries, so the command line will be at least like this:</para>
- <para>
- <command>java -classpath
-$CLASSPATH:/usr/lib/jboss/client/jboss-client.jar:/usr/lib/jboss/client/jbosssx-client.jar:/usr/lib/jboss/client/jnp-client.jar
com.web_tomorrow.cd.List;</command>
- </para>
- <para>If all is well, you will get a list of CDs.So we've created an
entity EJB, and
-a client
-program that uses it.You'll agree, I hope, that it isn't that much more
-complicated than
+JBoss client libraries. These are jboss-client.jar, jbosssw-client.jar and
jnp-client.jar.</para>
+ <para>You'll agree, that it isn't that much more complicated than
creating a session EJB. The additional steps required are: </para>
<para>The ejb-jar.xml file needs to indicate that the object is
persistent, and list
the persistent fields.
It also needs to specify the name and class of the primary key field. </para>
<para>If the default column names and types aren't what you need,
create a file
jaws.xml to specify them.</para>
+ <para>You should know have a lot of questions : Which database JBoss
used to store the
+data and how can I specify another one? How can I change the definition of the
table that JBoss
+created? Which control does I have on finder methods?</para>
+ <para>All these questions will be answered in the next chapter that
will introduce the
+specific CMP deployment descriptor "jaws.xml" and its default "standardjaws.xml".
Note that this
+default has has been used under the cover by JBoss for this example.</para>
</section>
<section>
<title>Discussion: container-managed persistence</title>
@@ -669,8 +661,8 @@
</para>
<section>
<title>Technical overview </title>
- <para>In the EJB field there is a very strong correspondence
between `rows of a
-database table', and `instances of an object'. It is clear that the EJB
+ <para>In the EJB field there is a very strong correspondence
between "rows of a
+database table", and "instances of an object". It is clear that the EJB
developers had this notion in mind from the very beginning. While the
specification doesn't stipulate that persistence is provided by database
tables, in practice it always is. Moreover, it is tacitly assumed that the
@@ -698,18 +690,18 @@
generate database access statements with the efficiency of a human
programmer. Consider this example: suppose I have an database table containing
details of my music CD collection. I want to search ithe
-collection for any one which has the text `Chopin' (case insensitive) in
-either the `title' or `notes' column. In SQL I could write a statement like
+collection for any one which has the text "Chopin" (case insensitive) in
+either the "title" or "notes" column. In SQL I could write a statement like
this:
<programlisting> SELECT FROM CD WHERE title LIKE "%chopin%" OR notes LIKE
"%chopin%";
</programlisting>
</para>
<para>The % character is an SQL wild-card and takes
care of finding the required
-string somewhere inside the field; the `LIKE' operator is
+string somewhere inside the field; the "LIKE" operator is
case-insensitive by default. How could we achieve this with a
-container-managed EJB? If `CD' is an EJB, the container-supplied method
-`findAll()' in its home interface will get all the current instances of `CD'.
+container-managed EJB? If "CD" is an EJB, the container-supplied method
+"findAll()" in its home interface will get all the current instances of "CD".
In practice it will do this by executing a statement like
@@ -721,7 +713,7 @@
store the primary key from each row of the database into the
appropriate attribute of each CD instance. Then the program must examine the
objects one at a time, checking whether they meet the required
-criteria (i.e., the word `Chopin' in the appropriate attributes). As the
+criteria (i.e., the word "Chopin" in the appropriate attributes). As the
program iterates throuugh the objects, the server must cause their
attributes to be read from the table; it won't have done this until now
because it would try to conserve memory. So for each object examined
@@ -743,8 +735,8 @@
<programlisting> UPDATE CD SET artist="Bloggs" WHERE ID="200";
</programlisting>
</para>
- <para>for example. This is efficient, but requires the
that `Artist' field really be
-called `artist'. This makes it difficult to change the names of columns in
+ <para>for example. This is efficient, but requires the
that "Artist" field really be
+called "artist". This makes it difficult to change the names of columns in
the table. Alternatively the server could do a SELECT to get the current
column values, delete the whole row, then insert a row with modified
values. This allows a number of values to change at once and, because all
@@ -757,7 +749,7 @@
<title>Limitations of late initialization </title>
<para>Suppose we want to find whether a CD with a
specific ID exists on the system.
With CMP this corresponds to finding whether there is a row in
-the database table with the corresponding value of the `id' column. The code
+the database table with the corresponding value of the "id" column. The code
in Java might look like this:<programlisting>// Get a reference to a CD Bean
Object ref = jndiContext.lookup("cd/CD");
@@ -768,8 +760,8 @@
// Find the matching CD
CD cd = home.findByPrimaryKey("xxx");</programlisting>
</para>
- <para>What will happen if `XXX' is not the ID of a CD
that exists? There would seem
-to be two sensible approaches. Either `findByPrimaryKey'
+ <para>What will happen if "XXX" is not the ID of a CD
that exists? There would seem
+to be two sensible approaches. Either "findByPrimaryKey"
could throw an exception, or perhaps it could return a null reference. In
either case the client could easily tell whether the object exists. In
practice, the EJB server may do neither of these things. It may well return a
@@ -778,7 +770,7 @@
initialization won't happen until the object is really required. This is done
to improve efficiency; there is, after all, no need to initialize the object
unless it will be needed. However, if the program continues to execute on
-the basis that `cd' refers to a valid object, an exception will be thrown
+the basis that "cd" refers to a valid object, an exception will be thrown
later when the program tries to interact with it. This may not be a
problem; if the ID had been generated from some earlier database access then
we may be sure it really exists, and any failure to find it in the
@@ -788,7 +780,7 @@
an object after getting a reference to it, like this:<programlisting>CD cd =
home.findByPrimaryKey("xxx");
String dummy = cd.getId();</programlisting>
</para>
- <para>If there is no CD whose ID field is `XXX' then
this will throw a
+ <para>If there is no CD whose ID field is "XXX" then
this will throw a
java.rmi.NoSuchObjectException. This gets around the problem
of late initialization, but at the cost of an additional SQL access.</para>
</section>
@@ -796,17 +788,17 @@
<title>Suitability of container-managed persistence
</title>
<para>In many applications of object-oriented
programming we have had to accept that
some things that are philosophically objects are in reality
-implemented as something else. The `something else' may be a row of a database
+implemented as something else. The "something else" may be a row of a database
table, or a line of a text file, or whatever; at some point we
had to code the interface between the object-oriented system and the
-`something elses'. Entity JavaBeans goes some way towards
+"something elses". Entity JavaBeans goes some way towards
eliminating this problem; things that are philosophically object can be
modelled as objects, with methods and persistence. But this comes at a
-cost. It's worth asking whether the `CD' EJB in the tutorial example really is
+cost. It's worth asking whether the "CD" EJB in the tutorial example really is
an object in a meaningful sense. It has attributes, but it doesn't do
very much. We don't really gain all that much by making it an object; it could
have remained a database row, and been manipulated through the
-`CDCollection' class. Of course this isn't as elegant, but elegance can come
+"CDCollection" class. Of course this isn't as elegant, but elegance can come
at a high price. </para>
<para>In summary then, container-managed persistence
is straightforward to
implement using JBoss (or any other EJB server, for that matter)
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development