[jboss-cvs] JBossAS SVN: r67442 - projects/microcontainer/trunk/docs/User_Guide/src/main/docbook.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Nov 26 09:32:38 EST 2007


Author: newtonm
Date: 2007-11-26 09:32:38 -0500 (Mon, 26 Nov 2007)
New Revision: 67442

Modified:
   projects/microcontainer/trunk/docs/User_Guide/src/main/docbook/User_Guide.xml
Log:
Redrafted content to reflect static and dynamic deployment of services.

Modified: projects/microcontainer/trunk/docs/User_Guide/src/main/docbook/User_Guide.xml
===================================================================
--- projects/microcontainer/trunk/docs/User_Guide/src/main/docbook/User_Guide.xml	2007-11-26 13:14:53 UTC (rev 67441)
+++ projects/microcontainer/trunk/docs/User_Guide/src/main/docbook/User_Guide.xml	2007-11-26 14:32:38 UTC (rev 67442)
@@ -38,8 +38,8 @@
       </itemizedlist>
       <para>Each environment aims to provide a base level of functionality on top of which  developers can add their own code to create applications. For example Java SE provides networking and security libraries together with graphical user interface toolkits to facilitate the development of desktop   and simple client-server applications. Java EE takes this a stage further by adding a number of &apos;enterprise  services&apos; such as transactions, messaging, and persistence that allow much more robust and scalable &apos;enterprise applications&apos; to be developed.  These services are  typically combined together inside a JEE application server in order to provide a standard runtime environment for enterprise applications but it is often the case that some are never used.</para>
       <para>Services that are never used  are undesirable as they can  take  up valuable resources such as CPU and memory resulting in lower performance. They may also clutter up the environment with redundant configuration files,  complicating maintenance and   adding unnecessary complexity.   Given these drawbacks it would   be better if there was a   way to create a custom runtime environment containing only those services  that were needed. You would then be able to create your own custom &apos;Java Edition&apos; tailored to your requirements.</para>
-      <para>JBoss Microcontainer aims to provide  these capabilities by allowing services, created using Plain Old Java Objects (POJOs), to be deployed into a standard Java SE runtime environment in a controlled manner to create a customized  environment  for your applications. Dependencies are fully managed to ensure that new services cannot be deployed until services they depend on have first been deployed. Likewise undeploying a service causes all dependent services to first be undeployed in order  to maintain the integrity of the system. You can even redeploy services at runtime providing that you access them via the microcontainer bus.</para>
-      <para>JBoss Application Server   5.0 uses the microcontainer to integrate enterprise services together with a Servlet/JSP container, EJB container, deployers and management utilities in order to     provide a standard Java EE environment. If you need additional services then you can simply deploy these on top of Java EE to provide the functionality you need. Likewise you are free to remove any services that you don&apos;t need simply by changing the  configuration. You can even use the microcontainer to do this in other   environments such as Glassfish since you can plug in different classloading models  during the service deployment phase.</para>
+      <para>JBoss Microcontainer aims to provide  these capabilities by allowing services, created using Plain Old Java Objects (POJOs), to be deployed into a standard Java SE runtime environment in a controlled manner to create a customized  environment  for your applications. Dependencies are fully managed to ensure that new services cannot be deployed until services they depend on have first been deployed. Where it makes sense to do so you can even redeploy services at runtime providing that you access them via the microcontainer bus. Undeploying a service  causes all dependent services to be undeployed first in order  to maintain the integrity of the system. </para>
+      <para>JBoss Application Server   5.0 uses the microcontainer to integrate enterprise services together with a Servlet/JSP container, EJB container, deployers and management utilities in order to     provide a standard Java EE environment. If you need additional services then you can simply deploy these on top of Java EE to provide the functionality you need. Likewise you are free to remove any services that you don&apos;t need simply by changing the  configuration. You can even use the microcontainer to do this in other   environments such as GlassFish and Tomcat since you can plug in different classloading models  during the service deployment phase.</para>
       <para>Since  JBoss Microcontainer is very lightweight and deals with POJOs it can also be used to deploy services into a Java ME runtime environment. This opens up new possibilities for mobile applications that can now take advantage of  enterprise services without requiring a full JEE application server. </para>
       <para>In common with other lightweight containers JBoss Microcontainer uses  dependency injection to wire individual POJOs together to create services.  Configuration is performed using either XML or annotations depending on where the information is best located. Finally unit testing is made extremely simple thanks to a helper class that extends JUnit to setup the test environment, allowing you to access  POJOs and services from your test methods using just a few lines of code.</para>
     </chapter>
@@ -50,8 +50,7 @@
       <note>
         <para>To build and run the examples you first need to install and configure Maven 2.0.7 available from <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink></para>
         <para>Installation is performed by downloading and unzipping the  maven-2.0.7-bin.zip file to a convenient location on your local disk. Configuration  consists of adding $MAVEN_HOME/bin to your path and adding the following profile to your ~/.m2/settings.xml file:</para>
