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
- Run the unit tests.
- Build a client JAR.
- 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.