Chapter 4. Using Services

The previous chapter guided you through creating, configuring, testing and packaging a service. The next step is to create a client which will perform actual work using the service.
The client in this example uses a Text User Interface (TUI) to accept input from the user and output results. This reduces the size and complexity of the example code.
All of the necessary files are located in the examples/User_Guide/gettingstarted/commandLineClient directory, which follows the Maven Standard Directory Layout, as seen in Example 4.1, “Listing for examples/User_Guide/gettingstarted/commandLineClient Directory”.

Example 4.1. Listing for examples/User_Guide/gettingstarted/commandLineClient Directory

├── pom.xml
├── src
│   ├── main
│   │   ├── assembly
│   │   │   ├── aop.xml
│   │   │   ├── classloader.xml
│   │   │   ├── common.xml
│   │   │   └── pojo.xml
│   │   ├── config
│   │   │   ├── aop-beans.xml
│   │   │   ├── classloader-beans.xml
│   │   │   ├── pojo-beans.xml
│   │   │   └── run.sh
│   │   ├── java
│   │   │   └── org
│   │   │       └── jboss
│   │   │           └── example
│   │   │               └── client
│   │   │                   ├── Client.java
│   │   │                   ├── ConsoleInput.java
│   │   │                   ├── EmbeddedBootstrap.java
│   │   │                   └── UserInterface.java
│   │   └── resources
│   │       └── log4j.properties
│   └── test
│       ├── java
│       │   └── org
│       │       └── jboss
│       │           └── example
│       │               └── client
│       │                   ├── ClientTestCase.java
│       │                   ├── ClientTestSuite.java
│       │                   └── MockUserInterface.java
│       └── resources
│           └── jboss-beans.xml
└── target
    └── classes
        └── log4j.properties
The client consists of three classes and one interface, located in the org/jboss/example/client directory.
UserInterface describes methods that the client calls at run-time to request user input. ConsoleInput is an implementation of UserInterface that creates a TUI which the user uses to interact with the client. The advantage of this design is that you can easily create a Swing implementation of UserInterface at a later date and replace the TUI with a GUI. You can also simulate the data-entry process with a script. Then you can check the behavior of the client automatically using conventional JUnit test cases found in Example 3.2, “Listing of the src/test/java Directory”.
For the build to work you must first build and install auditAspect.jar from the examples/User_Guide/gettingStarted/auditAspect directory using the mvn install command. A number of different client distributions are created, including one based on AOP which relies on auditAspect.jar being available in the local Maven repository.
If you previously typed mvn install from the examples/User_Guide/gettingStarted directory then humanResourcesService.jar and auditAspect.jar have already been built and packaged, along with the client, so this step will not be necessary.
To compile the source code, all of the steps in Procedure 4.1, “Compiling the Source Code” are performed when you issue the mvn package command from the commandLineClient directory.

Procedure 4.1. Compiling the Source Code

  1. Run the unit tests.
  2. Build a client JAR.
  3. Assemble a distribution containing all of the necessary files.
After compiling and packaging the client, the directory structure in the commandLineClient/target directory includes the subdirectories described in Example 4.2, “Subdirectories of the commandLineClient/target Directory”.

Example 4.2. Subdirectories of the commandLineClient/target Directory

client-pojo
used to call the service without AOP.
client-cl
used to demonstrate classloading features.
client-aop
Adding AOP support. See Chapter 5, Adding Behavior with AOP for more details.
Each sub-directory represents a different distribution with all of the shell scripts, JARs, and XML deployment descriptors needed to run the client in different configurations. The rest of this chapter uses the client-pojo distribution found in the client-pojo sub-directory, which is listed in Example 4.3, “Listing of the client-pojo Directory”.