-      </note>
-      <para><programlisting>&lt;settings&gt;
+        <para><programlisting>&lt;settings&gt;
   &lt;profiles&gt;
     &lt;profile&gt;
       &lt;id&gt;jboss.repository&lt;/id&gt;
@@ -95,7 +94,8 @@
     &lt;/profile&gt;
   &lt;/profiles&gt;
 &lt;/settings&gt;</programlisting></para>
-      <para>This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.</para>
+        <para>This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.</para>
+      </note>
       <para>Once you have configured Maven and downloaded the examples then you can go to one of the following subdirectories in the <code>examples/User_Guide</code> directory and enter <code>mvn install</code> to perform a build:</para>
       <itemizedlist>
         <listitem>
@@ -114,10 +114,11 @@
           <para>integrating - examples of how JBoss Microcontainer forms the basis of JBoss AS 5 and how you can deploy MBean services alongside POJO services for backwards compatibility</para>
         </listitem>
       </itemizedlist>
-      <para>Instructions on how to run the individual examples can be found in the relevant parts of this guide.</para>
+      <para>Instructions on how to run the individual examples can be found in the corresponding parts of this guide.</para>
     </chapter>
     <chapter>
       <title>Building services</title>
+      <para>Before we talk about building services using POJOs it is necessary to define what we mean by these terms.</para>
       <para><emphasis role="bold">
           <emphasis role="underline">POJOs</emphasis>
         </emphasis></para>
@@ -147,17 +148,17 @@
       <para>Q) Is a POJO a service?</para>
       <para>A) No, because although it performs work that is useful to multiple clients you cannot access it using a name. Clients have to create a POJO themselves either directly using the <code>new</code> operator or indirectly using a factory. </para>
       <para>Q) Does a  class have to implement an interface in order  to provide a &apos;well-defined&apos; interface?</para>
-      <para>A) Not necessarily. Providing that we don&apos;t remove fields or methods from a class, or restrict access to them, then  we can always change  its implementation without needing to recompile the client. See the  section entitled <ulink url="http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44524">Resolution of Symbolic References</ulink> from the Java Language Specification for more details.</para>
+      <para>A) Not necessarily. Providing that we don&apos;t remove fields or methods from a class, or restrict access to them,  we can always change  its implementation without needing to recompile the client. See the  section entitled <ulink url="http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44524">Resolution of Symbolic References</ulink> from the Java Language Specification for more details.</para>
       <para>The  &apos;well-defined&apos; interface in this respect is composed from  the original class&apos;s fields and methods together with their access modifiers.</para>
       <note>
         <para>Implementing an  interface is  only necessary  if we want to allow a client to <emphasis role="bold">choose</emphasis> between <emphasis role="bold">alternative implementations</emphasis>. i.e. if the client is compiled against an interface then we can provide as many different implementations of the interface as we like without having to recompile the client. This is because the interface ensures that the method signatures do not change.</para>
       </note>
       <para>What then must we do in order to create a service using a POJO? The answer is to provide a naming mechanism that allows us to register a reference to the POJO  instance with a name. Clients can then lookup the POJO reference using the name at runtime and use it to perform work. The POJO class is not required to implement an interface unless it is important that the client can choose between alternative implementations. </para>
-      <para>JBoss Microcontainer provides such a naming mechanism in order that we can  deploy our POJO  services into a runtime environment such as Java SE and look them up from within our applications.</para>
-      <para>Since robust implementations of Java EE services  are already available from  JBoss.org and other communities, it is common for companies to focus on creating more &apos;business-oriented&apos; services. For this reason we shall look at creating, configuring and testing a simple Human Resources service that could potentially be used  in a wide-variety of companies.</para>
+      <para>JBoss Microcontainer provides such a naming mechanism in the form of a Controller so that we can  deploy our POJO  services into a runtime environment such as Java SE and look them up from within our applications.</para>
+      <para>Since robust implementations of Java EE services  are already available from  JBoss.org and other communities, it is common for companies to focus on creating more &apos;business-oriented&apos; services. For this reason we shall look at creating, configuring and testing a simple Human Resources service that could potentially be used  by a number of different applications.</para>
       <section>
         <title>Creating POJOs</title>
-        <para>The example that relates to this section can be found in the <code>examples/User_Guide/gettingStarted/humanResourcesService</code> directory. The directory layout, as with all of the examples for this User Guide,  follows the <ulink url="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">Maven Standard Directory Layout</ulink>.</para>
+        <para>The example that relates to this section can be found in the <code>examples/User_Guide/gettingStarted/humanResourcesService</code> directory. The directory layout, as with all of the examples for the User Guide,  follows the <ulink url="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">Maven Standard Directory Layout</ulink>.</para>
         <para><programlisting>humanResourcesService/pom.xml
                      /src/main/java
                          /test/java
@@ -204,8 +205,8 @@
           </listitem>
         </itemizedlist>
         <para>The Human Resources Service is therefore composed of a handful of classes which work together to allow a list of employees, together with details of their addresses and salaries, to be maintained by an HRManger. Thanks to the SalaryStrategy interface it is possible to configure the HRManager so that different salary strategy implementations are used. These place minimum and maximum limits on the salaries that can be awarded to employees depending on various rules.</para>
