User: starksm 
  Date: 01/04/19 21:19:06

  Modified:    src/docs jbossintro.xml
  Log:
  Clean up the tutorial as it was rather rambling
  
  Revision  Changes    Path
  1.12      +603 -755  manual/src/docs/jbossintro.xml
  
  Index: jbossintro.xml
  ===================================================================
  RCS file: /cvsroot/jboss/manual/src/docs/jbossintro.xml,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- jbossintro.xml    2001/04/12 12:17:59     1.11
  +++ jbossintro.xml    2001/04/20 04:19:06     1.12
  @@ -1,755 +1,603 @@
  -<chapter>
  -     <title>First steps</title>
  -     <para>Author:
  -     <author>
  -                     <firstname>Kevin</firstname>
  -                     <surname>Boone</surname>
  -             </author>
  -             <email>[EMAIL PROTECTED]</email>
  -             <author>
  -                     <firstname>Tobias</firstname>
  -                     <surname>Frech</surname>
  -             </author>
  -     </para>
  -     <section>
  -             <title>Introduction</title>
  -             <section>
  -                     <title>What this section is about</title>
  -                     <para>
  -This section presents a step-by-step tutorial on how to set up `JBoss', the 
  -free Enterprise JavaBean (EJB) server, and create your first
  -Enterprise JavaBean and client. It doesn't explain what Enterprise JavaBeans 
  -are, or how they are used; there are a number of good
  -introductory articles on Sun's JavaSoft Web site. Although the description is 
  -based on the use of a Linux server, most of the issues discussed in
  -this article will also apply to other platforms. If you are using a Windows 
  -platform you will need to pay attention to the directory names, which
  -will be different from the one's I've assumed. 
  -</para>
  -             </section>
  -             <section>
  -                     <title>About JBoss</title>
  -                     <para>
  -JBoss is an implementation of the EJB 1.1 (and parts of 2.0)
  -specification, that is, it is a  
  -server and container for Enterprise JavaBeans. In this it is similar to Sun's
  -`J2SDK Enterprise Edition' (J2EE), but JBoss is much more single-minded than 
  -J2EE. JBoss provides only an EJB server; it does not include
  -support for JSP, SSL, and all the other protocols that the Sun product can 
  -handle. This means that it is smaller in memory and in disk space.
  -JBoss will run very effectively on a machine with 64 megabytes of RAM, and 
  -requires only some megabytes of disk (including source code!). Sun's
  -J2EE requires a minimum of 128 megabytes of RAM, and 31 megabytes of disk 
  -space. That's not to criticise the Sun product; it is a
  -heavyweight offering providing a host of services. Because of its small memory 
  -footprint, JBoss starts up about 10 times faster than J2EE.
  -There is a built-in SQL database server for handling persistent beans, and 
  -this starts up automatically with the server (J2EE ships with the
  -CloudScape SQL server, which has to be started separately). 
  -</para>
  -                     <para>
  -       One of the nicest features of JBoss is its support for `hot' 
  -deployment. What this means is that deploying a Bean is a simple as copying its
  -JAR file into the deployment directory. If this is done while the Bean is 
  -already loaded, JBoss automatically unloads it, then loads the new
  -version. Contrast this with the rigmarole that J2EE makes us go through... 
  -JBoss is distributed under the GNU public licence, which means that
  -it's free, even for commercial work, and is likely to remain that way. You get 
  -no support, of course. 
  -</para>
  -                     <para>
  -       The main weakness of JBoss is its documentation. There is, essentially, 
  -none. There is a mailing list, and you will almost certainly need
  -recourse to it at some point. This article hopes to remedy this deficiency, to 
  -a small degree, by describing step-by-step how a simple EJB can
  -be created, deployed and tested on the JBoss server. 
  -</para>
  -             </section>
  -             <section>
  -                     <title>Pre-requisites</title>
  -                     <para>
  -JBoss is written entirely in Java, and requires a Java system compatible with 
  -JDK 1.3. This is essential, not optional. Trust me on this; I've tried
  -it with JDK 1.2.2 and the `hot' deployment facility simply doesn't work. Since 
  -it is now possible to get Linux JDKs directly from Sun, there's
  -little reason not to upgrade if you're using an earlier version. </para>
  -                     <para>
  -I will assume that you are basically familiar with EJBs (and roughly know, for 
  -example, what a `home interface' is) and know how to compile Java
  -classes. 
  -</para>
  -             </section>
  -     </section>
  -     <section>
  -             <title>Installing JBoss</title>
  -             <para>Before installing and running the server, you should check that 
your JDK 
  -installation is working. You will 
  -need the JDK binaries directory in your PATH (this is essential: see below) 
  -not just for the user account which is doing the installation, but also for 
  -the user account that will run the server. If you are running the server as 
  -root, you should check that the JDK binaries are in the PATH even for root 
  -(root and ordinary users normally have different PATH settings). You won't 
  -need to specify a CLASSPATH environment variable if you don't normally have 
  -to.</para>
  -             <para>The next step will be to download, install and test the JBoss 
server. At 
  -the time of writing the most recent version of JBoss is 2.2.</para>
  -             <para>It doesn't matter very much where you install JBoss; my 
preference is to 
  -use /usr/local/jboss. If you don't have root access, or would rather not run 
  -untested software as root, jboss will work perfectly well if installed in a 
  -user directory and run as an ordinary user. I will assume in this tutorial 
  -that you are installing in /usr/local/jboss. If you haven't, change the paths 
  -as appropriate.</para>
  -             <para>JBoss is distributed as a ZIP file. You can download the binary
  -distribution which contains the latest offical release (which was 2.2
  -at the time of writing) or a source snapshot with the latest
  -version from CVS. This documentation mainly is written
  -for the 2.1 
  -version. You can get all the mentioned packages from http://www.jboss.org .
  -</para>
  -             <formalpara>
  -                     <title>Installation of binary package for Windows:</title>
  -                     <para>Download the binary package from http://www.jboss.org 
from the
  -Download - Binary section. Place it in a temporary directory and use your
  -favorite unziper to decompress it to the place where you want JBoss
  -installed. Start the "command line" from "Accessories" menu and change to
  -the directory to which you just decompressed the binary package. In
  -the following descriptions you will need to replace /usr/local/jboss/
  -with the path you selected to install JBoss to (e.g. c:\jboss\ ). Also
  -note that Windows is not using a colon <quote>:</quote> but a
  -semicolon <quote>;</quote> to separate
  -multiple entries in paths (e.g. the CLASSPATH).
  -</para>
  -             </formalpara>
  -             <formalpara>
  -                     <title>Installation of binary package for Linux:</title>
  -                     <para>
  -                             <literallayout>
  -                                     <command>cd /tmp/
  -lynx -source http://www.jboss.org/newsite/bin/jboss-2.2.zip > jboss-2.2.zip
  -su
  -cd /usr/local/
  -unzip /tmp/jboss-2.2.zip
  -mv jboss-2.2 jboss
  -cd jboss
  -</command>
  -                             </literallayout>
  -                     </para>
  -             </formalpara>
  -             <para>Now change to the user as which you want to run the
  -server. Please make sure, that this user has the JDK binaries in his
  -command path and that he has write access to the JBoss directory
  -(needed for log files and deployment).
  -You are now ready to change to the bin directory, and 
  -run the program like this: </para>
  -             <literallayout>
  -                     <command>cd bin
  -/bin/sh run.sh</command>
  -             </literallayout>
  -             <para>In a proper installation, the server should start without any 
error 
  -messages or exceptions being thrown. It will produce several pages of 
  -output on startup.</para>
  -             <!-- outdated, no test included in binary distro
  -<para>The JBoss distribution is supplied with one test Bean, packaged as 
  -bank.jar. This is supplied in the `deploy' subdirectory, which is where Beans 
  -are placed to deploy them. The effect of this is to deploy the `bank' bean 
  -when the server starts up. This is fine the first time, as it tests that the 
  -SQL server is working, but you can usefully move bank.jar out of the deploy 
  -directory when you are sure that everything's OK, and the server will start up 
  -more quickly.</para>
  --->
  -     </section>
  -     <section>
  -             <title>Creating the Bean</title>
  -             <para>
  -In this step we will write and compile a simple Enterprise JavaBean. You can 
  -download the source code for this example; according to which unpacker
  -(WinZIP, unzip, tar) you have available either download
  -interestEJB.zip or interestEJB.tar.gz from the file section in the
  -documentation section on www.jboss.org . You will need to 
  -unpack the archive into an empty directory.</para>
  -             <para>The example -- which is called `Interest' -- is about as simple 
as an 
  -EJB can get: it is a `stateless session bean'. Its job is to calculate the 
  -amount of compound interest payable on a sum of money borrowed over a 
  -specified term with a specified interest rate. In fact, there is only one 
  -functional line of code in the whole package.</para>
  -             <para>If you want to compile the classes yourself, you'll need to 
create a 
  -directory hierarchy that reflects the structure of the pacakage. The package 
  -in this example is com.web_tomorrow.interest so you'll need to create the 
  -directory structure: 
  -<literallayout>
  -com
  -  web_tomorrow
  -      interest
  -          {java source and class files here}
  -
  -</literallayout>
  -If you unpack the interestEJB-archive it will create a subdirectory
  -called "interest" and the needed structure automatically below it.</para>
  -     </section>
  -     <section>
  -             <title>EJBs: review</title>
  -             <para> As a reminder, and Enterprise JavaBean has a minimum of three 
  -classes.The remote interface. This is the class that exposes the methods of 
  -the Bean to the outside world. In the example, the remote interface is the 
  -class com.web_tomorrow.interest.Interest The Bean class. This implements the 
  -methods specified by the remote interface. In this example, the Bean class is 
  -com.web_tomorrow.interest.InterestBean The home interface. This specifies how 
  -a new Bean is created, managed and deleted. As a minimum it should specify at 
  -least one create() method. There should be an ejbCreate() method in the Bean 
  -class for each create() method in the home interface. In this example, the 
  -home interface is com.web_tomorrow.InterestHome </para>
  -             <para> Of course, a Bean can include other classes, or even other 
packages, 
  -but the classes listed above are the minimum. The classes must be packaged 
  -into a JAR archive with a directory structure that reflects the hierarchy of 
  -packages. In the example, the classes are in the package 
  -com.web_tomorrow.interest, so they need to be in the directory </para>
  -             <para>./com/web_tomorrow/interest/</para>
  -             <para>where the `.' represents the current working directory, wherever 
that 
  -is. You will also need a directory called META-INF to store the deployment 
  -descriptor (always called ejb-jar.xml) and -- optionally -- another XML file 
  -to tell the server about name mappings. With JBoss, this file must be called 
  -jboss.xml.</para>
  -             <para>So before writing the classes, we need a directory structure 
like this:  
  -<literallayout>
  -   com
  -    web_tomorrow
  -        interest
  -            {java source and class files here}
  -
  -   META-INF
  -        ejb-jar.xml
  -        jboss.xml (optional)
  -
  -</literallayout>
  -             </para>
  -             <para>If the jar utility is run at the top level of this directory 
structure, 
  -it will put the files in the right ordering in the archive. We will discuss 
  -the creation of the XML files later.</para>
  -             <para>Of course, in your own work you will create a directory 
hierarchy that 
  -reflect the package hierarchy you need, rather than `com.web_tomorrow.XXXX' 
  -</para>
  -     </section>
  -     <section>
  -             <title>Coding the classes</title>
  -             <para>We need three classes: the remote interface, the Bean, and the 
home 
  -interface. All the .java files will go in the subdirectory 
  -./com/web_tomorrow/interest.
  -The remote interface in this example is very simple.
  -</para>
  -             <figure>
  -                     <title>Remote interface for the `interest' EJB, file name 
Interest.java</title>
  -                     <programlisting>
  -package com.web_tomorrow.interest;
  -import javax.ejb.EJBObject;
  -import java.rmi.RemoteException;
  -
  -/**
  -This interface defines the `Remote' interface for the `Interest' EJB. Its
  -single method is the only method exposed to the outside world. The class
  -InterestBean implements the method.
  -*/
  -
  -public interface Interest extends EJBObject 
  -{
  -/**
  -Calulates the compound interest on the sum `principle', with interest rate per
  -period `rate' over `periods' time periods. This method also prints a message to
  -standard output; this is picked up by the EJB server and logged. In this way we
  -can demonstrate that the method is actually being executed on the server,
  -rather than the client.
  -*/
  -public double calculateCompoundInterest(double principle, 
  -  double rate, double periods) throws RemoteException;
  -}
  -</programlisting>
  -             </figure>
  -             <para> The remote interface specifies only one `business method' 
  -calculateCompoundInterest.   The home interface is even simpler. </para>
  -             <figure>
  -                     <title>Home  interface for the `interest' EJB, file name 
InterestHome.java</title>
  -                     <programlisting>
  -package com.web_tomorrow.interest;
  -import java.io.Serializable;
  -import java.rmi.RemoteException;
  -import javax.ejb.CreateException;
  -import javax.ejb.EJBHome;
  -
  -/**
  -This interface defines the `home' interface for the `Interest' EJB. 
  -*/
  -
  -public interface InterestHome extends EJBHome {
  -  /**
  -  Creates an instance of the `InterestBean' class on the server, and returns a
  -  remote reference to an Interest interface on the client. 
  -  */
  -  Interest create()
  -    throws RemoteException, CreateException;
  -}
  -</programlisting>
  -             </figure>
  -             <para>Finally, here is the Bean class. This is the only one that does 
any real 
  -work in this simple example.</para>
  -             <figure>
  -                     <title>Bean class for the `interest' EJB, file name 
InterestBean.java</title>
  -                     <programlisting>
  -
  -package com.web_tomorrow.interest;
  -import java.rmi.RemoteException; 
  -import javax.ejb.SessionBean;
  -import javax.ejb.SessionContext;
  -
  -/**
  -This class contains the implementation for the `calculateCompoundInterest'
  -method exposed by this Bean. It includes empty method bodies for the methods
  -prescribe by the SessionBean interface; these don't need to do anything in this
  -simple example.
  -*/
  -
  -public class InterestBean implements SessionBean {
  -  /**
  -  Calulates the compound interest on the sum `principle', with interest rate   
  -  per period `rate' over `periods' time periods. This method also prints a          
 
  -  message to standard output; this is picked up by the EJB server and logged.  
  -  In this way we can demonstrate that the method is actually being executed on 
  -  the server, rather than the client.
  -  */
  -  public double calculateCompoundInterest(double principle, 
  -    double rate, double periods) {
  -    System.out.println ("Someone called `calculateCompoundInterest!'");
  -    return principle * Math.pow(1+rate, periods) - principle;
  -  }
  -
  -  /**
  -  Empty method body
  -  */
  -  public InterestBean() {}
  -  /**
  -  Empty method body
  -  */
  -  public void ejbCreate() {}
  -  /**
  -  Empty method body
  -  */
  -  public void ejbRemove() {}
  -  /**
  -  Empty method body
  -  */
  -  public void ejbActivate() {}
  -  /**
  -  Empty method body
  -  */
  -  public void ejbPassivate() {}
  -  /**
  -  Empty method body
  -  */
  -  public void setSessionContext(SessionContext sc) {}
  -}  
  -</programlisting>
  -             </figure>
  -             <para>Notice that most of the methods are empty; they have to exist 
because 
  -they're specified by the SessionBean interface, but they don't need to do 
  -anything in this case.</para>
  -             <para>If you haven't already done so, you should create these .java 
files in 
  -the directory com/web_tomorrow/interest (or unpack the archive with them 
  -in). Then you can compile them using the command 
  -<command>javac -classpath /usr/local/jboss/client/ejb.jar 
com/web_tomorrow/interest/*.java</command>
  -             </para>
  -             <para>
  -Substituting the correct path to the JBoss class EJB library if you haven't 
  -installed JBoss in /usr/local/jboss. Also remember to start
  -compilation from your source root directory, which is right above
  -<quote>com</quote> from com/web_tomorrow/interest/. 
  -This should create three class files: 
  -InterestBean.class, Interest.class, and InterestHome.class.
  -With the classes compiled, it's time to create the deployment 
  -descriptor.</para>
  -     </section>
  -     <section>
  -             <title>The deployment descriptor</title>
  -             <para>Now it's time to create the deployment descriptor. As a 
reminder, this 
  -file tells the EJB server which classes form the Bean, the home interface and 
  -the remote interface. If there is more than one Bean in the package, it 
  -indicates also how the Beans interact with one another. In this simple 
  -example, there is only one Bean so we won't need to worry about that 
  -part.</para>
  -             <para>Most commercial EJB servers are supplied with graphical tools 
for 
  -constructing the deployment descriptor. JBoss does have an XML editor, but 
  -it's just as easy to construct the deployment descriptor manually. Here it 
  -is:</para>
  -             <figure>
  -                     <title>Deployment descriptor for the Interest Bean</title>
  -                     <literallayout><![CDATA[
  -<?xml version="1.0" encoding="Cp1252"?>
  -  <ejb-jar>
  -     <description>JBoss test application</description>
  -     <display-name>Test</display-name>
  -     <enterprise-beans>
  -       <session>
  -         <ejb-name>Interest</ejb-name>
  -         <home>com.web_tomorrow.interest.InterestHome</home>
  -         <remote>com.web_tomorrow.interest.Interest</remote>
  -         <ejb-class>com.web_tomorrow.interest.InterestBean</ejb-class>
  -         <session-type>Stateless</session-type>
  -         <transaction-type>Bean</transaction-type>
  -       </session>
  -     </enterprise-beans>
  -   </ejb-jar> 
  -]]></literallayout>
  -             </figure>
  -             <para>The deployment descriptor must be called ejb-jar.xml and it must 
be in 
  -the directory ./META-INF. A common mistake is to name this directory 
  -`META_INF' (with an underscore, rather than a dash) or write it lower
  -case, which won't work.</para>
  -             <para> In principle what we deploy on the server is an application, 
not a 
  -Bean. In this example our application consists of exactly one Bean, so it 
  -comes to the same thing. In the deployment descriptor, the section 
  -<![CDATA[<ejb-name>Interest</ejb-name>]]>  assigns a name to the Bean. jboss 
  -in its 
  -standard configuration will put the bean's home interface under the ejb-name 
  -moniker if you don't specify anything else. In other words, when your 
  -applications want to access the bean through it's home jboss will put it in 
  -JNDI under the ejb-name. </para>
  -             <para>In practice client applications are not forced to use this name. 
  -Typically a developer will not bother with specifying a different name for the 
  -JNDI namespace. However a production installation of a complete application 
  -comprising many beans, will usually use a different name than the one 
  -specified by the developer. Typically it could use `[application name]/[bean 
  -name]', which is what we shall use later.</para>
  -             <para>Although the deployment descriptor format of the ejb-jar.xml 
file is 
  -common to all EJB servers, and precisely defined in a DTD you can get from 
  -SUN, it doesn't specify some advanced stuff. Specifically it does not know how 
  -to map ejb-name to a deployment JNDI such as the one we just talked about. It 
  -also doesn't know how to map resources. The server may also need to be told 
  -how to manage persistence and state. There is, as yet, no standard way of 
  -specifying these things, and every server implementation does it differently. 
  -</para>
  -             <para>The approach taken by JBoss is it provides a standard behaviour 
that 
  -works mostly from the ejb-jar.xml file. There is no need for additional 
  -information in most cases. In case of advanced configurations we define the 
  -jboss.xml file that gives all the relevant information to the container, such 
  -as JNDI mapping names, persistence information, database mapping and advanced 
  -container configuration (interceptors and plugins), please refer to the 
  -section on jboss.xml for detailed information of what it can do, we will cover 
  -simple things here. </para>
  -             <para>The standard behaviour of jboss is capable of working from 
ejb-jar.xml 
  -in 95% of cases and needs jboss.xml only if you need to specify specific 
  -deployment information. </para>
  -             <para>An additional feature of the new metadata is that it works 
  -"differentially". In clear what this means is that if you wish to override the 
  -name of a bean you need to only specify that part of xml tags in the jboss.xml 
  -file.</para>
  -             <para>Using the ejb-name from ejb-jar.xml
  -for most development purposes, as soon as you provide a ejb-jar.xml with the 
  -beans the container will get the ejb-name as the JNDI name as standard 
  -behaviour.  This makes your development life easier.</para>
  -             <para>If you don't provide a jboss.xml file you will find your bean 
under the 
  -name "Interest".</para>
  -             <section>
  -                     <title>Overriding ejb-name with a real JNDI name in 
jboss.xml</title>
  -                     <para>If in deployment you would rather use the "myApp/myBean" 
naming pattern 
  -you need to provide the following text in jboss.xml. </para>
  -                     <para>jboss.xml:</para>
  -                     <figure>
  -                             <title>The JBoss XML descriptor. (Optional, this file 
is provided by 
  -the Bean deployer)</title>
  -                             <literallayout><![CDATA[
  -<jboss>
  -  <enterprise-beans>
  -    <session>
  -      <ejb-name>Interest</ejb-name>
  -      <jndi-name>interest/Interest</jndi-name>
  -    </session>
  -    <secure>false</secure>
  -  </enterprise-beans>
  -</jboss>
  -]]></literallayout>
  -                     </figure>
  -                     <para>All this file says is that the Bean called Interest is 
assigned the JNDI 
  -name of interest/Interest.</para>
  -                     <para>The indentation is just there for formatting and 
readability, it is non 
  -important.</para>
  -                     <para>So now we've got the deployment descriptor ejb-jar.xml. 
Again JBoss will 
  -happily run just from that file and bind the object under "Interest" as 
  -standard JNDI name. We also have the optional jboss.xml to provide another 
  -name "interest/Interest" to overwrite the standard behaviour with JNDI. We 
  -also have the classes. It's time to package them together.</para>
  -             </section>
  -     </section>
  -     <section>
  -             <title>Packaging and deploying the bean</title>
  -             <para>Creation of the Bean package involves building a JAR archive 
containing 
  -the classes and the XML files. For the example Bean we have been discussing, 
  -this is straightforward; at the top of the directory hierarchy run jar like 
  -this:</para>
  -             <literallayout>
  -                     <command>
  -jar cvf interest.jar com/web_tomorrow/interest/Interest.class \
  -com/web_tomorrow/interest/InterestHome.class \
  -com/web_tomorrow/interest/InterestBean.class \
  -META-INF
  -</command>
  -             </literallayout>
  -             <para>If you have `make' on your system, and you have unpacked the 
source code 
  -arhive, you can get the same effect simply by executing `make package'. I 
  -strongly recommend using Makefiles or shell scripts to do these operations 
  -because in practice you will be repeating them many times during development
  -jar builds an archive containing the three classes, and the XML files in the 
  -META-INF directory. If you list the contents of the archive you should see 
  -something like this:</para>
  -             <literallayout>
  -                     <computeroutput>
  -      0  06-16-00  11:34   META-INF/
  -     72  06-16-00  11:35   META-INF/MANIFEST.MF
  -    248  06-16-00  10:12   com/web_tomorrow/interest/Interest.class
  -    300  06-16-00  10:12   com/web_tomorrow/interest/InterestHome.class
  -    877  06-16-00  10:12   com/web_tomorrow/interest/InterestBean.class
  -    549  06-15-00  18:15   META-INF/ejb-jar.xml
  -   3597  06-15-00  17:20   META-INF/jboss.xml
  -</computeroutput>
  -             </literallayout>
  -             <para>Note that the directory structure must be exactly like this, or 
it won't 
  -work. Again a common mistake is to do a META_INF (underscore) or meta-inf 
  -(lower case) instead of 
  -META-INF, be careful with this one.</para>
  -             <para>To deploy the Bean on the server, all that's necessary is to 
copy the 
  -.jar file to the `deploy' directory on the server, e.g., 
  -
  -<command>cp interest.jar /usr/local/jboss/deploy </command>
  -             </para>
  -             <para>You can do this as often as you like; the server will detect 
that the 
  -file has changed and automatically re-deploy it. During deployment you should 
  -see the following messages from the server: </para>
  -             <literallayout>
  -                     <computeroutput>
  -[Auto deploy] Auto deploy of file:/usr/local/jboss/deploy/interest.jar
  -[J2EE Deployer Default] Deploy J2EE application:
  -file:/usr/local/jboss/deploy/interest.jar
  -[J2EE Deployer Default] Create application interest.jar
  -[J2EE Deployer Default] install module interest.jar
  -[Container factory]
  -Deploying:file:/usr/local/jboss/tmp/deploy/Default/interest.jar  
  -[Verifier] Verifying
  -file:/usr/local/jboss/tmp/deploy/Default/interest.jar/ejb1001.jar 
  -[Container factory] Deploying Interest
  -[Container factory] Deployed application:
  -file:/usr/local/jboss/tmp/deploy/Default/interest.jar 
  -[J2EE Deployer Default] J2EE application:
  -file:/usr/local/jboss/deploy/interest.jar is deployed.
  -</computeroutput>
  -             </literallayout>
  -             <para>If you see a message like this: </para>
  -             <literallayout>
  -                     <computeroutput>
  -[Auto deploy] Auto deploy of file:/usr/local/jboss/deploy/interest.jar
  -[J2EE Deployer Default] Deploy J2EE application:
  -file:/usr/local/jboss/deploy/interest.jar 
  -[Auto deploy] Deployment failed:file:/usr/local/jboss/deploy/interest.jar
  -</computeroutput>
  -             </literallayout>
  -             <para>then no Beans have been deployed -- the server always reports 
the Beans 
  -that it detects. This usually means that the deployment descriptor ejb-jar.xml 
  -is badly structured, or missing, or in the wrong directory. Note that the 
  -server doesn't need to have the CLASSPATH set with your classes it is done 
  -automatically from the deploy directory.</para>
  -             <para>If everything has gone according to plan, you should now have a 
Bean 
  -deployed on the server. We will now create a simple test client that runs one 
  -of its methods, just to prove that it's working.</para>
  -     </section>
  -     <section>
  -             <title>Coding and compiling the test client</title>
  -             <para>An EJB on its own is no use; we will need at least a simple 
client to 
  -use its services. A user of EJBs may be another EJB, and ordinary JavaBean, a 
  -JSP page, an applet, or a stand-alone application. In this example, for 
  -simplicity, we will code a simple application. This application will create an 
  -object of class Interest, and execute its one method.</para>
  -             <para>Upon "deployment" of the bean as we have seen in the previous 
step, the 
  -server has generated all the stubs and skeletons needed for the distributed 
  -calls.  What we are going to cover here is the way you lookup a reference in 
  -JNDI from a client and invoke it.  It is pretty straightforward.</para>
  -             <para>Here is the test client:</para>
  -             <figure>
  -                     <title>Test client, file name InterestClient.java</title>
  -                     <programlisting>
  -import javax.naming.*;
  -import com.web_tomorrow.interest.*;
  -import java.util.Hashtable;
  -import javax.rmi.PortableRemoteObject; 
  -import com.web_tomorrow.interest.*; 
  -
  -/**
  -This simple application tests the `Interest' Enterprise JavaBean which is
  -implemented in the package `com.web_tomorrow.interest'. For this to work, the
  -Bean must be deployed on an EJB server.
  -
  -
  -
  -
  -IMPORTANT If you want to test this in a real client-server
  -configuration, this class goes on the client; the URL of the naming provider
  -specifed in the class must be changed from `localhost:1099' to the URL of the
  -naming service on the server
  -*/
  -
  -class InterestClient {
  -  /**
  -  This method does all the work. It creates an instance of the Interest EJB on
  -  the EJB server, and calls its `calculateCompoundInterest()' method, then 
  -prints
  -  the result of the calculation.
  -  */
  -  public static void main(String[] args) {
  -    // Set up the naming provider; this may not always be necessary, depending
  -    // on how your Java system is configured.
  -    System.setProperty("java.naming.factory.initial", 
  -      "org.jnp.interfaces.NamingContextFactory");
  -    System.setProperty("java.naming.provider.url", 
  -      "localhost:1099");
  -
  -    // 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();
  -      System.out.println("Got context");
  -
  -      // Get a reference to the Interest Bean
  -      // This is in the case you use the jboss.xml to override the JNDI name
  -      Object ref  = jndiContext.lookup("interest/Interest");
  -      // If you didn't use the jboss.xml the following will work
  -      // Object ref = jndiContext.lookup("Interest");
  -
  -      System.out.println("Got reference");
  -
  -      // Get a reference from this to the Bean's Home interface
  -      InterestHome home = (InterestHome) 
  -        PortableRemoteObject.narrow (ref, InterestHome.class);
  -
  -      // Create an Interest object from the Home interface
  -      Interest interest = home.create();
  -
  -      // call the calculateCompoundInterest() method to do the calculation
  -      System.out.println 
  -        ("Interest on 1000 units, at 10% per period, compounded over 2 periods 
  -is:");
  -      System.out.println (interest.calculateCompoundInterest (1000, 0.10, 2));
  -    } catch(Exception e) {
  -      System.out.println(e.toString());
  -    }
  -  }
  -}
  -</programlisting>
  -             </figure>
  -             <para>Please note that the client tries to find
  -<quote>interest/Interest</quote> via JNDI. Your bean has been bound to
  -this name if you supplied a proper jboss.xml file. If not, the JNDI
  -name will be just <quote>Interest</quote>. For the later case adjust
  -the code please.</para>
  -             <para>It's important to understand that in reality this client will be 
running 
  -on a different computer to the Bean server. For testing you will probably run 
  -them on the same computer, but it will still be using a network connection. So 
  -the first part of the program indicates how to find the server. </para>
  -             <para>
  -                     
<programlisting>System.setProperty("java.naming.factory.initial", 
  -    "org.jnp.interfaces.NamingContextFactory");
  -  System.setProperty("java.naming.provider.url", 
  -    "localhost:1099"); </programlisting>
  -             </para>
  -             <para>There are several other ways to do this, which you may see 
described in 
  -other sections. In this case, the server is on the same machine as the client 
  -(`localhost') and the default naming port is `1099' for JBoss (other servers 
  -may use different port numbers). If you run the client and the server on 
  -different machines, you will need to change these settings.</para>
  -             <para>The comments in the program should describe how it works; one 
point that 
  -requires mention is that the recommended way to get a reference to the home 
  -interface on the server is like this: </para>
  -             <para>
  -                     <programlisting>InterestHome home = (InterestHome) 
  -        PortableRemoteObject.narrow (ref, InterestHome.class); 
  -</programlisting>
  -
  -which ensures compatibility with different RMI servers (e.g., CORBA). `narrow' 
  -ensures that the object returned in `ref' really can be converted to an object 
  -of class `InterestHome'.</para>
  -             <para>The test client doesn't need to be in the same package as the 
EJB 
  -classes, and in practice it probably won't be. So it needs to import the EJB 
  -classes using their fully-qualified class name, like this: </para>
  -             <para>
  -                     <classname>import com.web_tomorrow.interest.*; </classname>
  -             </para>
  -             <para>You will also need to pay attention to the CLASSPATH when 
compiling. 
  -Even though the EJB classes will run on the server, they need to be identified 
  -to the client so that the compiler can do the appropriate type checking. In 
  -the example program I have put the client at the top level of the directory 
  -hierachy, so if the CLASSPATH includes the current directory it will correctly 
  -find the EJB classes which are in the directories beneath it. </para>
  -             <para>
  -                     <command>javac -classpath
  -/usr/local/jboss/client/ejb.jar:. InterestClient.java</command>
  -             </para>
  -             <para>This generates InterestClient.class in the current directory. 
</para>
  -     </section>
  -     <section>
  -             <title>Running the test client</title>
  -             <para>We're now ready to run the test client, but first a word of 
  -explanation.</para>
  -             <para>In reality the client and the server are likely to be on 
different 
  -computers. When you compile the client, the compiler needs to know about the 
  -organization and methods of classes in the Bean so it can do type checking. 
  -When you run the client, the run-time engine needs to know about the Bean 
  -classes, because type-casting is done at run-time. So when the client attempts 
  -to cast the remote reference to a reference to an object of class InterestHome 
  -for example, it needs to know about this class. This means that you will need 
  -the Bean class files on both the client and the server even though they 
  -execute on the server. This is fairly obvious if you think about the logic, 
  -but it causes all sorts of problems for people who are new to RMI programming. 
  -If the client can't find the Bean classes, you will get error messages like 
  -this:</para>
  -             <literallayout>
  -                     <computeroutput>javax.naming.CommunicationException [Root 
exception is 
  -java.lang.ClassNotFoundException: com.web_tomorrow.interest.InterestHome]
  -</computeroutput>
  -             </literallayout>
  -             <para>A 'communication exception' is the exception that represents any 
error 
  -that can't readily be ascribed to a definite cause. If you get this message 
  -you need to pay attention to the CLASSPATH on the client. NOTE that the server 
  -doesn't need to have the classpath set, you just need to put it in the deploy 
  -directory and the server will generate a ClassLoader for it.</para>
  -             <para>If the client program is at the top of the directory hierarchy, 
with the 
  -Bean classes below it, then we can run it like this:</para>
  -             <literallayout><command>
  -java -classpath 
/usr/local/jboss/client/jboss-client.jar:/usr/local/jboss/client/jbosssx-client.jar:/usr/local/jboss/client/jnp-client.jar:.
 InterestClient</command>
  -             </literallayout>
  -             <para>Once again, this needs to go in a shell script or a Makefile; 
you won't 
  -want to type it more than once.</para>
  -             <para>Note the long CLASSPATH; it needs to include various JBoss 
client classes. These classes implement the EJB interfaces with container provider 
specific code, here JBoss. This is why we now no longer need to include the ejb.jar.
  -If all is well, the test client produces the following output: </para>
  -             <literallayout>
  -                     <computeroutput>
  -Got context
  -Got reference
  -Interest on 1000 units, at 10% per period, compounded over 2 periods is:
  -210.00000000000023
  -</computeroutput>
  -             </literallayout>
  -             <para>If it doesn't produce this output but you see a 
"MalformedURLException" 
  -try installing jboss in another directory that doesn't contain space in it's 
  -path (typically some installations on windows don't like C:\Program Files (the 
  -space).</para>
  -             <para>Another common problem you can see here is a "class not found 
exception" 
  -make sure you include all the jars needed.</para>
  -             <para>The Bean should produce an output on the server as well; this is 
to show 
  -that the Bean has executed on the server, not the client. Look for something 
  -like this in the server log: </para>
  -             <para>
  -                     <computeroutput>
  -[Interest] Someone called `calculateCompoundInterest!'
  -</computeroutput>
  -             </para>
  -             <para>Well, that's it. We covered coding, compiling and deploying the 
Bean, 
  -and coding and running a simple test client. If you found this article useful, 
  -drop me a line at [EMAIL PROTECTED]; if there's enough response I may 
  -be persuaded to produce some more sophisticated tutorials.</para>
  -     </section>
  -</chapter>
  +<?xml version = "1.0" encoding = "UTF-8"?>
  +
  +<chapter>
  +     <title>First steps</title>
  +     <para>Authors:<author>
  +                     <firstname>Kevin</firstname>
  +                     <surname>Boone</surname>
  +             </author>
  +             <email>[EMAIL PROTECTED]</email>
  +     </para>
  +     <para>
  +             <author>
  +                     <firstname>Tobias</firstname>
  +                     <surname>Frech</surname>
  +             </author>
  +     </para>
  +     <para>
  +             <author>
  +                     <firstname>Scott</firstname>
  +                     <surname>Stark</surname>
  +             </author>
  +             <email>[EMAIL PROTECTED]</email>
  +     </para>
  +     <section>
  +             <title>Introduction</title>
  +             <section>
  +                     <title>What this section is about</title>
  +                     <para>This section presents a step-by-step tutorial on how to 
set up 'JBoss', the free Enterprise JavaBean (EJB) server, and create your first
  +Enterprise JavaBean and client. It doesn't explain what Enterprise JavaBeans 
  +are, or how they are used; there are a number of good
  +introductory articles on Sun's JavaSoft Web site. Although the description is 
  +based on the use of a Linux server, most of the issues discussed in
  +this article will also apply to other platforms. If you are using a Windows 
  +platform you will need to pay attention to the directory names, which
  +will be different from the one's I've assumed. </para>
  +             </section>
  +             <section>
  +                     <title>About JBoss</title>
  +                     <para>JBoss is an implementation of the EJB 1.1 (and parts of 
2.0)
  +specification, that is, it is a  
  +server and container for Enterprise JavaBeans. In this it is similar to Sun's
  +'J2SDK Enterprise Edition' (J2EE), but JBoss is much more single-minded than 
  +J2EE. The JBoss core server provides only an EJB server; it does not include
  +support for JSP, SSL, and all the other protocols that the Sun product can 
  +handle. This means that it is smaller in memory and in disk space.
  +JBoss will run very effectively on a machine with 64 megabytes of RAM, and 
  +requires only a few megabytes of disk (including source code!). Sun's
  +J2EE requires a minimum of 128 megabytes of RAM, and 31 megabytes of disk 
  +space. That's not to criticise the Sun product; it is a
  +heavyweight offering providing a host of services. Because of its small memory 
  +footprint, JBoss starts up about 10 times faster than J2EE.
  +
  +There is a built-in SQL database server for handling persistent beans, and 
  +this starts up automatically with the server (J2EE ships with the
  +CloudScape SQL server, which has to be started separately). </para>
  +                     <para>One of the nicest features of JBoss is its support for 
`hot' 
  +deployment. What this means is that deploying a Bean is a simple as copying its
  +JAR file into the deployment directory. If this is done while the Bean is 
  +already loaded, JBoss automatically unloads it, then loads the new
  +version. Contrast this with the rigmarole that other J2EE server makes us go 
through... 
  +JBoss is distributed under the LGPL, which means that it's free, even for commercial
  +work, and is likely to remain that way. You get no support, of course. </para>
  +                     <para>This article helps get you started using JBoss 
  +by describing step-by-step how a simple EJB can be created, deployed and
  +tested on the JBoss server. </para>
  +             </section>
  +             <section>
  +                     <title>Pre-requisites</title>
  +                     <para>JBoss is written entirely in Java, and requires a Java 
system compatible with JDK 1.3. This is essential, not optional. Trust me on this; 
I've tried
  +it with JDK 1.2.2 and the `hot' deployment facility simply doesn't work. Since 
  +it is now possible to get Linux JDKs directly from Sun, there's
  +little reason not to upgrade if you're using an earlier version. </para>
  +                     <para>It is assumed that you are basically familiar with EJBs 
(and roughly know, for example, what a 'home interface' is) and know how to compile 
Java
  +classes. </para>
  +             </section>
  +     </section>
  +     <section>
  +             <title>Installing JBoss</title>
  +             <para>Before installing and running the server, you should check that 
your JDK 
  +installation is working. You will need the JDK binaries directory in your PATH 
(this is essential: see below) not just for the user account which is doing the 
installation,
  +but also for the user account that will run the server. If you are running the 
server
  +as root, you should check that the JDK binaries are in the PATH even for root
  +(root and ordinary users normally have different PATH settings). You won't 
  +need to specify a CLASSPATH environment variable if you don't normally have 
  +to.</para>
  +             <para>The next step will be to download, install and test the JBoss 
server. At 
  +the time of writing the most recent version of JBoss is 2.2.1.
  +It doesn't matter where you install JBoss. There is no requirement for root access 
to
  +run JBoss as none of the default ports are below the 1024 privaledged port range.
  +This tutorial refers to the JBoss installation directory as JBOSS_DIST.
  +When you see JBOSS_DIST substitute the path for your installation as 
appropriate.</para>
  +             <para>JBoss is distributed as a ZIP file. You can download the binary
  +distribution which contains the latest offical release (which was 2.2.1
  +at the time of writing) or a source snapshot with the latest
  +version from CVS. This documentation mainly is written
  +for the 2.2.1 version.</para>
  +             <section>
  +                     <title>Installation of binary package</title>
  +                     <para>Download the binary package from <ulink url = 
"http://sourceforge.net/projects/jboss/"> 
http://sourceforge.net/projects/jboss/</ulink> under the Latest File Releases section. 
Place it in a temporary directory and use your favorite unziper to decompress it to 
the place where you want JBoss
  +installed. The toplevel JBoss directory of the unzipped binary will be referred to 
as the JBOSS_DIST directory.</para>
  +                     <para>Make sure, that this user has the JDK binaries in his 
command path and that he has write access to the
  +JBoss directory (needed for log files and deployment).
  +You are now ready to change to the bin directory, and  run the JBoss server: </para>
  +                     <literallayout>
  +On Unix/Linux:
  +<command>
  +cd JBOSS_DIST/bin
  +/bin/sh run.sh
  +</command>
  +On Win32:
  +<command>
  +cd JBOSS_DIST\bin
  +run.bat
  +</command>
  +                     </literallayout>
  +                     <para>A proper installation should start without any error 
messages or exceptions being thrown. It will
  +produce several pages of output on startup. The console output should look 
something like the following
  +at the start and end for JBoss2.2.1 on Linux:
  +<literallayout>
  +<computeroutput>bash-2.04$ /bin/sh run.sh
  +JBOSS_CLASSPATH=:run.jar:../lib/crimson.jar
  +jboss.home = /tmp/JBoss-2.2.1
  +Using configuration "default"
  +[Info] Java version: 1.3.0_02,Sun Microsystems Inc.
  +[Info] Java VM: Java HotSpot(TM) Server VM 1.3.0_02,Sun Microsystems Inc.
  +[Info] System: Linux 2.2.16-22,i386
  +[Shutdown] Shutdown hook added
  +[Service Control] Registered with server
  +[Service Control] Initializing 24 MBeans
  +...
  +[Service Control] Started 24 services
  +[Default] JBoss 2.2.1 Started in 0m:8s</computeroutput>
  +</literallayout>
  +                     </para>
  +             </section>
  +     </section>
  +     <section>
  +             <title>Creating the Bean</title>
  +             <para>In this step we will write and compile a simple Enterprise 
JavaBean.
  +You can download the source code for this example in either zip(interestEJB.zip) or
  +tar/gzip( interestEJB.tar.gz) format from the file section of the documentation 
section
  +on <ulink url="http://www.jboss.org/documentation/files/">www.jboss.org<ulink>.
  +You will need to unpack the archive into an empty directory.</para>
  +             <para>The example, which is called 'Interest', is a simple stateless 
session EJB.
  +Its job is to calculate the amount of compound interest payable on a sum
  +of money borrowed over a specified term with a specified interest rate.
  +In fact, there is only one functional line of code in the whole package.</para>
  +             <para>If you want to compile the classes yourself, you'll need to 
create a 
  +directory hierarchy that reflects the structure of the pacakage. The package 
  +in this example is com.web_tomorrow.interest so you'll need to create the 
  +directory structure: <literallayout>
  +com
  +  web_tomorrow
  +      interest
  +          {java source and class files here}
  +</literallayout>
  +If you unpack the interestEJB-archive it will create a subdirectory called 
"interest" and the needed structure automatically below it.</para>
  +     </section>
  +     <section>
  +             <title>EJBs: review</title>
  +             <para> As a reminder, and Enterprise JavaBean has a minimum of three 
  +classes, the remote interface, the home interface, and the bean implementation.
  +The remote interface is the class that exposes the methods of 
  +the EJB to the outside world. In the example, the remote interface is the 
  +class com.web_tomorrow.interest.Interest. 
  +The home interface specifies how to create a bean that implements the remote 
interface.
  +In this example, the home interface is com.web_tomorrow.InterestHome.
  +The bean implementation provides an
  +implementation of the methods specified by the remote and home interfaces. In this
  +example, the Bean class is com.web_tomorrow.interest.InterestBean.</para>
  +             <para> Of course, a Bean can include other classes, or even other 
packages, 
  +but the classes listed above are the minimum. The classes must be packaged 
  +into a JAR archive with a directory structure that reflects the hierarchy of 
  +packages. In the example, the classes are in the package 
  +com.web_tomorrow.interest, so they need to be in the directory 
com/web_tomorrow/interest/</para>
  +             <para>You will also need a directory called META-INF to store the 
deployment 
  +descriptor (always called ejb-jar.xml) and -- optionally -- another XML file 
  +to tell the server about name mappings. With JBoss, this file must be called 
  +jboss.xml.</para>
  +             <para>So before writing the classes, we need a directory structure 
like this: <literallayout>com
  +  web_tomorrow
  +    interest
  +      {java source and class files here}
  +META-INF
  +  ejb-jar.xml
  +  joss.xml (optional)</literallayout>
  +             </para>
  +             <para>If the jar utility is run in the parent of this directory 
structure, it will create an archive
  +with the proper structure. We will discuss the creation of the XML files 
later.</para>
  +     </section>
  +     <section>
  +             <title>Coding the classes</title>
  +             <para>We need three classes: the remote interface, the home interface, 
and the bean implementation.
  +All the .java files will go in the subdirectory ./com/web_tomorrow/interest.
  +The remote interface in this example is very simple.</para>
  +             <figure>
  +                     <title>Remote interface for the interest EJB, file name 
Interest.java</title>
  +                     <programlisting>package com.web_tomorrow.interest;
  +
  +import javax.ejb.EJBObject;
  +import java.rmi.RemoteException;
  +
  +/**
  +This interface defines the `Remote' interface for the `Interest' EJB. Its
  +single method is the only method exposed to the outside world. The class
  +InterestBean implements the method.
  +*/
  +public interface Interest extends EJBObject 
  +{
  +  /** Calulates the compound interest on the sum `principle', with interest rate per
  +  period `rate' over `periods' time periods. This method also prints a message to
  +  standard output; this is picked up by the EJB server and logged. In this way we
  +  can demonstrate that the method is actually being executed on the server,
  +  rather than the client.
  +  */
  +  public double calculateCompoundInterest(double principle, 
  +    double rate, double periods) throws RemoteException;
  +}</programlisting>
  +             </figure>
  +             <para> The remote interface specifies only one `business method' 
  +calculateCompoundInterest.   The home interface is even simpler. </para>
  +             <figure>
  +                     <title>Home  interface for the interest EJB, file name 
InterestHome.java</title>
  +                     <programlisting>package com.web_tomorrow.interest;
  +
  +import java.rmi.RemoteException;
  +import javax.ejb.CreateException;
  +import javax.ejb.EJBHome;
  +
  +/** This interface defines the `home' interface for the `Interest' EJB. 
  +*/
  +public interface InterestHome extends EJBHome
  +{
  +  /**  Creates an instance of the `InterestBean' class on the server, and returns a
  +  remote reference to an Interest interface on the client. 
  +  */
  +  Interest create()
  +    throws RemoteException, CreateException;
  +}</programlisting>
  +             </figure>
  +             <para>Finally, here is the bean implementation class.</para>
  +             <figure>
  +                     <title>Implementation class for the interest EJB, file name 
InterestBean.java</title>
  +                     <programlisting>package com.web_tomorrow.interest;
  +
  +import java.rmi.RemoteException; 
  +import javax.ejb.SessionBean;
  +import javax.ejb.SessionContext;
  +
  +/** This class contains the implementation for the `calculateCompoundInterest'
  +method exposed by this Bean. It includes empty method bodies for the methods
  +prescribe by the SessionBean interface; these don't need to do anything in this
  +simple example.
  +*/
  +
  +public class InterestBean implements SessionBean
  +{
  +  /** Calulates the compound interest on the sum `principle', with interest rate   
  +  per period `rate' over `periods' time periods. This method also prints a          
 
  +  message to standard output; this is picked up by the EJB server and logged.  
  +  In this way we can demonstrate that the method is actually being executed on 
  +  the server, rather than the client.
  +  */
  +  public double calculateCompoundInterest(double principle, 
  +    double rate, double periods)
  +  {
  +    System.out.println ("Someone called `calculateCompoundInterest!'");
  +    return principle * Math.pow(1+rate, periods) - principle;
  +  }
  +
  +  public InterestBean() {}
  +  public void ejbCreate() {}
  +  public void ejbRemove() {}
  +  public void ejbActivate() {}
  +  public void ejbPassivate() {}
  +  public void setSessionContext(SessionContext sc) {}
  +
  +}  </programlisting>
  +             </figure>
  +             <para>Notice that most of the methods are empty; they have to exist 
because 
  +they're specified by the SessionBean interface, but they not needed for
  +this simple example EJB.</para>
  +             <para>If you haven't already done so, you should create these .java 
files in 
  +the directory com/web_tomorrow/interest (or unpack the archive). You can then
  +compile them using the command <command>javac -classpath JBOSS_DIST/client/ejb.jar 
com/web_tomorrow/interest/*.java</command>
  +             </para>
  +             <para>Substituting the actual value for JBOSS_DIST for your 
installation. Also remember to start
  +compilation from your source root directory, which is the parent directory of the
  +com/web_tomorrow/interest/ structure.
  +
  +The compilation will create three class files: 
  +InterestBean.class, Interest.class, and InterestHome.class.
  +With the classes compiled, it's time to create the ejb-jar.xml deployment 
descriptor.</para>
  +     </section>
  +     <section>
  +             <title>The deployment descriptor</title>
  +             <para>Now it's time to create the deployment descriptor. As a 
reminder, this 
  +file tells the EJB server which classes make up the bean implementation, the home 
interface and 
  +the remote interface. If there is more than one EJB in the package, it 
  +indicates also how the EJBs interact with one another. In this simple 
  +example, there is only one EJB so we won't need to worry about that 
  +part.</para>
  +             <para>Most commercial EJB servers are supplied with graphical tools 
for 
  +constructing the deployment descriptor. JBoss does have an XML editor, but 
  +it's just as easy to construct the deployment descriptor manually. Here it 
  +is:</para>
  +             <figure>
  +                     <title>Deployment descriptor for the Interest Bean</title>
  +                     <literallayout><![CDATA[
  +<?xml version="1.0" encoding="UTF-8"?>
  +
  +<ejb-jar>
  +     <description>JBoss test application</description>
  +     <display-name>Test</display-name>
  +     <enterprise-beans>
  +       <session>
  +         <ejb-name>Interest</ejb-name>
  +         <home>com.web_tomorrow.interest.InterestHome</home>
  +         <remote>com.web_tomorrow.interest.Interest</remote>
  +         <ejb-class>com.web_tomorrow.interest.InterestBean</ejb-class>
  +         <session-type>Stateless</session-type>
  +         <transaction-type>Bean</transaction-type>
  +       </session>
  +     </enterprise-beans>
  +</ejb-jar>
  +]]></literallayout>
  +             </figure>
  +             <para>The deployment descriptor must be called ejb-jar.xml and it must 
be in 
  +the directory ./META-INF. A common mistake is to name this directory 
  +`META_INF' (with an underscore, rather than a dash) or meta-inf 
  +which won't work.</para>
  +             <para>In principle what we deploy on the server is an application, not 
a 
  +single EJB. In this example our application consists of only one EJB. In the 
deployment
  +descriptor, the section <![CDATA[<ejb-name>Interest</ejb-name> assigns a name to the
  +EJB. JBoss by default will put the bean's home interface under the ejb-name 
  +moniker in the JNDI namespace if you don't override this default behavior.]]></para>
  +             <para>In practice client applications are not forced to use this name. 
  +Typically a developer will not bother with specifying a different name for the 
  +JNDI namespace. However a production installation of a complete application 
  +comprising many beans, will usually use a different name rather than the one 
  +specified by the developer. Typically this would be something like "[application 
name]/[bean 
  +name]", which is what we shall use later.</para>
  +             <para>Although the deployment descriptor format of the ejb-jar.xml 
file is 
  +common to all EJB servers, and precisely defined by a DTD you can get from 
  +Sun, it doesn't specify everything necessary for a particular EJB server.
  +Specifically it does not indicate how to map ejb-name to a deployment JNDI name
  +such as "[application name]/[bean name]".</para>
  +             <para>The approach taken by JBoss is to provide a default behaviour 
that 
  +works from the ejb-jar.xml file in most cases. In case of advanced configurations
  +you need to define JBoss specific behavior using a jboss.xml deployment descriptor.
  +Refer to the advanced configuration section for the complete details of jboss.xml
  +descriptor. The only item we will configure via the jboss.xml descriptor is the JNDI
  +name used to access the Interest EJB home interface.</para>
  +             <para>By default the JNDI name used to access an EJB's home interface 
is
  +the same as the ejb-name value from ejb-jar.xml. For this example that
  +means that the Interest bean would be located under the JNDI InitialContext
  +as "Interest". We want to have the home interface available using 
"interest/Interest"
  +so we need to specifiy this using the jboss.xml descriptor.</para>
  +             <section>
  +                     <title>Overriding ejb-name with a real JNDI name in 
jboss.xml</title>
  +                     <para>To override the default behavior of using the 
ejb-jar.xml ejb-name element
  +value as the JNDI name of a bean's home interface, you need to specify
  +what JNDI name should be used using a jboss.xml descriptor like the 
following:</para>
  +                     <figure>
  +                             <title>The JBoss XML descriptor.</title>
  +                             <literallayout><![CDATA[
  +<?xml version="1.0" encoding="UTF-8"?>
  +<jboss>
  +  <enterprise-beans>
  +    <session>
  +      <ejb-name>Interest</ejb-name>
  +      <jndi-name>interest/Interest</jndi-name>
  +    </session>
  +  </enterprise-beans>
  +</jboss>
  +]]></literallayout>
  +                     </figure>
  +                     <para>All this file says is that the Bean called Interest is 
assigned the JNDI 
  +name of interest/Interest.</para>
  +                     <para>So now we've created the standard ejb-jar.xml deployment 
descriptor as well as
  +the JBoss specific jboss.xml to set the JNDI name of the Interest EJB home
  +interface to "interest/Interest". We also have the EJB classes and so we have
  +all that we need to create the EJB jar package.</para>
  +             </section>
  +     </section>
  +     <section>
  +             <title>Packaging and deploying the bean</title>
  +             <para>Creation of the EJB jar package involves building a JAR archive 
containing 
  +the classes and the deployment descriptors. To build the EJB jar for the
  +Interest example simply run the jar command from the top of the directory
  +hierarchy:</para>
  +             <literallayout>
  +                     <computeroutput>jar cvf interest.jar 
com/web_tomorrow/interest/*.class META-INF
  +added manifest
  +adding: com/web_tomorrow/interest/Interest.class(in = 248) (out= 196)(deflated 20%)
  +adding: com/web_tomorrow/interest/InterestBean.class(in = 877) (out= 477)(deflated 
45%)
  +adding: com/web_tomorrow/interest/InterestHome.class(in = 300) (out= 204)(deflated 
32%)
  +ignoring entry META-INF/
  +adding: META-INF/ejb-jar.xml(in = 551) (out= 242)(deflated 56%)
  +adding: META-INF/jboss.xml(in = 226) (out= 130)(deflated 42%)</computeroutput>
  +                     <computeroutput>jar -tvf interest.jar
  +     0 Thu Apr 19 19:56:18 PDT 2001 META-INF/
  +    71 Thu Apr 19 19:56:18 PDT 2001 META-INF/MANIFEST.MF
  +   248 Thu Apr 19 19:20:54 PDT 2001 com/web_tomorrow/interest/Interest.class
  +   877 Thu Apr 19 19:20:54 PDT 2001 com/web_tomorrow/interest/InterestBean.class
  +
  +   300 Thu Apr 19 19:20:54 PDT 2001 com/web_tomorrow/interest/InterestHome.class
  +
  +   551 Thu Apr 19 18:48:32 PDT 2001 META-INF/ejb-jar.xml
  +   226 Thu Apr 19 19:54:04 PDT 2001 META-INF/jboss.xml</computeroutput>
  +             </literallayout>
  +             <para>To deploy the Bean on the server, all that's necessary is to 
copy the 
  +interest.jar file to the JBOSS_DIST/deploy directory of your JBoss installation.
  +You can do this as often as you like. The server will detect that the 
  +file has changed and automatically re-deploy it. During deployment you should 
  +see messages similar to the following on the server console:</para>
  +             <literallayout>
  +                     <computeroutput>[Auto deploy] Auto deploy of 
file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/deploy/interest.jar
  +[J2EE Deployer Default] Deploy J2EE application: 
file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/deploy/interest.jar
  +[J2EE Deployer Default] Create application interest.jar
  +[J2EE Deployer Default] install module interest.jar
  +[Container factory] 
Deploying:file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/tmp/deploy/Default/interest.jar
  +[Verifier] Verifying 
file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/tmp/deploy/Default/interest.jar/ejb1001.jar
  +[Container factory] Deploying Interest
  +[Container factory] Deployed application: 
file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/tmp/deploy/Default/interest.jar
  +[J2EE Deployer Default] J2EE application: 
file:/D:/usr/local/src/cvsroot/JBoss2.2/jboss/dist/deploy/interest.jar is 
deployed.</computeroutput>
  +             </literallayout>
  +             <para>If you see a message like this: </para>
  +             <literallayout>
  +                     <computeroutput>[Auto deploy] Auto deploy of 
file:/usr/local/jboss/deploy/interest.jar
  +
  +[J2EE Deployer Default] Deploy J2EE application:
  +
  +file:/usr/local/jboss/deploy/interest.jar 
  +
  +[Auto deploy] Deployment 
failed:file:/usr/local/jboss/deploy/interest.jar</computeroutput>
  +             </literallayout>
  +             <para>then no EJBs have been deployed -- the server always reports the 
EJBs
  +that it detects. This usually means that the deployment descriptor ejb-jar.xml 
  +is badly structured, or missing, or in the wrong directory. </para>
  +             <para>You should now have the Interest EJB deployed on the server. We 
will now create a simple
  +test client that runs one of its methods, just to verify that it's working.</para>
  +     </section>
  +     <section>
  +             <title>Coding and compiling the test client</title>
  +             <para>An EJB on its own is no use; we will need at least a simple 
client to 
  +use its services. A user of EJBs may be another EJB, an ordinary JavaBean, a 
  +JSP page, an applet, or a stand-alone application. In this example, for 
  +simplicity, we will code a simple application. This application will create an 
  +object of class Interest, and execute its one method.</para>
  +             <para>Upon deployment of the bean as we have seen in the previous 
step, the 
  +server has generated all the stubs and skeletons needed for the distributed 
  +calls.  What we are going to cover here is the way you lookup a reference in 
  +JNDI from a client and invoke it.  It is pretty straightforward.</para>
  +             <para>Here is the test client:</para>
  +             <figure>
  +                     <title>Test client, file name InterestClient.java</title>
  +                     <programlisting>import java.util.Properties;
  +import javax.rmi.PortableRemoteObject; 
  +import javax.naming.*;
  +
  +import com.web_tomorrow.interest.Interest;
  +import com.web_tomorrow.interest.InterestHome;
  +
  +/** This simple application tests the 'Interest' Enterprise JavaBean which is
  +implemented in the package 'com.web_tomorrow.interest'. For this to work, the
  +Bean must be deployed on an EJB server.
  +
  +IMPORTANT: If you want to test this in a real client-server
  +configuration, this class goes on the client; the URL of the naming provider
  +specifed in the class must be changed from 'localhost:1099' to the URL of the
  +naming service on the server
  +*/
  +class InterestClient
  +{
  +   /** This method does all the work. It creates an instance of the Interest EJB on
  +   the EJB server, and calls its `calculateCompoundInterest()' method, then prints
  +   the result of the calculation.
  +   */
  +   public static void main(String[] args)
  +   {
  +      // Set up the naming provider; this may not always be necessary, depending
  +      // on how your Java system is configured.
  +      Hashtable env = new Hashtable();
  +      env.setProperty("java.naming.factory.initial",  
"org.jnp.interfaces.NamingContextFactory");
  +      env.setProperty("java.naming.provider.url",  "localhost:1099");
  +      env.setProperty("java.naming.factory.url.pkgs",  "org.jboss.naming");
  +
  +      // 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(env);
  +         System.out.println("Got context");
  +
  +         // Get a reference to the Interest Bean
  +         Object ref  = jndiContext.lookup("interest/Interest");
  +         System.out.println("Got reference");
  +
  +         // Get a reference from this to the Bean's Home interface
  +         InterestHome home = (InterestHome) 
  +            PortableRemoteObject.narrow (ref, InterestHome.class);
  +
  +         // Create an Interest object from the Home interface
  +         Interest interest = home.create();
  +
  +         // call the calculateCompoundInterest() method to do the calculation
  +         System.out.println("Interest on 1000 units, at 10% per period, compounded 
over 2 periods is:");
  +         System.out.println(interest.calculateCompoundInterest (1000, 0.10, 2));
  +      }
  +      catch(Exception e)
  +      {
  +         System.out.println(e.toString());
  +      }
  +   }
  +}</programlisting>
  +             </figure>
  +             <para>Please note that the client lookup up the InterestHome interface 
under the JNDI name "interest/Interest".
  +Your bean's home interface has been bound to this name if you supplied a proper 
jboss.xml file. If not,
  +the JNDI name will be "Interest".</para>
  +             <para>It's important to understand that in reality this client may be 
running 
  +on a different computer than the JBoss server. For testing you will probably run 
  +them on the same computer, but it will still be using a network connection. So 
  +the first part of the program indicates how to find the JBoss server JNDI 
namespace.</para>
  +             <para>
  +                     <programlisting>      Properties env = new Properties();
  +      env.setProperty("java.naming.factory.initial",  
"org.jnp.interfaces.NamingContextFactory");
  +      env.setProperty("java.naming.provider.url",  "localhost:1099");
  +      env.setProperty("java.naming.factory.url.pkgs",  
"org.jboss.naming");</programlisting>
  +             </para>
  +             <para>There are several other ways to do this, which you may see 
described in 
  +other sections. In this case, the server is on the same machine as the client 
  +('localhost') and the default naming port is '1099' for JBoss (other servers 
  +may use different port numbers). If you run the client and the server on 
  +different machines, you will need to change these settings.</para>
  +             <para>The comments in the program should describe how it works; one 
point that 
  +requires mention is that the recommended way to get a reference to the home 
  +interface on the server is like this: </para>
  +             <para>
  +                     <programlisting>    InterestHome home = (InterestHome) 
  +    PortableRemoteObject.narrow (ref, InterestHome.class);</programlisting>which 
ensures compatibility with different RMI protocols (e.g., RMI/IIOP). The 'narrow' 
  +method ensures that the 'ref' object can be converted to an object 
  +of class 'InterestHome'.</para>
  +             <para>The test client doesn't need to be in the same package as the 
EJB 
  +classes, and in practice it probably won't be. So it needs to import the EJB 
  +classes using their fully-qualified class name as illustrated.</para>
  +             <para>To compile the InterestClient you need the InterestClient.java 
source, the EJB
  +classes and the Interest EJB interface classes. If you have downloaded the
  +interestEJB example code then you can compile the InterestClient using
  +the following after suitable substitution for JBOSS_DIST:</para>
  +             <para>
  +                     <command>javac -classpath ".:JBOSS_DIST/client/ejb.jar"  
InterestClient.java</command>
  +             </para>
  +             <para>This generates InterestClient.class in the current directory. 
</para>
  +     </section>
  +     <section>
  +             <title>Running the test client</title>
  +             <para>In reality the client and the server are likely to be on 
different 
  +computers. When you compile the client, the compiler needs to know about the 
  +organization and methods of Interest EJB interfaces so it can do type checking. 
  +When you run the client, the run-time engine needs to know about the Interest
  +and InterestHome classes, because type-casting is done at run-time. So when
  +the client attempts to cast the remote reference to a reference to an object of 
class InterestHome 
  +for example, it needs to know about this class. This means that you will need 
  +the Interest and InterestHome class files on both the client and the server even 
though they 
  +execute on the server. This is fairly obvious if you think about the logic, 
  +but it causes all sorts of problems for people who are new to RMI programming. 
  +If the client can't find the bean interface classes, you will get error messages 
like 
  +this:</para>
  +             <literallayout>
  +                     <computeroutput>javax.naming.CommunicationException [Root 
exception is 
  +java.lang.ClassNotFoundException: 
com.web_tomorrow.interest.InterestHome]</computeroutput>
  +             </literallayout>
  +             <para>A 'communication exception' is the exception that represents any 
error 
  +that can't readily be ascribed to a definite cause. If you get this message 
  +you need to pay attention to the CLASSPATH on the client. NOTE that the server 
  +doesn't need to have the classpath set, you just need to put it in the deploy 
  +directory and the server will generate a ClassLoader for it.</para>
  +             <para>The client program can be run from the directory in which it was 
compiled using
  +the following command with the approriate substitution for JBOSS_DIST:</para>
  +             <literallayout>
  +                     <command>java -classpath 
"JBOSS_DIST/client/jboss-client.jar:JBOSS_DIST/client/jbosssx-client.jar:JBOSS_DIST/client/jnp-client.jar:."
 InterestClient
  +Got context
  +Got reference
  +Interest on 1000 units, at 10% per period, compounded over 2 periods is:
  +210.00000000000023</command>
  +             </literallayout>
  +             <para>Note the CLASSPATH needs to include various JBoss client 
classes. These jars contain the standard EJB and
  +JNDI interfaces as well as the JBoss specific container code. The output is what 
you should see if all goes well.</para>
  +             <para>There should be output from the Interest EJB on the server 
console as well. This is generated
  +to show that the bean has executed on the server, not the client. Look for 
something 
  +like this in the server log or console:</para>
  +             <para>
  +                     <computeroutput>[Interest] Someone called 
`calculateCompoundInterest!'</computeroutput>
  +             </para>
  +             <para>Well, that's it. We covered coding, compiling and deploying an 
EJB, 
  +and coding and running a simple test client. If you found this article useful, 
  +drop me a line at [EMAIL PROTECTED]; if there's enough response I may 
  +be persuaded to produce some more sophisticated tutorials.</para>
  +     </section>
  +</chapter>
  \ No newline at end of file
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to