User: tobias  
  Date: 01/02/10 16:04:54

  Added:       src/docs jboss.xsl jbossapi.xml jbossdocs.xml jbossintro.xml
                        styles.css
  Log:
  initial checkin, good HTML and basic pdf support
  
  Revision  Changes    Path
  1.1                  manual/src/docs/jboss.xsl
  
  Index: jboss.xsl
  ===================================================================
  <?xml version="1.0"?>
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                  xmlns:saxon="http://icl.com/saxon"
                  xmlns:lxslt="http://xml.apache.org/xslt"
                  xmlns:xalanredirect="org.apache.xalan.xslt.extensions.Redirect"
                  xmlns:doc="http://nwalsh.com/xsl/documentation/1.0"
                   version="1.0"
                  exclude-result-prefixes="doc"
                  extension-element-prefixes="saxon xalanredirect lxslt">
        <xsl:import href="docbook/html/chunk.xsl"/>
        <xsl:param name="html.stylesheet">styles.css</xsl:param>
        <xsl:param name="toc.section.depth">0</xsl:param>
        <xsl:param name="chapter.autolabel" select="0"/>
        
        <xsl:template name="header.navigation">
                <xsl:param name="prev" select="/foo"/>
                <xsl:param name="next" select="/foo"/>
                <xsl:variable name="home" select="/*[1]"/>
                <xsl:variable name="up" select="parent::*"/>
                <xsl:if test="$suppress.navigation = '0'">
                                                        <table border="0" 
cellpadding="0" cellspacing="0" height="65">
                                        <tr height="65">
                                                <td rowspan="2">
                                                        <img src="images/jboss.gif" 
width="432" height="79"/>
                                                </td>
                                                <td rowspan="2" 
background="images/gbar.gif" width="100%" align="right" 
  valign="top">
                                                        <a>
                                                                                
<xsl:attribute name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$home"/></xsl:call-template></xsl:attribute>
                                                                                <img 
src="images/doc.gif" width="63" height="65" border="0"/>
                                                                        </a>
                                                        <xsl:choose>
                                                                <xsl:when 
test="count($up)>0">
                                                                        <a>
                                                                                
<xsl:attribute name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$up"/></xsl:call-template></xsl:attribute>
                                                                                <img 
src="images/toc.gif" width="60" height="65" border="0"/>
                                                                        </a>
                                                                </xsl:when>
                                                                
<xsl:otherwise>&#160;</xsl:otherwise>
                                                        </xsl:choose>
  
                                                        <xsl:if test="count($prev)>0">
                                                                <a>
                                                                        <xsl:attribute 
name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$prev"/></xsl:call-template></xsl:attribute>
                                                                        <img 
src="images/prev.gif" width="76" height="65" border="0"/>
                                                                </a>
                                                        </xsl:if>                      
                                 
                                                        <xsl:if test="count($next)>0">
                                                                <a>
                                                                        <xsl:attribute 
name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$next"/></xsl:call-template></xsl:attribute>
                                                                        <img 
src="images/next.gif" width="60" height="65" border="0"/>
                                                                </a>
                                                        </xsl:if>
                                                </td>
                                        </tr>
                                        <tr/>
                                </table>
                        </xsl:if>
        </xsl:template>
  
  
        <xsl:template name="footer.navigation">
                <xsl:param name="prev" select="/foo"/>
                <xsl:param name="next" select="/foo"/>
                <xsl:variable name="home" select="/*[1]"/>
                <xsl:variable name="up" select="parent::*"/>
                <xsl:if test="$suppress.navigation = '0'">
                                                        <table border="0" 
cellpadding="0" cellspacing="0" height="65">
                                        <tr height="65">
                                                <td rowspan="2">
                                                        <img src="images/gbar.gif" 
width="432" height="79"/>
                                                </td>
                                                <td rowspan="2" 
background="images/gbar.gif" width="100%" align="right" 
  valign="top">
                                                        <a>
                                                                                
<xsl:attribute name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$home"/></xsl:call-template></xsl:attribute>
                                                                                <img 
src="images/doc.gif" width="63" height="65" border="0"/>
                                                                        </a>
                                                        <xsl:choose>
                                                                <xsl:when 
test="count($up)>0">
                                                                        <a>
                                                                                
<xsl:attribute name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$up"/></xsl:call-template></xsl:attribute>
                                                                                <img 
src="images/toc.gif" width="60" height="65" border="0"/>
                                                                        </a>
                                                                </xsl:when>
                                                                
<xsl:otherwise>&#160;</xsl:otherwise>
                                                        </xsl:choose>
  
                                                        <xsl:if test="count($prev)>0">
                                                                <a>
                                                                        <xsl:attribute 
name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$prev"/></xsl:call-template></xsl:attribute>
                                                                        <img 
src="images/prev.gif" width="76" height="65" border="0"/>
                                                                </a>
                                                        </xsl:if>                      
                                 
                                                        <xsl:if test="count($next)>0">
                                                                <a>
                                                                        <xsl:attribute 
name="href"><xsl:call-template 
  name="href.target"><xsl:with-param name="object" 
  select="$next"/></xsl:call-template></xsl:attribute>
                                                                        <img 
src="images/next.gif" width="60" height="65" border="0"/>
                                                                </a>
                                                        </xsl:if>
                                                </td>
                                        </tr>
                                        <tr/>
                                </table>
                        </xsl:if>
        </xsl:template>
  
  </xsl:stylesheet>
  
  
  
  
  
  
  
  
  1.1                  manual/src/docs/jbossapi.xml
  
  Index: jbossapi.xml
  ===================================================================
  <chapter>
        <title>JBoss API</title>
  <section><title>The JBoss API</title>
  <para>The JBoss API is available in JavaDoc format <ulink 