-        <para>To compile the source code you simply need to enter <code>mvn compile</code> from the <code>humanResourcesService/</code> directory. This will create a new directory  called <code>target/classes</code>  containing the compiled code. To clean up the humanResourcesService project and remove the <code>target</code> directory simply enter <code>mvn clean</code>. </para>
-        <para>Now that we  have compiled our POJO classes we  need to create instances of them. This is done by creating an XML deployment descriptor  that contains a list of beans representing individual instances. Each bean is given a name so that the instance can be looked up at runtime by clients.</para>
+        <para>To compile the source code you simply need to enter <code>mvn compile</code> from the <code>humanResourcesService/</code> directory. This will create a new directory  called <code>target/classes</code>  containing the compiled code. To clean up the project and remove the <code>target</code> directory simply enter <code>mvn clean</code>. </para>
+        <para>Now that we  have compiled our classes we  need to create instances of them. This is done by creating an XML deployment descriptor  that contains a list of beans representing individual instances. Each bean is given a name so that the instance can be looked up at runtime by clients.</para>
         <programlisting>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
 
 &lt;deployment xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
@@ -215,11 +216,11 @@
    &lt;bean name=&quot;HRService&quot; class=&quot;org.jboss.example.service.HRManager&quot;/&gt;
       
 &lt;/deployment&gt;</programlisting>
-        <para>Here we have declared that we want to create an instance of the HRManager class and register it with the name HRService. This file is  passed to  a deployer associated with the microcontainer at runtime to perform the actual deployment and instantiate the beans.</para>
+        <para>Here we have declared that we want to create an instance of the HRManager class and register it with the name HRService. This file is  passed to  an XML deployer associated with the microcontainer at runtime to perform the actual deployment and instantiate the beans.</para>
       </section>
       <section>
         <title>Wiring POJOs together </title>
-        <para>So far we have seen how to  create POJOs and declare instances of them together with names in the XML deployment descriptor. However, individual POJO instances  can only provide relatively simple behaviour. Things really get interesting when we combine POJOs together to perform more complex tasks. In our example we know that we can choose  a number of different salary strategies for the HRManager so how do we go about wiring the POJOs together?</para>
+        <para>So far we have seen how to  create POJOs and declare instances of them together with names in an XML deployment descriptor. However, individual POJO instances  can only provide relatively simple behaviour. Things really get interesting when we combine POJOs together to perform more complex tasks. In our example we know that we can choose different salary strategy implementations for the HRManager so how do we go about wiring the POJOs together?</para>
         <para>The answer is to use the XML deployment descriptor again as follows:</para>
         <programlisting>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
 
@@ -235,7 +236,7 @@
          class=&quot;org.jboss.example.service.util.AgeBasedSalaryStrategy&quot;/&gt;
        
 &lt;/deployment&gt;</programlisting>
-        <para>We first need to create an instance of our chosen salary strategy by including an additional &lt;bean&gt; element. Here we have chosen the AgeBasedSalaryStrategy. Next we need to inject a reference to this bean into the instance of HRManager created using the HRService bean. Injection is possible  as the HRManager class contains a <code>setSalaryStrategy(SalaryStrategy strategy)</code> method. Behind the scenes JBoss Microcontainer will call this method on the newly created HRManager instance and pass in a reference to the AgeBasedSalaryStrategy instance.</para>
+        <para>We first need to create an instance of our chosen salary strategy implementation by including an additional &lt;bean&gt; element. Here we have chosen the AgeBasedSalaryStrategy. Next we need to inject a reference to this bean into the instance of HRManager created using the HRService bean. Injection is possible  as the HRManager class contains a <code>setSalaryStrategy(SalaryStrategy strategy)</code> method. Behind the scenes JBoss Microcontainer will call this method on the newly created HRManager instance and pass in a reference to the AgeBasedSalaryStrategy instance.</para>
         <para>In other words the XML deployment descriptor causes the same sequence of events to occur as if you had written the following code:</para>
         <programlisting>HRManager hrService = new HRManager();
 AgeBasedSalaryStrategy ageBasedSalary = new AgeBasedSalaryStrategy();
@@ -245,7 +246,7 @@
           <para>Although we can create instances of classes using the &lt;bean&gt; element in the deployment descriptor it is not always appropriate to do so. For example we do not need to create instances of the Employee and Address classes since these will be created by the client in response to input from the user. As such they remain part of the service but are not mentioned in the deployment descriptor. </para>
         </note>
         <note>