Example 4.3. Listing of the client-pojo Directory

       |-- client-1.0.0.jar
       |-- jboss-beans.xml
       |-- lib
       |   |-- concurrent-1.3.4.jar
       |   |-- humanResourcesService-1.0.0.jar
       |   |-- jboss-common-core-2.0.4.GA.jar
       |   |-- jboss-common-core-2.2.1.GA.jar
       |   |-- jboss-common-logging-log4j-2.0.4.GA.jar
       |   |-- jboss-common-logging-spi-2.0.4.GA.jar
       |   |-- jboss-container-2.0.0.Beta6.jar
       |   |-- jboss-dependency-2.0.0.Beta6.jar
       |   |-- jboss-kernel-2.0.0.Beta6.jar
       |   |-- jbossxb-2.0.0.CR4.jar
       |   |-- log4j-1.2.14.jar
       |   `-- xercesImpl-2.7.1.jar
       `-- run.sh
To run the client, change to the client-pojo directory and type ./run.sh. The Example 4.4, “HRManager Menu Screen” appears.

Example 4.4. HRManager Menu Screen

       Menu:

       d) Deploy Human Resources service
       u) Undeploy Human Resources service

       a) Add employee
       l) List employees
       r) Remove employee
       g) Get a salary
       s) Set a salary
       t) Toggle hiring freeze

       m) Display menu
       p) Print service status
       q) Quit
       >
To select an option, enter the letter shown on the left-hand side and press RETURN. For example to display the menu options enter m followed by RETURN. Entering more than one letter or entering an invalid option results in an error message.

Important

The run.sh script sets up the run-time environment by adding all of the JARs found in the lib/ directory to the classpath using the java.ext.dirs system property. It also adds the current directory and the client-1.0.0.jar using the -cp flag so that the jboss-beans.xml deployment descriptor can be found at run-time along with the org.jboss.example.client.Client class which is called to start the application.

4.1. Bootstrapping the Microcontainer

Before using the client to deploy and call your service, take a closer look at what happened during its construction:
public Client(final boolean useBus) throws Exception {
    this.useBus = useBus;

    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    url = cl.getResource("jboss-beans.xml");

    // Start JBoss Microcontainer
    bootstrap = new EmbeddedBootstrap();
    bootstrap.run();

    kernel = bootstrap.getKernel();
    controller = kernel.getController();
    bus = kernel.getBus();
}

		
		
		

First of all a URL representing the jboss-beans.xml deployment descriptor is created. This is later required so that the XML deployer can deploy and undeploy beans declared in the file. The getResource() method of the application classloader is used because the jboss-beans.xml file is included on the classpath. This is optional; the name and location of the deployment descriptor are unimportant as long as the URL is valid and reachable.
Next an instance of JBoss Microcontainer is created, along with an XML deployer. This process is called bootstrapping and a convenience class called BasicBootstrap is provided as part of the Microcontainer to allow for programmatic configuration. To add an XML deployer, extend BasicBootstrap to create an EmbeddedBootstrap class and override the protected bootstrap() method as follows:
public class EmbeddedBootstrap extends BasicBootstrap {
    protected BasicXMLDeployer deployer;
    public EmbeddedBootstrap() throws Exception {
	super();
    }

    public void bootstrap() throws Throwable {
	super.bootstrap();
	deployer = new BasicXMLDeployer(getKernel());
	Runtime.getRuntime().addShutdownHook(new Shutdown());
    }

    public void deploy(URL url) {
	...
	deployer.deploy(url);
	...
	    }

    public void undeploy(URL url) {
	...
	deployer.undeploy(url);
	...
	    }

    protected class Shutdown extends Thread {
	public void run() {
	    log.info("Shutting down");
	    deployer.shutdown();
	}
    }
}
		
		
		

The shutdown hook ensures that when the JVM exits, all of the beans are undeployed in the correct order. The public deploy/undeploy methods delegate to the BasicXMLDeployer so that beans declared in jboss-beans.xml can be deployed and undeployed.
Finally references to the Microcontainer controller and bus are restored, so you can look up bean references by name and access them directly or indirectly as necessary.