url="api/index.html">here</ulink>.</para>
  </section>
  </chapter>
  
  
  
  
  
  1.1                  manual/src/docs/jbossdocs.xml
  
  Index: jbossdocs.xml
  ===================================================================
  <!DOCTYPE book
    PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
    "docbookx/docbookx.dtd" [
  <!ENTITY jbossintro.xml SYSTEM "jbossintro.xml">
  <!ENTITY jbossapi.xml SYSTEM "jbossapi.xml">
  ]>
  <book>
  <bookinfo>
  <title>JBoss 2.0 Documentation</title>
  <copyright><year>2000</year><year>2001</year>
  <holder>JBoss Organization</holder>
  </copyright>
  </bookinfo>
  
  &jbossintro.xml;
  <!--
  &cmp.xml;
  &customizingjaws.xml;
  &advconfig.xml;
  &j2eedeployer.xml;
  &jbossfinal.xml;
  -->
  &jbossapi.xml;
  
  </book>
  
  
  
  
  
  
  
  1.1                  manual/src/docs/jbossintro.xml
  
  Index: jbossintro.xml
  ===================================================================
  <chapter>
        <title>Installing JBoss</title>
  
  <section><title>Introduction</title>
  <para>Before installing and running the server, you should check that your JDK 
  installation is working. (Step-by-step instructions are available.) 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.0. You can get JBoss 
  from www.jboss.org</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 using Install Anywhere which isn't a natural format 
  for Linux users. If you're running the X Window System on your Linux machine 
  and you have Netscape installed with Java enabled, this might work for you. 
  Otherwise, your best bet right now is to download from CVS or to install from 
  the Zip file like this:</para>
  
  <literallayout><command>su
  mkdir /usr/local/jboss
  cd /usr/local/jboss
  lynx -source \
    http://jboss.org/JBoss2/InstData/Other/install.zip \
    > install.zip
  mkdir installer
  cd installer
  unzip ../install.zip
  mv c:/jboss2/* ..
  cd ..
  rm -rf installer
  rm -f install.zip
  </command></literallayout>
  
  <para>You could try running the server now. Change to the bin directory, and 
  run the program like this: </para>
  
  <literallayout><command>cd bin
  java -jar run.jar
  </command>
  </literallayout>
  
  
  <para>In a proper installation, the server should start without any error 
  messages or exceptions being thrown. It will produce about three pages of 
  output on startup.</para>
  
  <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 interestEJB.tar.gz for this example; you will need to 
  unpack it into an empty directory.</para>
  
  <literallayout><command>cd /usr/local/jboss
  mkdir examples
  cd examples
  lynx -source http://jboss.org/interestEJB.tar.gz > interestEJB.tar.gz
  gunzip interestEJB.tar.gz
  tar xf interestEJB.tar
  rm -rf interestEJB.tar
  
  </command></literallayout>
  
  <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 archive interestEJB.tar.gz it will create this      
  structure automatically. </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</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</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</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/lib/ext/ejb.jarcom/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. This should create three class files: 
  InterestBean.class, Interest.class, and InterestHome.class. If you have `make' 
  on your system, and you have unpacked the archive, you can build all the 
  classes just be running make in the same directory as the Makefile.
  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), 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>
  
  <para>Overriding ejb-name with a real JNDI name in jboss.xml</para>
  
  <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>
        <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) 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
  [Container factory] Deploying:file:/usr/local/jboss/deploy/interest.jar
  [Container factory] Deploying Interest
  [Container factory] Started: Interest
  [Container factory] Bound Interest to interest/Interest
  [Container factory] Deployed application: file:/usr/local/jboss/deploy/interest.jar 
  </computeroutput></literallayout>
  
  <para>If you see a message like this: </para>
  <literallayout><computeroutput>
  [Container factory] Deploying:file:/usr/local/jboss/deploy/interest.jar
  [Container factory] Deployed application 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 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</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>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 articles. 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/lib/jboss/lib/ext/ejb.jar:. 
  InterestClient.java</command></para>
  
  <para>This generates InterestClient.class in the current directory. </para>
  
  
  </section>
  
  
  <section><title>Compiling and running 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 $$CLASSPATH:\
  /usr/local/jboss/lib/ext/ejb.jar:/usr/local/jboss/client/jboss-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 the JBoss client classes 
  and the EJB classes as well as the standard classpath (if any).
  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.</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>
  
  
  
  
  
  1.1                  manual/src/docs/styles.css
  
  Index: styles.css
  ===================================================================
  /* Background */
  body { background-color: #ffffee }
  
  /* Font selection */
  ul,ol,dt,dl,th,td,h1,h2,h3,h4,p { font-family: Verdana, Arial, Helvetica, sans-serif 
}
  
  /* Font styles */
  p {  font-size: 10pt}
  
  td { font-size: 12pt }
  th { font-size: 12pt; font-weight: bold}
  
  h1 { font-size: 16pt; font-weight: bold}
  h2 { font-size: 14pt; font-weight: bold}
  h3 { font-size: 12pt; font-weight: bold}
  h4 { font-size: 10pt; font-weight: bold; font-style: italic}
  
  /* Lists */
  ul { font-size: 10pt }
  ol { font-size: 10pt }
  
  dt { font-size: 10pt }
  dl { font-size: 10pt }
  
  /* Classes */
  .mediaobject { border: thin; border-style: solid; margin-right: 100% }
  .programlisting { padding: 1; width: auto; margin: auto; font-family: Courier; 
border-style: solid; border-width: 1; white-space: pre; background-color: #fffff7 }
  .literallayout { padding: 1; width: auto; margin: auto; border-style: solid; 
border-width: 1; background-color: #fffff7 }
  
  
  

Reply via email to