-          <para>Also note that it is possible to define multiple beans within a deployment descriptor providing that each has a unique name. The names are required in order to perform injection as shown above.  However this does not mean to say  that all of these beans represent services. While a service could be implemented using a single bean it is most often the case that multiple beans are used together as in our example. In these cases there is usually one bean that represents the service entry point containing the public methods intended for the clients to call. In our example this is the HRService bean. Notice that there is nothing in the XML deployment descriptor  to say which beans represent a service or indeed which bean if any is the service entry point (a service may run autonomously in which case it is its own client). Care must therefore be taken when creating deployment descriptors to ensure that sufficient comments are included to describe what the beans are!
  used for. Alternatively a naming convention such as ending  each bean name that represents a service entry point  with &apos;Service&apos; can be used instead, e.g. HRService.</para>
+          <para>Also note that it is possible to define multiple beans within a deployment descriptor providing that each has a unique name. The names are required in order to perform injection as shown above.  However this does not mean to say  that all of the beans represent services. While a service could be implemented using a single bean it is most often the case that multiple beans are used together as in our example. In these cases there is usually one bean that represents the service entry point containing the public methods intended for the clients to call. In our example this is the HRService bean. Notice that there is nothing in the XML deployment descriptor  to say which beans represent a service or indeed which bean if any is the service entry point (a service may run autonomously in which case it is its own client). Care must therefore be taken when creating deployment descriptors to ensure that sufficient comments are included to describe what the beans are u!
 sed for. Alternatively a naming convention such as ending  each bean name that represents a service entry point  with &apos;Service&apos; can be used instead, e.g. HRService.</para>
         </note>
       </section>
       <section>
@@ -273,15 +274,15 @@
       <section>
         <title>Testing a service</title>
         <para>We should now have a good idea about how to create POJOs and configure them using an XML deployment descriptor so how do we go about testing them? Thankfully JBoss Microcontainer makes it extremely easy to unit test individual POJOs as well as POJOs that are wired together through the use of a MicrocontainerTest class.</para>
-        <para>The org.jboss.test.kernel.junit.MicrocontainerTest class inherits from junit.framework.TestCase and as such it sets up each test by bootstrapping JBoss Microcontainer and adding a BasicXMLDeployer. It then looks on the classpath for an XML deployment descriptor with the same name as the test class (ending in .xml) and residing in a directory structure representing the class&apos;s package name. Any beans found in this file are deployed and can then be accessed using a convenience method called <code>getBean(String name)</code>. </para>
-        <para>You can see examples of these files in the src/test/resources directory:</para>
+        <para>The org.jboss.test.kernel.junit.MicrocontainerTest class inherits from junit.framework.TestCase and as such it sets up each test by bootstrapping JBoss Microcontainer and adding a BasicXMLDeployer. It then looks on the classpath for an XML deployment descriptor with the same name as the test class ending in .xml and residing in a directory structure representing the class&apos;s package name. Any beans found in this file are deployed and can then be accessed using a convenience method called <code>getBean(String name)</code>. </para>
+        <para>You can see examples of these deployment descriptors in the src/test/resources directory:</para>
         <programlisting>org/jboss/example/service/HRManagerTestCase.xml
                          /HRManagerAgeBasedTestCase.xml
                          /HRManagerLocationBasedTestCase.xml
 
 org/jboss/example/service/util/AgeBasedSalaryTestCase.xml
                               /LocationBasedSalaryTestCase.xml</programlisting>
-        <para>Our  test   code is located in the src/test/java directory:</para>
+        <para>The  test   code is located in the src/test/java directory:</para>
         <programlisting>org/jboss/example/service/HRManagerTestCase.java
                          /HRManagerAgeBasedTestCase.xml
                          /HRManagerLocationBasedTestCase.xml
@@ -300,7 +301,7 @@
       </section>
       <section>
         <title>Packaging a service</title>
-        <para>Now that we have successfully created and tested our service it is time to package it up so that others can use it. The simplest way to do this is to create a JAR containing all of the classes. You can  choose to  include the XML deployment descriptor if there is a sensible default way to configure the service but you are not required to do so.</para>
+        <para>Now that we have successfully created and tested our service it is time to package it up so that others can use it. The simplest way to do this is to create a JAR containing all of the classes. You can  choose to  include the  deployment descriptor if there is a sensible default way to configure the service but you are not required to do so.</para>
         <para>If you do choose to include the deployment descriptor then by convention you should call it <code>jboss-beans.xml</code> and put it in a META-INF directory. This helps if you want to later deploy the service in JBoss AS 5 as the  JAR deployer recognises this layout by default and will automatically perform the deployment.</para>
         <para>In our case we will not include it as we want to configure the service by editing the descriptor directly as a separate file. To generate a JAR in the <code>target</code> directory containing all of the compiled classes simply enter <code>mvn package</code> from the <code>humanResourcesService/</code> directory. </para>
         <para>To make the JAR available to other maven projects you then need to enter <code>mvn install</code> in order to copy it to your local maven repository.</para>
@@ -321,7 +322,7 @@
       <title>Using services </title>
       <para>In the previous chapter we looked at how to create, configure, test and package a service. It is now time to move on and create a client so that we can use the service to perform actual work.</para>
       <para>In order to keep things simple the client uses a Text User Interface (TUI) to accept input from the user and output results. In the real-world  a Graphical User Interface (GUI) would almost certainly be used but here we are more concerned with demonstrating how the client interacts with the service than showing how to develop a rich desktop application.</para>
-      <para>You will find all of the necessary files in the <code>examples/User_Guide/gettingstarted/commandLineClient</code> directory.  As with the Human Resources Service example this follows the Maven Standard Directory Layout: </para>
+      <para>You will find all of the necessary files in the <code>examples/User_Guide/gettingstarted/commandLineClient</code> directory.  As with the previous example this follows the Maven Standard Directory Layout: </para>
       <programlisting>commandLineClient/pom.xml
                  /src/main/assembly
                  /src/main/config
@@ -334,7 +335,7 @@
                         /ConsoleInput.java
                         /EmbeddedBootstrap.java
                         /UserInterface.java</programlisting>
-      <para>UserInterface describes methods that the client will call at runtime to request data from the user. ConsoleInput is an  implementation of this  that creates a TUI allowing the user to operate the client from the command line. The advantage of this design is that we can easily create a Swing implementation of UserInterface  at a later date and replace the TUI with a GUI if we decide to improve usability. We can also create a mock implementation for testing purposes that simulates a user entering data. This allows us to check the behaviour of the client automatically using conventional JUnit test cases, as demonstrated by the code in the <code>src/test/java</code> directory:</para>
+      <para>UserInterface describes methods that the client will call at runtime to request data from the user. ConsoleInput is an  implementation of this  that creates a TUI allowing the user to operate the client from the command line. The advantage of this design is that we can easily create a Swing implementation of UserInterface  at a later date and replace the TUI with a GUI if we decide to improve usability. We can also create a mock implementation for testing purposes that simulates a user entering data. This allows us to check the behaviour of the client automatically using conventional JUnit test cases as demonstrated by the code in the <code>src/test/java</code> directory:</para>
       <programlisting>org/jboss/example/client/ClientTestCase.java
                         /ClientTestSuite.java
                         /MockUserInterface.java</programlisting>
@@ -377,9 +378,9 @@
           <imagedata align="center" fileref="images/tuiMenu.png"/>
         </imageobject>
       </mediaobject>
-      <para>To select an option enter the  letter shown on the left-hand side and press return. For example to redisplay the menu options enter &apos;m&apos; followed by return. This is useful  if they scroll off the top of the screen as you input data and read responses. Entering more than one letter or entering an invalid option will result in an appropriate error message.</para>
+      <para>To select an option enter the  letter shown on the left-hand side and press return. For example to redisplay the menu options enter &apos;m&apos; followed by return. This is useful  if they scroll off the top of the screen as you input data and read results. Entering more than one letter or entering an invalid option will result in an appropriate error message.</para>
       <important>
-        <para>The run.sh script sets up the runtime environment by  adding all of the JARs found in the <code>lib</code> directory to the  classpath using the <code>java.ext.dirs</code> system property. It also adds the current directory and the client-1.0.0.jar using the <code>-cp</code> flag so that the jboss-beans.xml descriptor can be found at runtime together with the org.jboss.example.client.Client class which is called to start the application.</para>
+        <para>The run.sh script sets up the runtime environment by  adding all of the JARs found in the <code>lib</code> directory to the  classpath using the <code>java.ext.dirs</code> system property. It also adds the current directory and the client-1.0.0.jar using the <code>-cp</code> flag so that the jboss-beans.xml deployment descriptor can be found at runtime together with the org.jboss.example.client.Client class which is called to start the application.</para>
       </important>
       <section>
         <title>Bootstrapping the microcontainer</title>
@@ -398,8 +399,8 @@
     controller = kernel.getController();
     bus = kernel.getBus();
  }</programlisting>
-        <para>First of all a url representing the jboss-beans.xml deployment descriptor was created. This is required later on by the deployer so that we can deploy and undeploy beans declared in the file. Here we have chosen to use the getResource() method of the application classloader as we deliberately placed the jboss-beans.xml file  on the classpath.  However, this is not a requirement  and you are free to call the deployment descriptor anything you like and place it anywhere you want provided that the URL is valid and reachable.</para>
-        <para>Next we created an instance of JBoss Microcontainer together with a deployer. This process  is called bootstrapping and for convenience a  BasicBootstrap class is provided  as part of the microcontainer to allow for configuration via system properties. In order to add a deployer we simply extended BasicBootstrap to create an EmbeddedBootstrap class  and overrided the protected bootstrap() method as follows:</para>
+        <para>First of all a url representing the jboss-beans.xml deployment descriptor was created. This is required later on by the XML deployer so that we can deploy and undeploy beans declared in the file. Here we have chosen to use the getResource() method of the application classloader as we deliberately placed the jboss-beans.xml file  on the classpath.  However, this is not a requirement  and you are free to call the deployment descriptor anything you like and place it anywhere you want provided that the URL is valid and reachable.</para>
+        <para>Next we created an instance of JBoss Microcontainer together with an XML deployer. This process  is called bootstrapping and for convenience a  BasicBootstrap class is provided  as part of the microcontainer to allow for configuration via system properties. To add an XML deployer we simply extend BasicBootstrap to create an EmbeddedBootstrap class  and override the protected bootstrap() method as follows:</para>
         <programlisting>public class EmbeddedBootstrap extends BasicBootstrap {
 
     protected BasicXMLDeployer deployer;
@@ -437,7 +438,7 @@
         <para>Finally we stored references to the microcontainer controller and bus so that we can lookup bean references by name and invoke them either directly or indirectly as necessary.</para>
       </section>
       <section>
-        <title>Deploying and undeploying the service</title>
+        <title>Deploying the service</title>
         <para>Once the client has been created we can proceed to deploy the Human Resources service. This is done by entering the &apos;d&apos; option. You should see the following log output indicating that the BasicXMLDeployer has parsed the jboss-beans.xml file using the url and instantiated the beans found within.</para>
         <mediaobject>
           <imageobject>
@@ -447,7 +448,7 @@
         <note>
           <para>The microcontainer is able to instantiate the beans as their classes are available in the application classpath inside the <code>lib/humanResourcesService.jar</code> file. We could have equally placed these classes in an exploded directory structure and added this to the classpath but in general you will package them in a JAR for convenience. </para>
         </note>
-        <para>Notice that our deployment descriptor is entirely separate from the humanResourcesService.jar file. This is done on purpose so that you can easily edit it and test your changes by undeploying and deploying the beans again at runtime. You can test this by uncommenting fragments of the file to configure the HRService bean in different ways:</para>
+        <para>Notice that our deployment descriptor is entirely separate from the humanResourcesService.jar file. This is done on purpose so that you can easily edit it and test your changes by redeploying the service. The jboss-beans.xml file in the example contains some commented out fragments of XML that you can uncomment to configure it  in different ways:</para>
         <programlisting>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
 &lt;deployment xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;            xsi:schemaLocation=&quot;urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd&quot;            xmlns=&quot;urn:jboss:bean-deployer:2.0&quot;&gt;
 
@@ -468,14 +469,10 @@
     &lt;/bean&gt; --&gt;
 
 &lt;/deployment&gt;</programlisting>
-        <para>To undeploy the service type &apos;u&apos; followed by return. You can then deploy it again using the &apos;d&apos; option, remembering to save any changes to the jboss-beans.xml file first. You can confirm that your changes have been applied by printing out the status of the HRService using the &apos;p&apos; option.</para>
-        <important>
-          <para>The act of deploying a bean, as we already know, consists of creating an instance of the bean class and associating a reference to it with the bean name. This prevents clients from having to create the bean themselves as they can simply access it using the name at runtime. So what happens during undeployment?</para>
-          <para>The answer is that the microcontainer releases its reference to the bean instance, the intention being that it becomes available for garbage collection. Whether it can be garbage collected or not depends on whether any clients have cached their own copy of the reference that they looked up. The impact of this is discussed in the next section.</para>
-        </important>
+        <para>Depending on how you access the service at runtime you may need to shutdown the application and restart it again to  redeploy the service and see your changes. This reduces the flexibility of the application but  results in faster performance at runtime.  Alternatively you may be able to simply redeploy the service whilst the application is running. This increases  flexilibity but results in slower runtime performance. Careful consideration of these tradeoffs must   be made  before deciding on the approach you will take.</para>
       </section>
       <section>
-        <title>Using the kernel controller</title>
+        <title>Accessing a service directly</title>
         <para>If no parameter is given to the <code>run.sh</code> script when  the client is started then a reference to the HRService bean is looked up using the microcontainer controller once the service is deployed:</para>
         <programlisting>private final static String HRSERVICE = &quot;HRService&quot;;
 
@@ -488,8 +485,8 @@
         if (context != null) { manager = (HRManager) context.getTarget(); }
     }
 }</programlisting>
-        <para>Rather than directly lookup a reference to the bean instance we actually lookup a reference to a <code>ControllerContext</code>. We then obtain a reference to the bean instance from the context using the <code>getTarget()</code> method.  The reason for this is because the bean can exist in many states within the microcontainer e.g. DESCRIBED, INSTANTIATED, CONFIGURED, INSTALLED. In order to keep a track of which state the bean is in we need to wrap it in another object called a context that describes the current state. The name of the context is the same as the bean name. Once a context reaches the INSTALLED state then the bean it represents is considered to be deployed.</para>
-        <para>Now that we have a reference to the bean instance representing our service entry point we can call methods on it at runtime to perform work:</para>
+        <para>Rather than immediately looking up a reference to the bean instance we first lookup a reference to a <code>ControllerContext</code>. We then obtain a reference to the bean instance from the context using the <code>getTarget()</code> method.  The reason for this is because the bean can exist in many states within the microcontainer e.g. DESCRIBED, INSTANTIATED, CONFIGURED, INSTALLED. In order to keep track of which state the bean is in we need to wrap it in another object called a context that describes the current state. The name of the context is the same as the bean name. Once a context reaches the INSTALLED state then the bean it represents is considered to be deployed.</para>
+        <para>Now that we have a reference to the bean instance representing our service entry point we can call methods on it to perform work:</para>
         <programlisting>@SuppressWarnings(&quot;unchecked&quot;)
 Set&lt;Employee&gt; listEmployees() {
     if (useBus)
@@ -497,18 +494,20 @@
     else
         return manager.getEmployees();
 }</programlisting>
-        <para>So far, so good, but what happens if we want to reconfigure the service and redeploy it at runtime? As we know from the previous section the microcontainer will release its reference to the bean instance and create another instance representing the new configuration. If we have cached the reference to the first instance in our client then undeploying the service has no affect as it  can still be used to access the bean. Similarly deploying the service again will not cause another lookup so the client will continue to use the cached  reference.</para>
-        <important>
-          <para>If a client caches its own reference to a bean instance looked up from the microcontainer then this prevents the instance from being garbage collected when it is undeployed.  Deploying the bean again simply creates another instance which is totally separate from the first. Subsequent lookups will then return references to this second instance resulting in two different versions of the service running at the same time.</para>
-          <para>Care must therefore be taken to ensure that you understand the effects of caching references to bean instances looked up from the microcontainer. </para>
-        </important>
-        <para>If we really want to reconfigure and redeploy our service at runtime then we either need to recache the reference to the bean instance each time we deploy the service or we need to use a bus. Using a bus is the preferred method as it is not always practical to keep track of which clients have copies of the bean reference or if they have passed them on to others.</para>
+        <para>The client is said to be accessing the service directly since it&apos;s using a reference to the actual bean instance.   Performance is good as each method call goes directly to the bean but  what happens if we want to reconfigure the service and redeploy it whilst the application is running? </para>
+        <para>Reconfiguration as we know is achieved by making changes to the XML deployment descriptor and saving the file but in order to redeploy the service we must first undeploy the current one. During undeployment the microcontainer  controller releases its reference to the bean instance representing the service entry point together with any beans that depend on it. The intention is that these beans will subsequently become available for garbage collection as they are no longer required by the application. Deploying the service again creates  new bean  instances representing the new configuration. Any subsequent lookups from clients will then retrieve references to these new instances and  they will be able to access the reconfigured service.</para>
+        <para>The problem is that  we  cache the reference to the bean instance in our client when we deploy the service for the first time. Undeploying the service therefore has no affect as the bean instance can still be accessed using the cached reference and it will not be garbage collected until the client releases it. Similarly deploying the service again will not cause another lookup as the client already has a cached reference. It will therefore continue to use the bean instance representing the initial service configuration.</para>
+        <note>
+          <para>You can test this behaviour for yourself by typing  &apos;u&apos; followed by return to undeploy the current service. You should still be able to access the service from the client even though it is &apos;undeployed&apos;. Now make some changes to the configuration using the jboss-beans.xml file and deploy it again using the &apos;d&apos; option (remember to save any changes you make to jboss-beans.xml first). Printing out the status of the service using the &apos;p&apos; option should allow you to see that the client is still accessing the initial service that was deployed.</para>
+        </note>
+        <para>Even if we change our client so that we lookup a new reference each time the service is redeployed there is nothing to prevent new developers from coming along and mistakedly handing out copies of this reference to other objects. If all of these references are not cleaned up during redeployment then this then puts us in the same situation as before with access to older instances of the service still possible.</para>
+        <para>To reliably redeploy the reconfigured service you must therefore shutdown the application completely using the &apos;q&apos; option and then restart it using the run.sh script. For enterprise  services such as Transactions, Messaging and Persistance this is not considered a problem since they are  generally always in use. As such they cannot be redeployed at runtime and benefit from the high performance given by using direct access. If your service falls into this category then you too should consider using direct access via the microcontainer controller.</para>
       </section>
       <section>
-        <title>Using the kernel bus</title>
+        <title>Accessing a service indirectly</title>
         <para>The run.sh script can be called with an optional parameter &apos;bus&apos; to specify that calls to the Human Resources service should take place using the microcontainer bus:</para>
         <programlisting>./run.sh bus</programlisting>
-        <para>Since we no longer have a direct reference to the bean instance we must specify all of the information needed to call a method at runtime. This consists of the bean name, method name, method arguments and method types. The bus takes this information using the invoke() method and uses it to call the bean on the client&apos;s behalf.</para>
+        <para>We no longer lookup a direct reference to the bean instance using the microcontainer controller but instead call an invoke() method on the bus passing in the bean name, method name, method arguments and method types. The bus takes this information and uses it to call the bean on the client&apos;s behalf.</para>
         <programlisting>private final static String HRSERVICE = &quot;HRService&quot;;
 
 ...
@@ -530,19 +529,23 @@
     }
     return result;
 }</programlisting>
-        <para>Behind the scenes the bus looks up the reference to the bean instance and calls the method using reflecton. As the bus does not cache the reference we can  safely make changes to our service configuration and redeploy it at runtime. Subsequent calls by the client will then result in the new reference to the service being used as expected.   In technical terms we say that the client and service have been decoupled. You can test this behaviour out for yourself by deploying the service, adding a new employee, listing the employees to check they have been added and then redeploying the service. You should find that listing the employees again results in an empty list as employees aren&apos;t persisted between redeployments.</para>
+        <para>Behind the scenes the bus looks up the reference to the bean instance and calls the method using reflecton. Since the client never has a direct reference to the bean instance we say that it accesses the service &apos;indirectly&apos;. As the bus does not cache the reference we can  safely make changes to our service configuration and redeploy it at runtime. Subsequent calls by the client will then result in the new reference to the service being used as expected.   In technical terms we say that the client and service have been decoupled.</para>
+        <note>
+          <para>You can test this behaviour out for yourself by deploying the service and using the &apos;p&apos; option to print out the status. Undeploy the service using the &apos;u&apos; option and check that you cannot access it anymore. Now make some changes to the configuration using the jboss-beans.xml file and deploy it again using the &apos;d&apos; option (remember to save any changes you make to jboss-beans.xml first). Printing out the status again using the &apos;p&apos; option should reveal that the client is accessing the new service configuration.</para>
+        </note>
+        <para>As the bus uses reflection to call bean instances it is slower than using direct access. The benefit however is that only the bus references the bean instances directly. This means that when a service is redeployed we can clean up all of the existing references and replace them with new ones, allowing us to reliably redeploy a service at runtime. Services that are not used very often or that are specific to certain applications are good candidates for indirect access using the microcontainer bus.</para>
       </section>
       <section>
-        <title>Controlling Classloading</title>
-        <para>So far we have been using the application classloader to load all of the classes in our application. The application classpath  was setup by the run.sh script using the -cp flag to include the current directory and the client-1.0.0.jar.</para>
+        <title>Dynamic deployment</title>
+        <para>So far we have been using the external and application classloaders to load all of the classes in our application. The application classpath  was setup by the run.sh script using the -cp flag to include the current directory and the client-1.0.0.jar.</para>
         <programlisting>java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1</programlisting>
-        <para>For convenience the JARs in the lib directory were added using the <code>java.ext.dirs</code> system property as this prevents us from having to list the full path to each of the JARs after the -cp flag.</para>
+        <para>For convenience the JARs in the lib directory were added to the external classloader&apos;s classpath  using the <code>java.ext.dirs</code> system property as this prevents us from having to list the full path to each of the JARs after the -cp flag. Since the external classloader is the parent of the application classloader our client classes can find all of the microcontainer classes together with the Human Resources service classes at runtime.</para>
         <note>
-          <para>If you are using Java 6+ then you can use a wildcard to include all JARs in a directorywith the -cp flag.<programlisting>java -cp `pwd`/lib/*:.:client-1.0.0.jar org.jboss.example.client.Client $1</programlisting></para>
+          <para>If you are using Java 6+ then you can use a wildcard to include all JARs in a directory with the -cp flag.<programlisting>java -cp `pwd`/lib/*:.:client-1.0.0.jar org.jboss.example.client.Client $1</programlisting>This means that all of the classes in our application will be added to the application classloader&apos;s classpath.</para>
         </note>
-        <para>This is all well and good but what happens if we now want to deploy an additional service at runtime? If the new service is packaged in a JAR file then it needs to be visible to a classloader before any of the classes can be loaded.   The trouble is we have already setup the classpath for the application classloader on startup so we cannot easily add the url of the JAR. The same situation applies if the service classes are contained in a directory structure. Unless the top-level directory is located in the current directory (which is on the application classpath) then the classes will not be found by the application classloader.</para>
+        <para>This is all well and good but what happens if we now want to deploy an additional service at runtime? If the new service is packaged in a JAR file then it needs to be visible to a classloader before any of the classes can be loaded.   The trouble is we have already setup the classpath for the application classloader (and external classloader) on startup so we cannot easily add the url of the JAR. The same situation applies if the service classes are contained in a directory structure. Unless the top-level directory is located in the current directory (which is on the application classpath) then the classes will not be found by the application classloader.</para>
         <para>What we need is the ability to create a new classloader that knows the location of the new service&apos;s classes so that we can load them and deploy the service&apos;s beans. JBoss Microcontainer allows us to do this using the &lt;classloader&gt; element in the  deployment descriptor.</para>
-        <para>Also mention the fact that we need to create a new classloader if we want to reload the service after we have recompiled the classes.</para>
+        <para>Also mention the fact that we need to create a new classloader if we want to reload the service after we have recompiled the classes. Creating new classloaders is necessary because we wish to deploy new services or redeploy existing ones at runtime without stopping the server. It is therefore the deployer which is responsible for creating a classloader and in doing so it must also consider what the parent of the newly created classloader should be.</para>
       </section>
     </chapter>
     <chapter>




More information about the jboss-cvs-commits mailing list