# JBoss Microcontainer 2.0.0 Beta9

## What this Book Covers

This book aims to help you become familiar with JBoss Microcontainer in order that you can use it to develop your own services or applications.

Part I 'Getting Started' introduces the technology and explains how it relates to Java development in general. It then goes on to cover a complete use-case so that you can quickly see how the microcontainer works in real-life.

Part II 'POJO Development' takes a look at the various methods you can use to construct POJOs and wire them together using injection together with other features.

Part III 'AOP Development' goes on to look at how you can add behaviour to your POJOs using aspects and modify the deployment/undeployment process with lifecycle callbacks.

Part IV 'Extending the Microcontainer' shows how you can write your own extensions by creating new dependencies and gives some examples of how this has already been done.

## Getting Started

### Introduction

The Java platform has traditionally been distributed in 3 editions, each providing a different type of runtime environment:

- Java ME (Micro Edition) - Mobile or other embedded devices

- Java SE (Standard Edition) - Desktop machines or servers (typically running 2-tier applications)

- Java EE (Enterprise Edition) - Servers (typically running 3-tier applications)

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 'enterprise services' such as transactions, messaging, and persistence that allow much more robust and scalable 'enterprise applications' 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.

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 'Java Edition' tailored to your requirements.

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.

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't need simply by changing the configuration. You can even use the microcontainer to do this in other environments such as Tomcat and GlassFish since you can plug in different classloading models during the service deployment phase.

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.

In common with other lightweight containers JBoss Microcontainer uses dependency injection to wire individual POJOs together to create services. Configuration is performed using either annotations or XML 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.

### Download and Installing

JBoss Microcontainer 2.0.0 is currently only available as a beta release via Maven2. This means that you need to install and configure Maven before you can begin development. Once this is done then you can create a maven project that depends on the JBoss Microcontainer JARs in order to download and install them into your local maven repository. You can then create an assembly for your final application in order to package the relevant JARs into a distributable format.

The examples created for this User Guide use Maven2 to achieve exactly this so it is highly recommended that you download these first and take a look at how they work.

To build and run the examples you first need to install and configure Maven 2.0.7 available from http://maven.apache.org/

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:

    <settings>
      <profiles>
        <profile>
          <id>jboss.repository</id>
          <activation>
            <property>
              <name>!jboss.repository.off</name>
            </property>
          </activation>
          <repositories>
            <repository>
              <id>snapshots.jboss.org</id>
              <url>http://snapshots.jboss.org/maven2</url>
              <snapshots>
                <enabled>true</enabled>
              </snapshots>
            </repository>
            <repository>
              <id>repository.jboss.org</id>
              <url>http://repository.jboss.org/maven2</url>
              <snapshots>
                <enabled>false</enabled>
              </snapshots>
            </repository>
          </repositories>
          <pluginRepositories>
            <pluginRepository>
              <id>repository.jboss.org</id>
              <url>http://repository.jboss.org/maven2</url>
              <snapshots>
                <enabled>false</enabled>
              </snapshots>
            </pluginRepository>
            <pluginRepository>
              <id>snapshots.jboss.org</id>
              <url>http://snapshots.jboss.org/maven2</url>
              <snapshots>
                <enabled>true</enabled>
              </snapshots>
            </pluginRepository>
          </pluginRepositories>
        </profile>
      </profiles>
    </settings>

This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.

Once you have configured Maven and downloaded the examples then you can go to one of the following subdirectories in the `examples/User_Guide` directory and enter `mvn install` to perform a build:

- gettingStarted - projects for creating and using a service together with AOP

- pojoDevelopment - examples of creating and configuring POJOs using XML and annotations

- aopDevelopment - examples of using AOP to add behaviour to POJOs

- extending - examples of how we created various extensions to the microcontainer by creating new dependencies

Instructions on how to run the individual examples can be found in the corresponding parts of this guide.

### Building services

Before we talk about building services using POJOs it is necessary to define what we mean by these terms.

POJOs

The term POJO is an acronym for Plain Old Java Object and was first coined while Rebecca Parsons, Josh MacKenzie, and Martin Fowler were preparing for a talk at a conference in September 2000. It describes the practice of encoding business logic in regular java objects instead of components such as EJB 2.1 Entity Beans. The benefit of this approach is that you're not required to implement any special interfaces. This not only keeps your code simple but allows it to be used in a wider variety of environments and makes it easy to unit test.

Definition: A POJO declares business methods, which define behaviour, and properties, which represent state. Some properties represent associations to other POJOs.

For experienced developers this should sound familiar as it mimicks almost exactly the proposals set out in the JavaBeans specification. JavaBeans describes a component model for User Interface development emphasizing simplicity and standardized naming conventions for property accessor methods. The idea was that this would allow automatic discovery of an object's properties so that an instance could easily be created and populated with state at runtime. The main use case was creating and configuring visual user interface components such as text boxes, buttons, and tables from within an Integrated Development Environment (IDE).

Definition: A Java Bean is a reusable software component that can be manipulated visually in a builder tool.

Importantly a Java Bean is not required to inherit from any particular base class or interface. Also while Java Beans are primarily targeted at builder tools they are entirely usable by programmers with conventional text editors.

Strictly speaking a Java Bean should include support for events and persistence but in many cases developers choose not to implement these features and simply follow the standardized naming conventions for property accessor methods; i.e. get and set. This 'lightweight' form of Java Bean is commonly referred to as simply a 'bean' and is semantically equivalent to a POJO.

The terms POJO and bean are therefore interchangeable and you will encounter both in the microcontainer documentation and configuration files.

Services

The word 'service' has many definitions in the English language but in the context of developing Java applications it is helpful to define it as follows:

1. A service should perform work that is useful to multiple clients, thereby preventing each client from having to perform the work themselves.

2. A service should have a name that clients can lookup at runtime to gain access. This provides a standard way to access different kinds of services and removes the need for clients to explicitly create them before they can be used.

3. Internal changes to a service should not affect any clients. In practice this means that clients should access a service using a well defined interface so that the implementation can be changed without having to recompile any clients.

Using this definition we can now answer some simple questions:

Q) Is a POJO a service?

A) No, because although it performs work that is useful to multiple clients you cannot access it using a name. Also clients have to explicitly create a POJO themselves either directly using the `new` operator or indirectly using a factory.

Q) Does a class have to implement an interface in order to provide a 'well-defined' interface?

A) Not necessarily. Providing that we don't remove fields or methods from a class, or restrict access to them, we can always change its implementation without needing to recompile any clients. See the section entitled Resolution of Symbolic References from the Java Language Specification for more details.

The 'well-defined' interface in this respect is composed from the original class's fields and methods together with their access modifiers.

Implementing an interface is only necessary if we want to allow a client to choose between alternative implementations. 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.

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.

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.

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 'business-oriented' 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.

#### Creating POJOs

The example that relates to this section can be found in the `examples/User_Guide/gettingStarted/humanResourcesService` directory. The directory layout, as with all of the examples for the User Guide, follows the Maven Standard Directory Layout.

    humanResourcesService/pom.xml
                         /src/main/java
                             /test/java
                             /test/resources

Java source files are located in packages beneath the src/main/java directory:

    org/jboss/example/service/Address.java
                             /Employee.java
                             /HRManager.java

    org/jboss/example/service/util/SalaryStrategy.java
                                  /AgeBasedSalaryStrategy.java
                                  /LocationBasedSalaryStrategy.java

Each of these classes represents a simple POJO that doesn't implement any special interfaces. The most important class is HRManager as this represents the service entry point providing all of the public methods that clients will call.

- addEmployee(Employee employee)

- removeEmployee(Employee employee)

- getEmployee(String firstName, String lastName)

- getEmployees()

- getSalary(Employee employee)

- setSalary(Employee employee, Integer newSalary)

- isHiringFreeze()

- setHiringFreeze(boolean hiringFreeze)

- getSalaryStrategy()

- setSalaryStrategy(SalaryStrategy strategy)

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.

To compile the source code you simply need to enter `mvn compile` from the `humanResourcesService/` directory. This will create a new directory called `target/classes` containing the compiled code. To clean up the project and remove the `target` directory simply enter `mvn clean`.

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.

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

       <bean name="HRService" class="org.jboss.example.service.HRManager"/>

    </deployment>

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.

#### Wiring POJOs together

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?

The answer is to use the XML deployment descriptor again as follows:

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

       <bean name="HRService" class="org.jboss.example.service.HRManager">
         <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property>
       </bean>

       <bean name="AgeBasedSalary"
             class="org.jboss.example.service.util.AgeBasedSalaryStrategy"/>

    </deployment>

We first need to create an instance of our chosen salary strategy implementation by including an additional <bean> 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 `setSalaryStrategy(SalaryStrategy strategy)` 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.

In other words the XML deployment descriptor causes the same sequence of events to occur as if you had written the following code:

    HRManager hrService = new HRManager();
    AgeBasedSalaryStrategy ageBasedSalary = new AgeBasedSalaryStrategy();
    hrService.setSalaryStrategy(ageBasedSalary);

In addition to performing injection via property setter methods JBoss Microcontainer can also perform injection via constructor parameters if necessary. For more details please see the 'Injection' chapter in Part II 'POJO Development'.

Although we can create instances of classes using the <bean> 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.

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 used for. Alternatively a naming convention such as ending each bean name that represents a service entry point with 'Service' can be used instead, e.g. HRService.

#### Configuring a service

Injecting references between POJO instances is one way of configuring a service however we can also inject values into POJO properties. The following deployment descriptor shows how we can configure the HRManager instance to have a hiring freeze and the AgeBasedSalaryStrategy to have new minimum and maximum salary values:

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

       <bean name="HRService" class="org.jboss.example.service.HRManager">
         <property name="hiringFreeze">false</property>
         <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property>
       </bean>

       <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy">
         <property name="minSalary">1000</property> <property name="maxSalary">80000</property>
       </bean>

    </deployment>

As with wiring POJOs together the classes need to have public setter methods for the relevant properties so that values can be injected. For example the HRManager class has a `setHiringFreeze(boolean hiringFreeze)` method and the AgeBasedSalaryStrategy class has `setMinSalary(int minSalary)` and `setMaxSalary(int maxSalary)` methods.

The values in the deployment descriptor are converted from strings into the relevant types (boolean, int etc...) by JavaBean PropertyEditors. A large number of these are provided by default for standard types but you can easily create your own if necessary. See the Properties chapter in Part II 'POJO Development' for more details.

#### Testing a service

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.

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's package name. Any beans found in this file are deployed and can then be accessed using a convenience method called `getBean(String name)`.

You can see examples of these deployment descriptors in the src/test/resources directory:

    org/jboss/example/service/HRManagerTestCase.xml
                             /HRManagerAgeBasedTestCase.xml
                             /HRManagerLocationBasedTestCase.xml

    org/jboss/example/service/util/AgeBasedSalaryTestCase.xml
                                  /LocationBasedSalaryTestCase.xml

The test code is located in the src/test/java directory:

    org/jboss/example/service/HRManagerTestCase.java
                             /HRManagerAgeBasedTestCase.xml
                             /HRManagerLocationBasedTestCase.xml
                             /HRManagerTest.java
                             /HRManagerTestSuite.java

    org/jboss/example/service/util/AgeBasedSalaryTestCase.java
                                  /LocationBasedSalaryTestVase.java
                                  /SalaryStrategyTestSuite.java

The HRManagerTest class extends MicrocontainerTest in order to set up a number of employees to use as the basis for the tests. Individual test cases then subclass this to perform the actual work. You can also see a couple of TestSuite classes that are used to group individual test cases together for convenience.

To run the tests simply enter `mvn test` from the `humanResourcesService/` directory. You should see some DEBUG log output which shows JBoss Microcontainer booting up and deploying beans from the relevant XML file before running each test. At the end of the test it then undeploys the beans and shuts down the microcontainer.

Some of the tests such as HRManagerTestCase, AgeBasedSalaryTestCase and LocationBasedSalaryTestCase simply unit test individual POJOs whilst other tests such as HRManagerAgeBasedTestCase and HRManagerLocationBasedTestCase unit test the whole service consisting of multiple POJOs wired together. Either way the method for conducting the tests remains the same. Thanks to the MicrocontainerTest class it is trivial to set up and conduct comprehensive tests for any part of your code.

Finally note that we didn't unit test the Address or Employee classes here. They were deliberately left out as they only contain trivial logic which is very unlikely to break.

#### Packaging a service

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.

If you do choose to include the deployment descriptor then by convention you should call it `jboss-beans.xml` 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.

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 `target` directory containing all of the compiled classes simply enter `mvn package` from the `humanResourcesService/` directory.

To make the JAR available to other maven projects you then need to enter `mvn install` in order to copy it to your local maven repository.

The final layout of the JAR is as follows:

    org/jboss/example/service/Address.class
                             /Employee.class
                             /HRManager.class
    org/jboss/example/service/util/AgeBasedSalaryStrategy.class
                                  /LocationBasedSalaryStrategy.class
                                  /SalaryStrategy.class
    META-INF/MANIFEST.MF
    META-INF/maven/org.jboss.microcontainer.examples/humanResourcesService/pom.xml
                                                                          /pom.properties

The META-INF/maven directory is automatically produced by maven and is required so that other maven projects can use this JAR as a dependency. If you are not using maven as your build system then you will not have this directory.

### Using services

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.

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.

You will find all of the necessary files in the `examples/User_Guide/gettingstarted/commandLineClient` directory. As with the previous example this follows the Maven Standard Directory Layout:

    commandLineClient/pom.xml
                     /src/main/assembly
                         /main/config
                         /main/java
                         /main/resources
                         /test/java
                         /test/resources

The client consists of 3 classes and 1 interface, located in the `src/main/java` directory:

    org/jboss/example/client/Client.java
                            /ConsoleInput.java
                            /EmbeddedBootstrap.java
                            /UserInterface.java

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 `src/test/java` directory:

    org/jboss/example/client/ClientTestCase.java
                            /ClientTestSuite.java
                            /MockUserInterface.java

To compile the source code, run the unit tests, build a client JAR and assemble a distribution containing all of the necessary files simply type `mvn package` from the `commandLineClient` directory.

For the build to work you must first have built and installed auditAspect.jar from the `examples/User_Guide/gettingStarted/auditAspect` directory using the `mvn install` command. This is because we actually create a number of different client distributions including one based on AOP which relies on auditAspect.jar being available in the local maven repositiory.

If you previously typed `mvn install` from the `examples/User_Guide/gettingStarted` directory then you will have already built and installed humanResourcesService.jar together with auditAspect.jar and the client will have already been packaged so this step will not be necessary.

Once you have successfully compiled and packaged the client you will find the following subdirectories in the `commandLineClient/target` directory:

- client-pojo.dir - used to call the service without any AOP

- client-cl.dir - used to demonstrate classloading features

- client-aop.dir - used in Chapter 5. Adding behaviour through AOP

Each of these represents a different distribution containing all of the shell scripts, JARs, and XML deployment descriptors that we need to run the client in different configurations. For the moment we will use the client-pojo distribution which can be found in the client-pojo.dir subdirectory:

    run.sh
    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

To run the client simply `cd` into client-pojo.dir and type `./run.sh`. You will then be presented with the following menu of options:

To select an option enter the letter shown on the left-hand side and press return. For example to redisplay the menu options enter 'm' 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.

The run.sh script sets up the runtime 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 runtime together with the org.jboss.example.client.Client class which is called to start the application.

#### Bootstrapping the microcontainer

Before we use the client to deploy and call our service, lets 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 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.

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:

    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 is exited all of the beans are undeployed in the correct order. The public deploy/undeploy methods simply delegate to the BasicXMLDeployer so that we can deploy and undeploy beans declared in our jboss-beans.xml file.

Finally we stored references to the microcontainer controller and bus so that we can lookup bean references by name and access them directly or indirectly as necessary.

#### Deploying the service

Once the client has been created we can proceed to deploy the Human Resources service. This is done by entering the 'd' 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.

The microcontainer is able to instantiate the beans as their classes are available in the extension classpath inside the `lib/humanResourcesService.jar` file. We could have equally placed these classes in an exploded directory structure and added this to the application classpath but in general you will package them in a JAR for convenience.

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:

    <?xml version="1.0" encoding="UTF-8"?>
    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

        <bean name="HRService" class="org.jboss.example.service.HRManager">
            <!-- <property name="hiringFreeze">true</property>
            <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> -->
        </bean>

        <!-- <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy">
            <property name="minSalary">1000</property>
            <property name="maxSalary">80000</property>
        </bean>

        <bean name="LocationBasedSalary"
    class="org.jboss.example.service.util.LocationBasedSalaryStrategy">
            <property name="minSalary">2000</property>
            <property name="maxSalary">90000</property>
        </bean> -->

    </deployment>

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.

#### Direct access

If no parameter is given to the `run.sh` 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:

    private HRManager manager;
    ...
    private final static String HRSERVICE = "HRService";

    ...

    void deploy() {
        bootstrap.deploy(url);
        if (!useBus && manager == null) {
            ControllerContext context = controller.getInstalledContext(HRSERVICE);
            if (context != null) { manager = (HRManager) context.getTarget(); }
        }
    }

Rather than immediately looking up a reference to the bean instance we first lookup a reference to a `ControllerContext`. We then obtain a reference to the bean instance from the context using the `getTarget()` method. The reason for this is because the bean can exist in many states within the microcontainer e.g. NOT_INSTALLED, 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.

Now that we have a reference to the bean instance representing our service entry point we can call methods on it to perform work:

    @SuppressWarnings("unchecked")
    Set<Employee> listEmployees() {
        if (useBus)
            ...
        else
            return manager.getEmployees();
    }

The client is said to be accessing the service directly since it'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?

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 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.

The problem is that we cache the reference to the bean instance representing our service entry point 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.

You can test this behaviour for yourself by typing 'u' followed by return to undeploy the current service. You should still be able to access the service from the client even though it is 'undeployed'. Now make some changes to the configuration using the jboss-beans.xml file and deploy it again using the 'd' option (remember to save any changes you make to jboss-beans.xml first). Printing out the status of the service using the 'p' option should allow you to see that the client is still accessing the initial instance of the service that was deployed.

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.

To reliably redeploy the reconfigured service you must therefore shutdown the application completely using the 'q' option and restart it again using the `run.sh` script. For enterprise services such as transactions, messaging and persistance this is perfectly acceptable 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.

#### Indirect access

The `run.sh` script can be called with an optional parameter 'bus' to specify that calls to the Human Resources service should take place using the microcontainer bus:

    ./run.sh bus

Instead of using a direct reference to the bean instance obtained from the microcontainer controller we now 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's behalf.

    private final static String HRSERVICE = "HRService";

    ...

    @SuppressWarnings("unchecked")
    Set<Employee> listEmployees() {
        if (useBus)
            return (Set<Employee>) invoke(HRSERVICE, "getEmployees", new Object[] {}, new String[] {});
        else
            return manager.getEmployees();
    }

    private Object invoke(String serviceName, String methodName, Object[] args, String[] types) {
        Object result = null;
        try {
            result = bus.invoke(serviceName, methodName, args, types);
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return result;
    }

Behind the scenes the bus looks up the reference to the bean instance specified by the bean name and calls the chosen method using reflecton. Since the client never has a direct reference to the bean instance we say that it accesses the service 'indirectly'. 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 for yourself by deploying the service and using the 'p' option to print out the status. Undeploy the service using the 'u' 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 'd' option (remember to save any changes you make to jboss-beans.xml first). Printing out the status again using the 'p' option should reveal that the client is accessing the new service configuration.

As the bus uses reflection to call bean instances it is slower than using direct access. The benefit however is that only the bus has references to the bean instances. 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. This is either because the reduction in performance does not matter if the service is used rarely or the service can be deployed and undeployed together with the relevant applications to keep the runtime environment clean.

#### Dynamic classloading

So far we have been using the extension 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.

    java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1

For convenience the JARs in the lib directory were added to the extenion classloader's classpath using the `java.ext.dirs` system property as this prevents us from having to list the full path to each of the JARs after the -cp flag. Since the extension 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.

If you are using Java 6+ then you can use a wildcard to include all JARs in a directory with the -cp flag.

    java -cp `pwd`/lib/*:.:client-1.0.0.jar org.jboss.example.client.Client $1

This means that all of the classes in our application will be added to the application classloader's classpath and the extension classloader's classpath will retain its default value.

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 its classes can be loaded. The trouble is we have already setup the classpath for the application classloader (and extension 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.

It's also possible that we may wish to redeploy an existing service with changes to some of its classes. Since it is forbidden for an existing classloader to reload classes due to security constraints how can this be done?

What we need is the ability to create a new classloader that knows the location of the new service's classes, or that can load new versions of an existing service's classes, so that we can deploy the service's beans. JBoss Microcontainer allows us to do this using the <classloader> element in the deployment descriptor.

The client-cl distribution in the `commandLineClient/target/client-cl.dir` directory contains the following files that demonstrate how this works:

    run.sh
    client-1.0.0.jar
    jboss-beans.xml
    lib/concurrent-1.3.4.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
    otherLib/humanResourcesService-1.0.0.jar

As you can see the humanResourcesService.jar file has been moved to a new subdirectory called `otherLib`. In this location it is no longer available to either the extension or application classloaders whose classpaths are setup in the `run.sh` script:

    java -Djava.ext.dirs=`pwd`/lib -cp .:client-1.0.0.jar org.jboss.example.client.Client $1

We must therefore create a new classloader during the deployment of the service so that we can load in the service classes and create instances of the beans. You can see how this is done by looking at the contents of the jboss-beans.xml file:

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                  xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                                  xmlns="urn:jboss:bean-deployer:2.0">

      <bean name="URL" class="java.net.URL">
        <constructor>
    <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter>
        </constructor>
      </bean>

      <bean name="customCL" class="java.net.URLClassLoader">
        <constructor>
          <parameter>
            <array>
              <inject bean="URL"/>
            </array>
          </parameter>
        </constructor>
      </bean>

      <bean name="HRService" class="org.jboss.example.service.HRManager">
        <classloader><inject bean="customCL"/></classloader>
        <!-- <property name="hiringFreeze">true</property>
        <property name="salaryStrategy"><inject bean="AgeBasedSalary"/></property> -->
      </bean>

       <!-- <bean name="AgeBasedSalary" class="org.jboss.example.service.util.AgeBasedSalaryStrategy">
        <property name="minSalary">1000</property>
        <property name="maxSalary">80000</property>
      </bean>

      <bean name="LocationBasedSalary" class="org.jboss.example.service.util.LocationBasedSalaryStrategy">
        <property name="minSalary">2000</property>
        <property name="maxSalary">90000</property>
      </bean> -->

    </deployment>

First of all we create an instance of java.net.URL called URL using parameter injection in the constructor to specify the location of the humanResourcesService.jar file on our local filesystem. Then we create an instance of a URLClassLoader by injecting the URL bean into the constructor as the only element in an array. Once this is done then we simply include a <classloader> element in our HRService bean definition and inject the customCL bean. This specifies that the HRManager class needs to be loaded by the customCL classloader.

But how do we know which classloader to use for the other beans in the deployment?

The answer is that all beans in the deployment use the current thread's context classloader. In our case the thread that handles deployment is the main thread of the application which has its context classloader set to the application classloader on startup. If you wish, you can choose to specify a different classloader for the entire deployment using a <classloader> element as follows:

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                  xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                                  xmlns="urn:jboss:bean-deployer:2.0">

      <classloader><inject bean="customCL"/></classloader>

      <bean name="URL" class="java.net.URL">
        <constructor>
    <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter>
        </constructor>
      </bean>

      <bean name="customCL" class="java.net.URLClassLoader">
        <constructor>
          <parameter>
            <array>
              <inject bean="URL"/>
            </array>
          </parameter>
        </constructor>
      </bean>

      ...

    </deployment>

This would be necessary for example if you wished to reconfigure the service by uncommenting the AgeBasedSalary or LocationBasedSalary beans. As you might expect, classloaders specified at the bean level override the deployment level classloader and if you wish to ignore the deployment level classloader altogether, and use the default classloader for a bean, then you can use the <null/> value as follows:

      <bean name="HRService" class="org.jboss.example.service.HRManager">
        <classloader><null/></classloader>
      </bean>

If you decide to create a new classloader for your service using the deployment descriptor then be aware that you may not be able to access classes loaded by it from the application classloader anymore. In our example this means that the client will no longer be able to cache a direct reference to the bean instance when using the microcontainer controller. You can see this for yourself by starting the client using the `run.sh` command and then trying to deploy the service. You should see that a java.lang.NoClassDefFoundError exception is thrown and the application will then exit.

You must therefore use the bus to access the service indirectly and provide access to any classes shared by the client in the application classpath. In our example this means the Address, Employee, and SalaryStrategy classes.

### Adding behaviour with AOP

Object Oriented Programming (OOP) contains many useful techniques for software development including encapsulation, inheritance, and polymorphism but does not solve the problem of how to address logic that is often repeated in many different classes. Examples of this include logging, security, and transactional logic which is traditionally hard-coded into each class making the source code difficult to maintain. We call logic of this nature a 'cross-cutting concern' as it typically applies across class hierarchies.

Aspect Oriented Programming (AOP) provides a solution to this by allowing cross-cutting concerns to be applied to classes after they have been compiled. This keeps the source code free of logic which is not central to the main purpose of the class and aids maintenance. The way it is done varies depending on the AOP implementation. Typically if a class implements an interface then all method calls to an instance of the class first pass through a proxy that implements the same interface and adds in the required behaviour. Alternatively, if an interface is not used, then the java bytecode of the compiled class is modified so that the original methods are renamed and replaced by methods that implement the cross-cutting logic. These new methods then call the original methods after the cross-cutting logic has been executed. The same result can be achieved by modifying the bytecode to create a subclass of the original class that overrides its methods. The overriden methods then execute the cross-cutting logic before calling the corresponding methods of the super class.

JBoss AOP is a framework for Aspect-Oriented Programming that allows you to create cross-cutting concerns using conventional java classes and methods. In AOP terminology each concern is represented by an aspect that you implement using a simple POJO. Behaviour is provided by methods within the aspect called advices that follow certain rules for their parameter and return types together with any exceptions that they throw. Other than this you are free to use conventional object-oriented notions such as inheritance, encapsulation, and composition in order to make your cross-cutting concerns as maintainable as possible. Aspects are applied to code using an expression language that allows you to specify which constructors, methods and even fields to target. This means that you can quickly change the behaviour of a number of classes simply by editing a configuration file.

In this chapter we are going to look at using JBoss AOP together with the microcontainer to create and apply an auditing aspect to the Human Resources Service. We could choose to place auditing code within the HRManager class but it would detract from the main purpose of the class and add unnecessary complexity. The design of the aspect will ensure that it can also be used with other classes if our requirements change at a later date.

We shall also look at how AOP can be used to apply additional behaviour during the deployment phase. Specifically we will show how you can create and bind a proxy to a bean instance into a basic JNDI service so that you can access it using a JNDI lookup instead of the microcontainer controller.

#### Creating an aspect

The `examples/User_Guide/gettingStarted/auditAspect` directory contains all the files you need to create the aspect.

    auditAspect/pom.xml
               /src/main/java/org/jboss/example/aspect/AuditAspect.java

As you can see from the source code below all we need is a simple POJO.

    public class AuditAspect {

        private String logDir;
        private BufferedWriter out;

        public AuditAspect() {
            logDir = System.getProperty("user.dir") + "/log";

            File directory = new File(logDir);
            if (!directory.exists()) {
                directory.mkdir();
            }
        }

        public Object audit(ConstructorInvocation inv) throws Throwable {
            SimpleDateFormat formatter = new SimpleDateFormat("ddMMyyyy-kkmmss");
            Calendar now = Calendar.getInstance();
            String filename = "auditLog-" + formatter.format(now.getTime());

            File auditLog = new File(logDir + "/" + filename);
            auditLog.createNewFile();
            out = new BufferedWriter(new FileWriter(auditLog));
            return inv.invokeNext();
        }

        public Object audit(MethodInvocation inv) throws Throwable {
            String name = inv.getMethod().getName();
            Object[] args = inv.getArguments();
            Object retVal = inv.invokeNext();

            StringBuffer buffer = new StringBuffer();
            for (int i=0; i < args.length; i++) {
                if (i > 0) {
                    buffer.append(", ");
                }
                buffer.append(args[i].toString());
            }

            if (out != null) {
                out.write("Method: " + name);
                if (buffer.length() > 0) {
                    out.write(" Args: " + buffer.toString());
                }
                if (retVal != null) {
                     out.write(" Return: " + retVal.toString());
                }
                out.write("\n");
                out.flush();
            }
            return retVal;
        }
    }

The constructor checks for the presence of a `log` directory in the current working directory and creates one if not found. After this we define an advice that will be called whenever the constructor of our target class is called. The purpose of this is to create a new log file within the log directory so that we can record method calls made on different instances of our target class in separate files. Finally we define an advice that will apply to each method call made on the target class. Here we store the method name and arguments together with the return value so that we can construct an audit record and write it to the current log file. Notice how each advice calls `inv.invokeNext()`. This is required in order to call the next advice, if more than one cross-cutting concern has been applied, or to call the target constructor/method.

Each advice is implemented using a method that takes an invocation object as a parameter, throws Throwable and returns Object. This is necessary as we do not know at design time which constructors or methods our advices will be applied to so the types must be as generic as possible. For more information on creating aspects and advices together with additional examples of how to apply them to various classes please consult the JBoss AOP project documentation.

To compile the class and create an auditAspect.jar file that can be used by other examples simply type `mvn install` from the auditAspect directory.

#### Configuring the microcontainer

Before we can apply the audit aspect to our service we must first add a number of JARs to the extension classpath. These can be found in the `lib` subdirectory of the client-aop distribution located in the `examples/User_Guide/gettingStarted/commandLineClient/target/client-aop.dir` directory:

    run.sh
    client-1.0.0.jar
    jboss-beans.xml
    lib/auditAspect-1.0.0.jar
       /concurrent-1.3.4.jar
       /humanResourcesService-1.0.0.jar
       /javassist-3.6.0.GA.jar
       /jboss-aop-2.0.0.beta1.jar
       /jboss-aop-mc-int-2.0.0.Beta6.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
       /trove-2.1.1.jar
       /xercesImpl-2.7.1.jar

First of all we need to include the `auditAspect` jar as we need to create an instance of our aspect at runtime in order to execute the logic. We then need to include the jar file for JBoss AOP (`jboss-aop`) together with its dependencies; `javassist` and `trove`. Finally we need to add the`jboss-aop-mc-int` jar as this contains an XML schema definition that allows us to define aspects inside our XML deployment descriptor. It also contains integration code to create dependencies between normal beans and aspect beans within the microcontainer so that we can add behaviour during the deployment and undeployment phases.

Since we are using Maven2 to assemble the client-aop distribution we can easily add these JAR files by declaring the appropriate dependencies in our `pom.xml` file and creating a valid assembly descriptor. If you are using Ant to perform your build then you will need to do this in a different way.

#### Applying an aspect

Now that we have a valid distribution containing everything we need we can configure our jboss-beans.xml file to apply the audit aspect. This can be found in the `examples/User_Guide/gettingStarted/commandLineClient/target/client-aop.dir` directory:

    <?xml version="1.0" encoding="UTF-8"?>

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

        <bean name="AspectManager" class="org.jboss.aop.AspectManager">
            <constructor factoryClass="org.jboss.aop.AspectManager"
                                 factoryMethod="instance"/>
        </bean>

        <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
                           name="AuditAspect" class="org.jboss.example.aspect.AuditAspect"
                           method="audit" pointcut="execution(public org.jboss.example.service.HRManager->new(..)) OR                                        execution(public * org.jboss.example.service.HRManager->*(..))">
        </aop:aspect>

        ...

    </deployment>

Before we can apply our aspect to any classes we need to create an instance of org.jboss.aop.AspectManager using a <bean> element. We use a factory method instead of calling a conventional constructor as we only want one instance of the AspectManager in the JVM at runtime i.e. it is a singleton.

Next we create an instance of our aspect called AuditAspect using the <aop:aspect> element. This looks much like the <bean> element as it has `name` and `class` attributes that you can use in the same way. However it also has `method` and `pointcut` attributes that you can use to apply or 'bind' an advice within the aspect to constructors and methods within other classes. We use these attributes to bind the audit advice to all public constructors and methods within the HRManager class. We only need to specify one method called audit as we have overloaded this method within our AuditAspect class with different parameters. JBoss AOP knows at runtime which one to select based on whether a constructor or method invocation is being made.

This additional configuration is all we need to apply the audit aspect at runtime and add auditing behaviour to the Human Resources service. You can test this out for yourself by running the client using the `run.sh` script. A `log` directory will be created on startup alongside the `lib` directory as the AuditAspect bean is created by the microcontainer. Each deployment of the Human Resources service will then cause a new log file to appear within the `log` directory containing a record of any calls made from the client to the service:

    log/auditLog-28112007-163902
       /auditLog-28112007-164055
       /auditLog-28112007-164108

The audit records inside the log files will look something like this:

    Method: getEmployees Return: []
    Method: addEmployee Args: (Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860) Return: true
    Method: getSalary Args: (Santa Claus, null - Birth date unknown) Return: 10000
    Method: getEmployees Return: [(Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860)]
    Method: isHiringFreeze Return: false
    Method: getEmployees Return: [(Santa Claus, 1 Reindeer Avenue, Lapland City - 25/12/1860)]
    Method: getSalaryStrategy

If you wish to remove the auditing behaviour then you can simply comment out the relevant fragments of XML in the deployment descriptor and restart the application.

The order of deployment for aspects declared in this way relative to normal beans matters in the deployment descriptor. Specifically each aspect must be declared before the beans that it applies to so that the microcontainer deploys them in that order. This is because the microcontainer may need to alter the bytecode of the normal bean class in order to add the cross-cutting logic before it creates an instance and stores a reference to it in the controller. If a normal bean instance has already been created then this is not possible.

#### Lifecycle callbacks

In addition to applying aspects to beans that we instantiate using the microcontainer we can also add behaviour during the deployment and undeployment process. As you may recall from the Direct access section of Chapter 4, a bean goes through several different states as it is deployed. These include:

- NOT_INSTALLED - the deployment descriptor containing the bean has been parsed along with any annotations on the bean itself.

- DESCRIBED - any dependencies created by AOP have been added to the bean and custom annotations have been processed.

- INSTANTIATED - an instance of the bean has been created.

- CONFIGURED - properties have been injected into the bean along with any references to other beans.

- CREATE - the create method, if defined on the bean, has been called.

- START - the start method, if defined on the bean, has been called.

- INSTALLED - any custom install actions that were defined in the deployment descriptor have been executed and the bean is ready to access.

The CREATE and START states are included in order to allow services that used to be implemented as MBeans in JBoss AS 3.x and 4.x to function correctly when implemented as beans in JBoss AS 5.x. If you do not define any corresponding create/start methods in your bean then it will simply pass straight through these states.

Together these states represent the bean's lifecycle and using an additional set of <aop> elements you can define a number of callbacks to be applied to any point:

    <aop:lifecycle-describe> - applied when entering/leaving the DESCRIBED state
    <aop:lifecycle-instantiate> - applied when entering/leaving the INSTANTIATED state
    <aop:lifecycle-configure> - applied when entering/leaving the CONFIGURED state
    <aop:lifecycle-create> - applied when entering/leaving the CREATE state
    <aop:lifecycle-start> - applied when entering/leaving the START state
    <aop:lifecycle-install> - applied when entering/leaving the INSTALLED state

Just like the <bean> element and the <aop:aspect> element the <aop:lifecycle-> elements contain `name` and `class` attributes. These allow the microcontainer to create an instance of the callback class and give it a name so that it can be used as beans enter/leave the relevant state during deployment and undeployment. You can specify which beans are affected by the callback using the `classes` attribute:

    <aop:lifecycle-install xmlns:aop="urn:jboss:aop-beans:1.0"
        name="InstallAdvice"
        class="org.jboss.test.microcontainer.support.LifecycleCallback"
        classes="@org.jboss.test.microcontainer.support.Install">
    </aop:lifecycle-install>

Here we have specified that additional logic in the LifecycleCallback class should be applied to any bean classes that are annotated with @org.jboss.test.microcontainer.support.Install before they enter and after they leave the INSTALLED state.

In order for the callback class to work it must contain `install` and `uninstall` methods that take ControllerContext as a parameter:

    import org.jboss.dependency.spi.ControllerContext;

    public class LifecycleCallback {

        public void install(ControllerContext ctx) {
            System.out.println("Bean " + ctx.getName() + " is being installed";
        }

        public void uninstall(ControllerContext ctx) {
            System.out.println("Bean " + ctx.getName() + " is being uninstalled";
        }
    }

The install method will be called during the bean's deployment and the uninstall method during its undeployment.

Although we are adding behaviour to the deployment and undeployment process using callbacks we are not actually using AOP to achieve this. The reason we have included them in this section, and the reason why they are part of the aop XML schema, is that they use the pointcut expression functionality of JBoss AOP to determine which bean classes they should apply to. We have already shown how the `classes` attribute allows you to write a shorthand pointcut expression to target annotated bean classes. Later in Part III - AOP Development we will show how it is possible to use regular pointcut expressions to target classes in a much more powerful way.

#### Adding service lookup through JNDI

Until now we have looked up references to bean instances representing services through the microcontainer controller. Whilst there is nothing wrong with this it is not ideal since we must first have a reference to the microcontainer kernel before we can access the controller:

    private HRManager manager;

    private EmbeddedBootstrap bootstrap;
    private Kernel kernel;
    private KernelController controller;

    private final static String HRSERVICE = "HRService";

    ...

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

    kernel = bootstrap.getKernel();
    controller = kernel.getController();

    ...

    ControllerContext context = controller.getInstalledContext(HRSERVICE);
    if (context != null) { manager = (HRManager) context.getTarget(); }

Handing out kernel references to every client that looks up a service represents a significant risk as it provides wide-spread access to the microcontainer configuration. It would be better to apply the ServiceLocator pattern and have a class that performs lookups on behalf of the clients. Better still we could pass the bean references, together with their names, to the ServiceLocator at deployment time using a lifecycle callback so that it could look them up without knowing about the microcontainer at all. Undeployment would subsequently remove the bean references from the ServiceLocator to prevent further lookups.

While it would not be too difficult to write our own ServiceLocator implementation we can save time by integrating an existing one such as JBoss Naming Service (JBoss NS). This has the additional benefit of complying to the Java Naming and Directory Interface (JNDI) specification. JNDI enables clients to access different, possibly multiple, naming services using a common API.

All that we need to do is create an instance of JBoss NS using the microcontainer and then add a lifecycle callback to perform the binding and unbinding of our bean references during deployment/undeployment. We can then mark the bean classes that we wish to bind references for using annotations and find them at runtime using the shorthand pointcut expression as shown earlier.

### Advanced deployment

Mention the need for a main deployer and explain how we add various deployers to this.

#### Deployment stages and actions

Give example of using aspectized bean deployer and show how it's the same as the BasicXMLDeployer.

#### Changing the descriptor file format

Give an example where we move the jboss-beans.xml file out of the META-INF directory and change the location of the classes.

#### Changing the archive structure

Give an example of changing the jboss-beans.xml file for a jboss-beans.properties file.

#### Changing the classloader

#### Adding a deployment action

## POJO Development

### Introduction

In Part I of this guide we looked at a complete use-case showing how to develop a service using POJOs and access it from one or more clients. This should have given you a good overview of how the microcontainer is intended to be used in real applications. In Part II we look more closely at the various features available for creating POJOs, wiring them together, deploying them into the runtime environment, and managing their dependencies. With this knowledge you should be able to create flexible and reusable services that can be integrated together to provide a custom runtime suited to your needs.

### Running the examples

You can find examples of how to use each of the features described here in the `examples/User_Guide/pojoDevelopment` directory:

    alias
    annotations
    autowiring
    classloader
    collections
    constructor
    demand
    factory
    injection
    installation
    javabeans
    lifecycle
    locator
    properties
    simple
    spring
    supply

To build these simply `cd` to this directory and enter `mvn package`. A `target` directory will then be created in each subdirectory as follows:

    target/archive-tmp
          /classes
          /<exampleName>-1.0.0.jar
          /<exampleName>-dist.dir

The contents of the <exampleName>-dist.dir will be similar for each example:

    <exampleName>-1.0.0.jar
    log4j.properties
    lib/concurrent-1.3.4.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

If you previously used the examples from Part I you will notice that we no longer have a `run.sh` script. Instead we have made <exampleName>-1.0.0.jar executable. This means that it contains a META-INF/MANIFEST.MF file with Main-Class and Class-Path attributes:

    Main-Class: org.jboss.kernel.plugins.bootstrap.standalone.StandaloneBootstrap
    Class-Path: .
                lib/jboss-common-core-2.0.4.GA.jar
                lib/junit-3.8.1.jar
                l ib/jboss-common-logging-spi-2.0.4.GA.jar
                lib/xercesImpl-2.7.1.jar
                lib /ant-1.6.5.jar
                lib/jboss-container-2.0.0.Beta6.jar
                lib/jboss-common-c ore-2.2.1.GA.jar
                lib/dtdparser121-1.2.1.jar
                lib/jbossxb-2.0.0.CR4.jar
                lib/jboss-aop-2.0.0.beta1.jar
                lib/jboss-common-logging-log4j-2.0.4.G A.jar
                lib/activation-1.0.2.jar
                lib/jboss-test-1.0.4.GA.jar
                lib/xml-ap is-2.7.1.jar
                lib/concurrent-1.3.4.jar
                lib/webdavlib-2.0.jar
                lib/jboss -profiler-jvmti-1.0.0.CR5.jar
                lib/jboss-kernel-2.0.0.Beta6.jar
                lib/jb oss-managed-2.0.0.Beta6.jar
                lib/jboss-metatype-2.0.0.Beta6.jar
                lib/co mmons-httpclient-2.0.2.jar
                lib/javassist-3.6.0.GA.jar
                lib/jboss-loggi ng-spi-2.0.3.GA.jar
                lib/log4j-1.2.14.jar
                lib/jboss-dependency-2.0.0.B eta6.jar
                lib/ant-junit-1.6.5.jar

Certain JAR files included in the Class-Path attribute are not present in the `lib` directory. This is because the maven-jar-plugin is creating the Class-Path value using its internal dependency resolution mechanism and including JARs that are not actually needed at runtime. This is the fault of the pom.xml descriptors in projects such as jbossxb, which the microcontainer depends on, that do not currently mark their dependencies as optional. For clarity we have prevented all of these JARs appearing in the lib directory of the distribution by explicitly listing only those that are required in the `examples/User_Guide/pojoDevelopment/`dist.xml`` file which is passed to the maven-assembly-plugin.

Once we have fixed the pom.xml files in the projects that the microcontainer depends on then this filtering will no longer be necessary.

The Main-Class attribute contains the name of a StandaloneBootstrap class that is provided with the microcontainer. This class is very similar to the EmbeddedBootstrap class that we used in Part I with the addition of a main() method so that it can be called from the command line:

    public class StandaloneBootstrap extends BasicBootstrap
    {
       protected BasicXMLDeployer deployer;
       protected String[] args;

       public static void main(String[] args) throws Exception {
          StandaloneBootstrap bootstrap = new StandaloneBootstrap(args);
          bootstrap.run();
       }

       public StandaloneBootstrap(String[] args) throws Exception {
          super();
          this.args = args;
       }

       public void bootstrap() throws Throwable {
          super.bootstrap();

          deployer = new BasicXMLDeployer(getKernel());

          Runtime.getRuntime().addShutdownHook(new Shutdown());

          ClassLoader cl = Thread.currentThread().getContextClassLoader();
          for (Enumeration e = cl.getResources(StandaloneKernelConstants.DEPLOYMENT_XML_NAME); e.hasMoreElements(); ) {
             URL url = (URL) e.nextElement();
             deploy(url);
          }
          for (Enumeration e = cl.getResources("META-INF/" + StandaloneKernelConstants.DEPLOYMENT_XML_NAME); e.hasMoreElements(); ) {
             URL url = (URL) e.nextElement();
             deploy(url);
          }

          // Validate that everything is ok
          deployer.validate();
       }

       protected void deploy(URL url) throws Throwable {
          deployer.deploy(url);
       }

       protected void undeploy(URL url) {
          try {
             deployer.undeploy(url);
          }  catch (Throwable t) {
             log.warn("Error during undeployment: " + url, t);
          }
       }

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

The bootstrap() method also includes code to automatically scan the classpath for files called jboss-beans.xml (the value of StandaloneKernelConstants.DEPLOYMENT_XML_NAME) that may or may not reside in a META-INF directory. If any such files are found then their URLs are passed to the BasicXMLDeployer to deploy any beans declared inside. In our examples we place a jboss-beans.xml file into the META-INF directory of our <exampleName>-1.0.0.jar so that it can be found in this way.

To run any of the examples simply `cd` to the relevant `target/<exampleName>-dist.dir` directory and execute the JAR file using the `java -jar <exampleName>-1.0.0.jar` command, replacing <exampleName> with the name of the example you are running, .e.g `java -jar constructor-1.0.0.jar`

Running an example causes the following sequence of events to occur:

1. The <exampleName>-1.0.0.jar is executed.

2. The StandaloneBootstrap class defined in the Main-Class attribute of the META-INF/MANIFEST.MF file within the JAR is run which bootstraps the microcontainer and searches the classpath for files called jboss-beans.xml.

3. The META-INF/jboss-beans.xml file in the <exampleName>-1.0.0.jar is found and the beans declared within it are deployed.

4. The main() method of the StandaloneBootstrap class ends and the JVM shuts down undeploying the beans in reverse order.

If you would like to use the StandaloneBootstrap class within your own applications to deploy beans on startup then you can do so as follows:

    import org.jboss.kernel.plugins.bootstrap.standalone.StandaloneBootstrap;

    public class MyApp {
        public static void main(String[] args) throws Exception
        {
            StandaloneBootstrap.main(args);
            // your application code...
        }
    }

Because the deploy() and undeploy() methods of the StandaloneBootstrap are protected you will not be able to call them from your application after the initial startup. If you wish to deploy and undeploy beans at runtime then the EmbeddedBootstrap class may be a better choice. Alternatively you are free to create your own bootstrap class that uses BasicBootstrap and BasicXMLDeployer to provide whatever functionality you need.

### Configuring POJOs

In accordance with modern development methods JBoss Microcontainer supports POJO configuration via annotations and/or deployment descriptors. The decision to use one or the other depends on what you are trying to achieve. If there is a sensible default configuration for your POJOs then it may be worthwhile defining this using annotations so that users do not have to maintain a separate deployment descriptor. Since annotations are overriden by deployment descriptors at runtime it is always possible for users to change the default configuration using a descriptor if necessary.

Annotations are overriden by deployment descriptors at runtime.

If there is no sensible default configuration then it may be worthwhile using a deployment descriptor instead of annotations. This keeps the source code free of potentially redundant information and allows for easy customization since the initial deployment descriptor acts as a template for further changes.

Sometimes a mixture of annotations and a deployment descriptor is best. It's up to you to discover what makes most sense for your particular situation.

#### Using annotations

With the notable exception of defining classloaders nearly all of the microcontainer features can be used by adding annotations to your POJO classes.

We are not able to define classloaders using annotations for the simple reason that in order to read any annotations we must first load the class. Once the class is loaded we cannot change its classloader so a classloader annotation would be useless.

The microcontainer annotations live in the `org.jboss.beans.metadata.api.annotations` package and to use them you need Java 1.5 or above.

If you are using Java 1.4 or below then JBoss Microcontainer allows you to define a subset of the annotations in the XML deployment descriptor. The caveat is that these apply to bean instances instead of bean classes. As with normal annotations you are free to add as many as necessary at a single point. However you must always specify the fully-qualified class name since there is no way to 'import' packages in XML. Currently you can place annotations inside the following elements:

- <deployment> -all beans in the deployment inherit this annotation

      <deployment name="SimpleDeployment" xmlns="urn:jboss:bean-deployer:2.0">
          <annotation>@org.jboss.test.TestAnnotation</annotation>
      </deployment>

- <bean>

      <bean name="example" class="org.jboss.test.Example">
          <annotation>@org.jboss.test.TestAnnotation1</annotation>
          <annotation>@org.jboss.test.TestAnnotation2</annotation>
      </bean>

- <constructor>

      <bean name="example" class="org.jboss.test.Example">
          <constructor>
              <annotation>@org.jboss.test.TestAnnotation</annotation>
          </constructor>
      </bean>

- <create>, <start>, <stop>, <destroy>

      <bean name="example" class="org.jboss.test.Example">
          <create>
              <annotation>@org.jboss.test.TestAnnotation</annotation>
          </create>
      </bean>

- <install>, <uninstall>

      <bean name="example" class="org.jboss.test.Example">
          <install method="someMethod">
              <annotation>@org.jboss.test.TestAnnotation</annotation>
          </install>
      </bean>

- <incallback>, <uncallback>

- <value>

      <bean name="example" class="org.jboss.test.Example">
          <property name="PropertyName">
              <annotation>@org.jboss.test.TestAnnotation</annotation>
              <value>123</value>
          </property>
      </bean>

Annotations declared in XML apply to bean instances instead of bean classes.

Examples of how to use both normal and XML annotations will be given in the following sections.

#### Writing deployment descriptors

Deployment descriptors externalize the configuration of POJOs into one or more files that are separate from the source code. This means that changes can be made without having to recompile any classes. The usual way to define a deployment descriptor is using the bean-deployer XML schema whose root element is <deployment>. This is used to group multiple beans together so that they are deployed as a unit:

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_2_0.xsd"
                        xmlns="urn:jboss:bean-deployer:2.0">

        <!-- Bean definitions -->

    </deployment>

The bean definitions are created using <bean> elements that each describe a single POJO instance. Each bean is given a name so that it can be referenced elsewhere in the deployment descriptor or looked up by a client at runtime.

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_2_0.xsd"
                        xmlns="urn:jboss:bean-deployer:2.0">

        <bean name="Person" class="org.jboss.example.microcontainer.PersonBean"/>

        <bean name="Address" class="org.jboss.example.microcontainer.AddressBean"/>

    </deployment>

The name of the file containing these elements can be anything you like providing that a deployer can access it and parse the contents correctly. By convention it is called jboss-beans.xml as anything that ends in -beans.xml is found by default using the FileStructure deployer.

Although deployment descriptors are usually created using the bean-deployer XML schema it is also possible to use other XML schemas or even Java properties as shown in the following sections.

#### Using JavaBean XML

Together with the bean-deployer XML schema the microcontainer also contains a javabean XML schema. This is a lightweight version of bean-deployer that allows for the construction and configuration of JavaBeans without any advanced features like bean injection, callbacks or dependencies. It is intended to be used in situations where the microcontainer has been customised to remove all of the advanced functionality so that it can be bootstrapped in very small runtime environments.

Construction of POJOs is performed using either a normal constructor or a static factory method. In either case constructor or method parameters can be added as necessary:

- Default constructor

      <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean"/>

- Contructor with parameters

      <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean">
          <constructor>
              <property name="ABoolean">true</property>
              <property name="ACharacter">x</property>
              <property name="AShort">123</property>
          </constructor>
      </javabean>

- Static factory method

      <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean">
          <constructor factoryClass="org.jboss.test.javabean.support.SimpleBeanFactory"
                       factoryMethod="newInstance"/>
      </javabean>

- Static factory method with parameters

      <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean">
          <constructor factoryClass="org.jboss.test.javabean.support.SimpleBeanFactory"
                       factoryMethod="newInstance">
              <property name="AString">StringValue</property>
              <property name="AByte">12</property>
          </constructor>
      </javabean>

JavaBean declarations do not include a `name` attribute which means that you cannot inject references into other JavaBeans or lookup a reference to a JavaBean instance from a client at runtime.

Once a JavaBean has been constructed then simple injection of property values is possible using the <property> element:

    <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean">
        <property name="ADouble">3.14e12</property>
        <property name="ADate">Jan 01 00:00:00 CET 2001</property>
        <property name="ABigDecimal">12e4</property>
        <property name="ABigInteger">123456</property>
        <property name="abyte">12</property>
    </javabean>

As with properties defined using the bean-deployer XML schema the string values are converted into objects of the correct type using JavaBean PropertyEditors. For cases where the type is ambiguous, e.g. when defining numbers, you can specify the required type by including a `class` attribute:

    <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.javabean.support.SimpleBean">
        <property name="ANumber" class="java.lang.Long">12345</property>
    </javabean>

Beans created using the bean-deployer XML schema can include JavaBeans created using the javabean XML schema instead of string values. This provides a simple way to inject objects composed of multiple values into a bean property without having to write a complicated property editor:

    <bean name="example" class="org.jboss.acme.Example">
        <property name="myProperty">
            <javabean xmlns="urn:jboss:javabean:1.0" class="org.jboss.test.javabean.support.SimpleBean">
                <property name="ADate">Jan 01 00:00:00 CET 2001</property>
                <property name="ABigDecimal">12e4</property>
            </javabean>
        </property>
    </bean>

#### Using Spring XML

Spring like JBoss Microcontainer allows POJOs to be created and configured using an XML schema. As the microcontainer largely supports the same set of features as Spring it is possible to use the spring-beans schema to define beans instead of the bean-deployer schema. This makes migrating services built and tested using Spring to JBoss Microcontainer very straightforward.

To define beans using the spring-beans schema you need to include `spring-int.jar` on the microcontainer classpath. You can then create a deployment descriptor containing a <beans> element at the root instead of the usual <deployment> element:

    <beans xmlns="urn:jboss:spring-beans:2.0">
        <bean id="testBean" class="org.jboss.test.spring.support.SimpleBean">
            <constructor-arg index="2">
                <value>SpringBean</value>
            </constructor-arg>
            <constructor-arg index="0">
                <value>1</value>
            </constructor-arg>
            <constructor-arg index="1">
                <value>3.14159</value>
            </constructor-arg>

            <property name="mylist">
                <list value-type="java.lang.String">
                    <value>onel</value>
                    <value>twol</value>
                    <value>threel</value>
                </list>
            </property>

            <property name="myset">
                <set value-type="java.lang.String">
                    <value>ones</value>
                    <value>twos</value>
                    <value>ones</value>
                </set>
            </property>

            <property name="mymap">
                <map key-type="java.lang.String">
                    <entry>
                        <key>
                            <value>test_key</value>
                        </key>
                        <value type="java.lang.String">myvalue</value>
                    </entry>
                </map>
            </property>
        </bean>
    </beans>

The namespace declaration `xmlns="urn:jboss:spring-beans:2.0"` tells the microcontainer that it should interpret the XML according to the spring-bean schema.

You can even mix beans declared using the bean-deployer schema with those declared using the spring-beans schema just like we did with the javabean schema. All that you need to do is include the correct namespace declarations in the relevant elements:

- JBoss Microcontainer deployment containing Spring defined beans

      <deployment xmlns="urn:jboss:bean-deployer:2.0">

          <bean name="oldBean" class="org.jboss.test.spring.support.OldBean">
              <property name="testBean">
                  <inject/>
              </property>
          </bean>

          <bean xmlns="urn:jboss:spring-beans:2.0" id="testBean" class="org.jboss.test.TestBean">
              <property name="mylist">
                  <list value-type="java.lang.String">
                      <value>onel</value>
                      <value>twol</value>
                      <value>threel</value>
                  </list>
              </property>
          </bean>

      </deployment>

- Spring defined deployment containing JBoss Microcontainer beans

      <beans xmlns="urn:jboss:spring-beans:2.0">

          <bean id="testBean" class="org.jboss.test.spring.support.SimpleBean">
              <property name="refBean">
                  <ref bean="oldBean"/>
              </property>
          </bean>

          <bean xmlns="urn:jboss:bean-deployer:2.0" name="oldBean" class="org.jboss.test.spring.support.OldBean">
              <property name="myString">I'm an old bean</property>
          </bean>

      </beans>

Adding `spring-int.jar` to the microcontainer classpath simply adds the ability to define beans using the spring-beans XML schema. It does not integrate JBoss Microcontainer with Spring libraries.

#### Using Java Properties

Using XML schemas to create deployment descriptors provides us wth a powerful way to express complex configuration information. However the XML parsers that are needed to interpret this information are often large in size which doesn't help when bootstrapping the microcontainer in small runtime environments. For this reason you can also choose to create deployment descriptors using Java properties.

### Creating POJOs

#### Defining classloaders

In order to create POJO instances we must first load the corresponding POJO classes into the JVM using a classloader. JBoss Microcontainer does this by using the classloader associated with the current thread of execution, i.e. the thread context classloader. But what do we mean by the current thread of execution and who sets its context classloader?

In all of our examples so far we have created applications that only use a single thread. This is the 'primordial' thread created by the main() function:

    public static void main(String[] args) {}

As the only thread in the application (other than the garbage collecton thread which is created for every Java application) this executes all of the code including calling the deploy() method of our BasicXMLDeployer:

    public class BasicXMLDeployer extends BasicKernelDeployer
    {
        ...
        public KernelDeployment deploy(final URL url) throws Throwable
       {
           ...

            long start = System.currentTimeMillis();

            Unmarshaller unmarshaller = factory.newUnmarshaller();
            KernelDeployment deployment = (KernelDeployment) unmarshaller.unmarshal(url.toString(), resolver);
             if (deployment == null)
                throw new RuntimeException("The xml " + url + " is not well formed!");
            deployment.setName(url.toString());

            if (trace)
            {
                long now = System.currentTimeMillis();
                log.trace("Parsing " + url + " took " + (now-start) + " milliseconds");
            }

            deploy(deployment);

            if (trace)
            {
                long now = System.currentTimeMillis();
                log.trace("Deploying " + url + " took " + (now-start) + " milliseconds");
            }

            return deployment;
        }

        ...
    }

The deploy() method takes a URL representing the location of an XML deployment descriptor and passes it as a string to an unmarshaller. The unmarshaller parses the XML, converts it into an object representation called a KernelDeployment and sets its name. The KernelDeployment object is then passed to the deploy() method of the superclass BasicKernelDeployer. This iterates through all of the beans in the deployment creating a context for each one which it subsequently passes to the contoller's install() method to peform the deployment. The controller then performs actions on each context to take the bean from one state to another: NOT_INSTALLED, DESCRIBED, CONFIGURED, INSTANTIATED, CREATE, START, INSTALLED. Once a bean reaches the INSTALLED state then it's considered to be deployed.

During the deployment process, as the controller performs the Instantiate action, the thread context classloader is used to load the bean's class into the JVM. As all of the controller code is executed by the thread that calls controller.install() we refer to this as the current thread of execution.

Therefore when using the BasicXMLDeployer the classloader used to load bean classes is retrieved from the thread that calls the BasicXMLDeployer's deploy() method as this goes on to call controller.install() which subsequently executes the Instantiate action. For all of our examples this is the primordial thread whose context classloader is set on startup to the classloader that loaded the application, i.e. the application classloader. This means that in our examples the microcontainer can load any bean classes present on the application, extension or boot classpaths.

What happens though if we create our own threads in the application and use these to call the deploy() method of our BasicXMLDeployer?

If you create a thread then by default its context classloader will be set to the parent thread's context classloader. As any hierarchy of threads is ultimately rooted at the primordial thread this means that by default they will all use the application classloader. To change this you simply need to call setContextClassLoader() on a thread at runtime. This is typically done on the current thread using `Thread.currentThread().setContextClassloader()`.

If you choose not to use the BasicXMLDeployer and instead use the equivalent aspectized deployer then the classloader used to load bean classes is taken from the thread that calls the process() method of the MainDeployer. This is because the MainDeployer process() method iterates through all of the registered deployers calling their process() methods which in turn call controller.install() to perform the deployment.

Now that we know the default classloader comes from the current thread of execution, which if not set explicitly is set on startup to be the application classloader, how can we change it to load bean classes from other locations?

If you are using the BasicXMLDeployer or its equivalent aspectized deployer then you can define classloaders for entire deployments or individual beans by including <classloader> elements within the XML deployment descriptor. To specify a different classloader for all the beans in a deployment you need to include a <classloader> element above all of the <bean> elements:

    <deployment>
        <classloader><inject bean="deploymentCL"/></classloader>

        <bean name="Bean1" ... >
            ...
        </bean>

        <bean name="Bean2" ... >
            ...
        </bean>

    </deployment>

If instead you wish to override either the default classloader or a deployment classloader for a particular bean then you need to include a <classloader> element within the <bean> definition itself:

    <deployment>
        <classloader><inject bean="deploymentCL"/></classloader>

        <bean name="Bean1" ... >
            <classloader><inject bean="beanCL"/></classloader>
            ...
        </bean>

        <bean name="Bean2" ... >
            ...
        </bean>

    </deployment>

Finally you can choose to use the default classloader for a bean instead of the deployment classloader, if one is defined, by including a <classloader> element with a </null> value:

    <deployment>
        <classloader><inject bean="deploymentCL"/></classloader>

        <bean name="Bean1" ... >
            <classloader><inject bean="beanCL"/></classloader>
            ...
        </bean>

        <bean name="Bean2" ... >
            <classloader></null></classloader>
            ...
        </bean>

    </deployment>

The classloader beans that you inject must be deployed in the runtime environment before bean classes can be loaded. Typically this is done by also declaring them in the XML deployment descriptor:

    <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd"
                xmlns="urn:jboss:bean-deployer:2.0">

        <bean name="URL" class="java.net.URL">
            <constructor>
           <parameter>file:/Users/newtonm/jbossmc/microcontainer/trunk/docs/examples/User_Guide/gettingStarted/commandLineClient/target/client-cl.dir/otherLib/humanResourcesService-1.0.0.jar</parameter>
            </constructor>
        </bean>

        <bean name="customCL" class="java.net.URLClassLoader">
            <constructor>
                <parameter>
                    <array>
                        <inject bean="URL"/>
                    </array>
                </parameter>
            </constructor>
        </bean>

        <bean name="HRService" class="org.jboss.example.service.HRManager">
            <classloader><inject bean="customCL"/></classloader>
            ...
    </bean>

If a classloader is not available for a bean when an attempt is made to deploy it then the bean will remain in a pre INSTANTIATED state. Once the classloader is deployed then the bean will automatically continue to deploy. This means that you can define classloaders in the deployment descriptor after beans that depend on them and everything will deploy as expected.

User defined classloaders are detected by the microcontainer during the deployment process as the controller performs the Instantiate action. They are used instead of the default classloader by calling setContextClassLoader() on the current thread. In this way they can be subsequently retrieved by code that loads the bean class using Thread.currentThread().getContextClassLoader(). After the bean class has been loaded the default classloader is put back by calling setContexClassLoader() again.

#### Calling constructors

Creating POJO instances is performed either by calling a constructor or using a factory method. The <constructor> element is used in both cases and parameters can be passed if necessary using nested <parameter> elements. Annotations also exist for either case with parameter values represented as annotations of the constructor parameters themselves.

At present it is not possible to create a POJO instance only using annotations. This is because classes are not automatically loaded and scanned whenever they are added to the classpath. Doing so would significantly reduce the performance of the deployment process as all classes would need to be loaded, even if they were not yet required. Instead you must always define beans using a deployment descriptor as this tells the microcontainer which classes to load. These classes are subsequently scanned for annotations such as @Constructor and @Factory to discover how to create instances.

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean"/>

- Default constructor

      @Constructor
      public TestConstructorBean() {
       ...
      }

      <bean name="Test" class="org.jboss.example.constructor.TestConstructorBean"/>

- Constructor with parameters

      @Constructor
      public TestConstructorBean(@StringValue("this is a test contructor") String testString, @StringValue("25") int testNumber) {
       ...
      }

      <bean name="Test" class="org.jboss.example.constructor.TestConstructorBean">
          <constructor>
              <parameter>this is a test constructor</parameter>
              <parameter>25</parameter>
          </constructor>
      </bean>

- Choosing between two constructors with the same number of parameters

      public TestConstructorBean(String testString, int testNumber) {
          ...
      }

      @Constructor
      public TestConstructorBean(@StringValue("this is a test constructor") String testString, @StringValue(value="25", type="long") long testNumber) {
          ...
      }

      <bean name="Test" class="org.jboss.example.constructor.TestConstructorBean">
          <constructor>
              <parameter>this is a test constructor</parameter>
              <parameter class="long">25</parameter>
          </constructor>
      </bean>

  You only need to include the `class` attribute on enough parameters to resolve the ambiguity.

You can also specify javabeans as parameters if required using the @JavaBeanValue annotation or <javabean> element. In this particular case the annotation is not very useful as it can only call the default constructor of the javabean class to create an instance. If you want to use a different constructor or inject properties then you should use the XML element instead.

    @Constructor
    public TestConstructorBean(@StringValue("this is a test constructor") String testString, @JavaBeanValue("org.jboss.test.Person") Person testPerson) {
        ...
    }

    <bean name="Test" class="org.jboss.example.constructor.TestConstructorBean">
        <constructor>
            <parameter>this is a test constructor</parameter>
            <parameter>
                <javabean xmlns="urn:jboss:javabean:2.0" class="org.jboss.test.Person">
                    <constructor>
                        <property name="age">21</property>
                    </constructor>
                    <property name="firstName">Mark</property>
                    <property name="lastName">Newton</property>
                </javabean>
            </parameter>
        </constructor>
    </bean>

Finally you can inject references to other beans or their properties into constructor parameters giving you complete control of the construction of your POJOs.

    @Constructor
    public TestConstructorBean(@Inject(bean="TestPerson") Person testPerson, @Inject(bean="TestAddress", property="street") String street) {
        ...
    }

    <bean name="Test" class="org.jboss.example.constructor.TestConstructorBean">
        <constructor>
            <parameter>
                <inject bean="TestPerson"/>
            </parameter>
            <parameter>
                <inject bean="TestAddress" property="street"/>
            </parameter>
        </constructor>
    </bean>

#### Using factories

If you have a number of classes that share the same interface then you may want to use a factory to create your POJO instances. JBoss Microcontainer provides support for static or non-static factory methods which can also take parameters if necessary.

- Static factory method

      @Factory (factoryClass="org.jboss.example.MyFactory",
                factoryMethod="newInstance")
      public class SimpleBean {
         ...
      }

      <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
          <constructor factoryClass="org.jboss.example.MyFactory"
                       factoryMethod="newInstance"/>
      </bean>

- Static factory method with parameters

      @Factory (factoryClass="org.jboss.example.MyFactory",
                factoryMethod="newInstance",
                parameters={@Value(string=@StringValue("a string")),@Value(string=@StringValue("7"))})
      public class SimpleBean {
         ...
      }

      <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
          <constructor factoryClass="org.jboss.example.MyFactory"
                       factoryMethod="newInstance">
              <parameter>a string</parameter>
              <parameter>7</parameter>
          </constructor>
      </bean>

- Non-static factory method

      @Factory (factory=@Value(javabean=@JavaBeanValue("org.jboss.example.MyOtherFactory")),
                factoryMethod="createBean")
      public class SimpleBean {
          ...
      }

      <bean name="MyOtherFactory" class="org.jboss.example.MyOtherFactory"/>

      <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
          <constructor factoryMethod="createBean">
              <factory bean="MyOtherFactory"/>
          </constructor>
      </bean>

- Non-static factory method with parameters

      @Factory (factory=@Value(javabean=@JavaBeanValue("org.jboss.example.MyOtherFactory")),
                factoryMethod="createBean",
                parameters={@Value(string=@StringValue("a string")),@Value(string=@StringValue("7"))})
      public class SimpleBean {
          ...
      }

      <bean name="MyOtherFactory" class="org.jboss.example.MyOtherFactory"/>

      <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
          <constructor factoryMethod="createBean">
              <factory bean="MyOtherFactory"/>
              <parameter>a string</parameter>
              <parameter>7</parameter>
          </constructor>
      </bean>

For the special case where a bean implements its own static factory method in order to create itself then you can also use a shorthand notation:

- Bean implementing its own static factory method

      public class SimpleBean {

          @FactoryMethod
          public static newInstance(@StringValue("a string") String name, @StringValue("5") int level) {
              ...
          }
      }

      <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
          <constructor factoryMethod="newInstance">
              <parameter>a string</parameter>
              <parameter>5</parameter>
          </constructor>
      </bean>

  Note that the @FactoryMethod annotation doesn't have a parameter attribute as the method parameters themselves are annotated.

Factory method parameters can also be configured using JavaBeans and injected bean references if necessary just like constructor parameters.

#### Creating bean aliases

By default each bean declared in the deployment descriptor has a unique name that is used to inject it into other beans or to provide a reference to clients at runtime. Sometimes however it is useful to define additional names or aliases. This can be done using the @Aliases annotation or <alias> XML element. System property replacement is used by default to change the value of the alias at runtime but you can disable this if required.

- Defining extra bean names

      @Aliases({"MyAlias", "Test: ${test.name}"})
      public class SimpleBean {
          ...
      }

      <bean name="MyBean" class="org.acme.SimpleBean">
          <alias>MyAlias</alias>
          <alias>Test: ${test.name}</alias>
      </bean>

- Disabling System property replacement

      @Aliases({"MyAlias", "Test: ${test.name}"} replace="false")
      public class SimpleBean {
          ...
      }

      <bean name="MyBean" class="org.acme.SimpleBean">
          <alias>MyAlias</alias>
          <alias replace="false">Test: ${test.name}</alias>
      </bean>

The type of an alias doesn't have to be a string. If you want to choose a different type then you can specify a `class` attribute in the <alias> XML element. At present you cannot do this using the @Aliases annotation.

- Choosing a different alias type

      <bean name="MyBean" class="org.acme.SimpleBean">
          <alias class="java.lang.Integer">12345</alias>
      </bean>

Sometimes you may wish to define an alias for a bean after it has been deployed. This can be done using the standalone <alias> element in the deployment descriptor. There is no equivalent annotation in this case as there is no sensible place to put it.

- Defining a standalone alias

      <deployment name="FirstDeployment" xmlns="urn:jboss:bean-deployer:2.0">

          <bean name="Bean1" class="java.lang.Object"/>
          <bean name="Bean2" class="java.lang.Object"/>

      </deployment>

      <deployment name="SecondDeployment" xmlns="urn:jboss:bean-deployer:2.0">

          <bean name="Xyz1" class="java.lang.Object">
              <property name="locker1"><inject name="Lock1"></property>
              <property name="locker2"><inject name="Lock2"></property>
          </bean>

          <alias name="Bean1">Lock1</alias>
          <alias name="Bean2">Lock2</alias>

      </deployment>

Standalone aliases behave just like normal beans with respect to dependencies. Specifically they won't be deployed until the beans that they represent have been deployed first. Likewise when a bean is undeployed then any corresponding standalone aliases are undeployed first.

Furthermore if any beans depend on a standalone alias then they will not be deployed until the alias is deployed first. Similarly undeploying a standalone alias will cause all dependent beans to be undeployed, regardless of whether the bean that it represents remains deployed.

### Injecting properties

#### Using values

Once a POJO instance has been created then it can be configured by injecting property values. Like most other features this can be done using either annotations or a deployment descriptor. For each property that you wish to inject the bean must define an appropriate setter method for the microcontainer to call.

    public class PropertiesBean {

        public void setTitle(@StringValue("JBoss Microcontainer") String title) {
            ...
       }

        public void setLink(@StringValue("http://www.jboss.org") URL link) {
            ...
        }

        public void setNumber(@StringValue("4") int number) {
            ...
        }
    }

    <bean name="PropertiesBean" class="org.jboss.example.microcontainer.properties.PropertiesBean">
        <property name="title">JBoss Microcontainer</property>
        <property name="link">http://www.jboss.org</property>
        <property name="number">4</property>
    </bean>

As you have probably noticed we are required to enter all of our values as strings since we are dealing with text files. These strings are converted into objects of the correct type using JavaBean PropertyEditors. If the property takes an interface or abstract class then you can pass a specific implementation using a `type` or `class` attribute depending on whether you're using annotations or XML.

    public class PropertiesBean {
        public void setNumber(@StringValue(value="4", type="java.lang.Long") Number number) {
            ...
       }
    }

    <bean name="PropertiesBean" class="org.jboss.example.microcontainer.properties.PropertiesBean">
        <property name="number" class="java.lang.Long">4</property>
    </bean>

Sometimes you may want to pass in a value that isn't of the same type as the property but can be progressed into it. Progression is typically used for converting numbers from one type to another, e.g. Short to Int or Float to Double. JBoss Microcontainer by default will automatically perform progression using a `SimpleProgressionConverter` implementation.

    <bean name="SimpleBean" class="org.jboss.test.SimpleBean">
        <property name="anInt">
            <javabean xmlns="urn:jboss:javabean:2.0" class="java.lang.Double">
                <constructor>
                    <property name="aDouble">123.456</property>
                </constructor>
            </javabean>
        </property>
        <property name="aShort">
            <javabean xmlns="urn:jboss:javabean:2.0" class="java.lang.Float">
                <constructor>
                    <property name="aFloat">987.6543</property>
                </constructor>
            </javabean>
        </property>
        <property name="aFloat">
            <javabean xmlns="urn:jboss:javabean:2.0" class="java.lang.Integer">
                <constructor>
                    <property name="anInt">314159</property>
                </constructor>
            </javabean>
        </property>
    </bean>

You can replace the default progression converter implementation with one of your own by setting the `org.jboss.reflect.plugins.progressionConverter` system property using a fully-qualified class name. If you want to prevent progression from occuring altogether then you can use the `NullProgressionConverter` which is also provided.

    -Dorg.jboss.reflect.plugins.progressionConverter=org.jboss.reflect.plugins.NullProgressionConvertor

If you want to use a null value then you need to use the @NullValue annotation or <null/> element. This is so we can differentiate it from the string 'null'.

    public void setTitle(@NullValue String title) {
        ...
    }

    <bean name="PropertiesBean" class="org.jboss.example.microcontainer.properties.PropertiesBean">
        <property name="title"><null/></property>
    </bean>

Similarly if you want to refer to the current object then you should use the @ThisValue annotation or <this/> element.

    public void setObject(@ThisValue Object target) {
        ...
    }

    <bean name="PropertiesBean" class="org.jboss.example.microcontainer.properties.PropertiesBean">
        <property name="target"><this/></property>
    </bean>

Property values can also be defined using a longer form of XML if you prefer.

    <bean name="PropertiesBean" class="org.jboss.example.microcontainer.properties.PropertiesBean">
        <property name="number">
            <value class="java.lang.Long">4</value>
        </property>
    </bean>

This is primarily used when configuring values representing collections such as lists, sets and arrays. Elements of a collection are defined by listing annotations or nesting <value> elements as follows:

    @CollectionValue(elementClass="java.lang.String",
                     {@Value(string=@StringValue("string1")),
                      @Value(string=@StringValue("string2")),
                      @Value(string=@StringValue("string3")),
                      @Value(string=@StringValue("string4"))})
    public void setCollection(Collection collection) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="collection">
            <collection elementClass="java.lang.String">
                <value>string1</value>
                <value>string2</value>
                <value>string3</value>
                <value>string4</value>
           </collection>
        </property>
    </bean>

The `elementClass` attribute specifies the default class for the values. This can be overriden for individual values using the `type` or `class` attributes.

    @CollectionValue(elementClass="java.lang.String",
                     {@Value(string=@StringValue("string1")),
                      @Value(string=@StringValue("string2")),
                      @Value(string=@StringValue(value="3.0", type="java.lang.Float")),
                      @Value(string=@StringValue(value="4", type="java.lang.Integer"))})
    public void setCollection(Collection collection) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="collection">
            <collection elementClass="java.lang.String">
                <value>string1</value>
                <value>string2</value>
                <value class="java.lang.Float">3.0</value>
                <value class="java.lang.Integer">4</value>
           </collection>
        </property>
    </bean>

The type of each value must be specified using either the `elementClass` or `type/class` attribute in order for the collection to be created.

Lists, sets and arrays take the same form as the collection annotation and XML element.

    @ListValue(elementClass="java.lang.String",
               {@Value(string=@StringValue("my first string")),
                @Value(string=@StringValue("my second string"))})
    public void setList(List list) {
        ...
    }

    @SetValue(elementClass="java.lang.Integer",
              {@Value(string=@StringValue("50")),
               @Value(string=@StringValue("55"))})
    public void setSet(Set set) {
        ...
    }

    @ArrayValue(elementClass="java.lang.Float",
                {@Value(string=@StringValue("1.0")),
                 @Value(string=@StringValue("2.0"))})
    public void setArray(Object[] array) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="list">
            <list elementClass="java.lang.String">
                <value>my first string</value>
                <value>my second string</value>
            </list>
        </property>

        <property name="set">
            <set elementClass="java.lang.Integer">
                <value>50</value>
                <value>55</value>
            </set>
        </property>

        <property name="array">
            <array elementClass="java.lang.Float">
                <value>1.0</value>
                <value>2.0</value>
            </array>
        </array>
    </bean>

They can even be nested within one another if required.

    @ListValue(elementClass="java.lang.String",
               {@Value(string=@StringValue("my first string")),
                @Value(string=@SetValue(elementClass="java.lang.Integer",
                                        {@Value(string=@StringValue("1")),
                                         @Value(string=@StringValue="2"))})
                      )})
    public void setList(List list) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="list">
            <list elementClass="java.lang.String">
                <value>my first string</value>
                <value>
                    <set elementClass="java.lang.Integer">
                        <value>1</value>
                        <value>2</value>
                    </set>
                </value>
            </list>
        </property>
    </bean>

Maps can also be created using multiple entries of key/value pairs. As we now have two types to consider we must use the `keyClass` and `valueClass` attributes to specify the default classes for each entry. Again these can be overriden for individual entries if necessary.

    @MapValue(keyClass="java.lang.String",
              valueClass="java.lang.String",
              {@EntryValue(key=@Value(string=@StringValue("foo.bar.key")),
                           value=@Value(string=@StringValue("QWERT"))),
               @EntryValue(key=@Value(string=@StringValue("xyz.key")),
                           value=@Value(string=@StringValue("QWERTY")))
              })
    public void setMap(Map<String, String> map) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="map">
            <map keyClass="java.lang.String" valueClass="java.lang.String">
                <entry>
                    <key>foo.bar.key</key>
                    <value>QWERT</value>
                </entry>
                <entry>
                    <key>xyz.key</key>
                    <value>QWERTY</value>
                </entry>
            </map>
        </property>
    </bean>

So far we have defined collections, lists, sets, arrays and maps but all of these have multiple implementations, e.g. java.util.ArrayList, java.util.LinkedList, so which are we using at runtime? By default JBoss Microcontainer will look for an existing instance using the corresponding getter method for the property. If one is found then it is used. If not then the type of the property is analysed and providing that it represents a class (not an interface) then this is used to create a new instance. Failing that a default instance will be created as follows:

- Collection - java.util.ArrayList

- List - java.util.ArrayList

- Set - java.util.HashSet

- Array - java.lang.Object[]

- Map - java.util.HashMap

If you want to override this behaviour and specify your own class then you can simply add a `clazz` attribute to your annotation or `class` attribute to your XML element containing the fully-qualified class name. This causes the microcontainer to create a new instance using the specified class.

    @SetValue(clazz="java.util.TreeSet",
              elementClass="java.lang.Integer",
              {@Value(string=@StringValue("50")),
               @Value(string=@StringValue("55"))})
    public void setSet(Set set) {
        ...
    }

    <bean name="SimpleBean"
     class="org.jboss.example.SimpleBean">
        <property name="set">
            <set class="java.util.TreeSet" elementClass="java.lang.Integer">
                <value>50</value>
                <value>55</value>
            </set>
        </property>
    </bean>

If you don't specify a `clazz``/class` attribute but you want to ensure that a new instance is created then you can prevent the microcontainer from looking for a existing instance by specifying a `preinstantiate` attribute in the <property> element. Currently this cannot be achieved using annotations.

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <property name="list" preinstantiate="false">
            <list elementClass="java.lang.String">
                <value>string1</value>
                <value>string2</value>
            </list>
        </property>
    </bean>

If you want to define a `clazz``/class` attribute for an array then you must use the following syntax:

`[L`<fully-qualified class name>`;`

e.g. an array of strings - [Ljava.lang.String;

or an array of integers - [Ljava.lang.Integer;

#### Calling methods

Using PropertyEditors to create instances of objects from strings is fine in many situations but sometimes you need to inject a return value from a method call. As the method is responsible for creating the value we refer to it as a value factory. Hence the @ValueFactory annotation or <value-factory> element can be used in place of @StringValue or <value> to call a method and inject the returned value during deployment.

    @ValueFactory(bean="SimpleBean",
                  method="getFullName")
    public void setName(String name) {
        ...
    }

    <bean name="PropHolder" class="org.jboss.test.kernel.config.support.PropHolder">
        <property name="name">
            <value-factory bean="SimpleBean" method="getFullName"/>
        </property>
    </bean>

If you need to pass any parameters to the method then you can use multiple @Parameter annotations or nested <parameter> elements.

    @ValueFactory(bean="SimpleBean",
                  method="getFullName",
                  parameters="{@Parameter(string=@StringValue("Bob")),
                               @Parameter(string=@StringValue("Smith"))}")
    public void setName(String name) {
        ...
    }

    <bean name="PropHolder" class="org.jboss.test.kernel.config.support.PropHolder">
        <property name="name">
            <value-factory bean="SimpleBean" method="getFullName">
                <parameter>Bob</parameter>
                <parameter>Smith</parameter>
            </value-factory>
        </property>
    </bean>

Alternatively if only one parameter is required then you can use the `parameter` attribute to create a shorthand version. However this only works for values that can be created from strings.

    @ValueFactory(bean="SimpleBean",
                  method="getFullName",
                  parameter="@Parameter(string=@StringValue("Bob"))")
    public void setName(String name) {
        ...
    }

    <bean name="PropHolder" class="org.jboss.test.kernel.config.support.PropHolder">
        <property name="name">
            <value-factory bean="SimpleBean" method="getFullName" parameter="Bob"/>
        </property>
    </bean>

It is also possible to specify a default value to use in case the method returns null. This is done using the `defaultValue`/`default` attribute which like the `parameter` attribute only accepts values created using strings.

    @ValueFactory(bean="SimpleBean",
                  method="getFullName",
                  defaultValue="Mark Newton")
    public void setName(String name) {
        ...
    }

    <bean name="PropHolder" class="org.jboss.test.kernel.config.support.PropHolder">
        <property name="name">
            <value-factory bean="SimpleBean" method="getFullName" default="Mark Newton"/>
        </property>
    </bean>

#### Using bean references

Injecting string-based properties or the return values of method calls into individual beans allows us to perform simple configurations. To create more complex configurations we need to wire beans together by injecting references using the @Inject annotation or <inject> element.

    @Inject(bean = "Name1")
    public void setSimpleBean(SimpleBean bean) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.test.SimpleBean">
        <property name="simpleBean">
            <inject bean="Name1"/>
        </property>
    </bean>

Bean injections can be used anywhere a string value is used but you must ensure that the type of bean being injected is compatible with the type of property being set. It is also possible to inject a property from one bean into another using the `property` attribute.

    @Inject(bean = "Name1", property="age")
    public void setAge(Integer age) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.test.SimpleBean">
        <property name="age">
            <inject bean="Name1" property="age"/>
        </property>
    </bean>

Although injection is simple to use it provides a very powerful way to create arbitrary relationships between POJO instances. The dependencies that are formed by these relationships are discussed in the next chapter 'Defining Dependencies'.

Sometimes you may wish to declare a bean simply so that you can inject it into a single property. In this case you can replace the <inject> element with the bean declaration itself to reduce the amount of XML required. This is not possible using annotations as there is no annotation to declare a bean.

    <bean name="SimpleBean" class="org.jboss.test.SimpleBean">
        <property name="testBean">
            <bean="TestBean" class="org.jboss.test.TestBean">
                <property name="age">25</property>
            </bean>
        </property>
    </bean>

#### Injecting context information

You may recall that inside the microcontainer each bean is represented by a context which holds amongst other things the bean's current state. This context information can be injected into bean properties or constructor/factory-method parameters using the @Inject annotation or <inject> element together with a `fromContext` attribute.

    @Inject(bean="otherBean",
            fromContext="beanInfo")
    public void setBeanInfo(BeanInfo beanInfo) {
        ...
    }

    <bean name="sndBean" class="org.jboss.test.NameAwareBean">
        <property name="beaninfo">
            <inject bean="otherBean" fromContext="beaninfo"/>
        </property>
    </bean>

If you want to inject information about the current bean's context then you can simply omit the `bean` attribute.

    @Inject(fromContext="beanInfo")
    public void setBeanInfo(BeanInfo beanInfo) {
        ...
    }

    <bean name="sndBean" class="org.jboss.test.NameAwareBean">
        <property name="beaninfo">
            <inject fromContext="beaninfo"/>
        </property>
    </bean>

The `fromContext` attribute can take the following values:

- name - the name of the bean

- aliases - a list of the bean's other names

- metadata - information about the bean from annotations or deployment descriptors

- beaninfo - information about the bean from the bean class

- scope - the microcontainer scope that the bean belongs to

- id - the internal id of the bean within the microcontainer

- context - the bean context

All context information is wrapped into unmodifiable objects to prevent the user from changing anything outside of the microcontainer's control.

#### Auto-wiring

Having to write large amounts of configuration information just to wire together sometimes trivial beans can often be frustrating. For this reason JBoss Microcontainer provides the ability to autowire beans. Auto-wiring means that a bean's properties or constructor/factory-method parameters are set by automatically searching for matching beans. The benefit is that you don't have to specify the names of the beans to inject yourself but the drawback is that this only works reliably for small environments. If you have an environment where more than one bean matches the property or parameter being set then it becomes unclear from the configuration information which one will be chosen during deployment.

To use auto-wiring you simply need to specify an @Inject annotation or <inject> element without a `bean` attribute for the parameter or property that you wish to set.

    @Inject
    public class Example(ThreadPool pool) {
        ...
    }

    <bean name="paramInj" class="com.acme.Example">
        <constructor>
            <parameter name="threadPool"><inject/></parameter>
        </constructor>
    </bean>

    @Inject
    public void setThreadPool(ThreadPool pool) {
        ...
    }

    <bean name="propInj" class="com.acme.Example">
        <property name="threadPool"><inject/></property>
    </bean>

By default the microcontainer will search for a bean whose class matches that of the parameter/property. However you can change this behaviour when auto-wiring properties so that the microcontainer searches for a bean whose name matches the property name. This is done using the `type` attribute of the <inject> element.

    @Inject(type="ByName")
    public void setThreadPool(ThreadPool pool) {
        ...
    }

    <bean name="propInj" class="com.acme.Example">
        <property name="threadPool"><inject type="ByName"/></property>
    </bean>

If no match is found then by default the deployment will fail but for certain properties it may be acceptable for injection to occur after deployment. In these cases you can specify that a property should be set using a callback mechanism whenever a suitable bean becomes available. This is done using the `option` attribute.

    @Inject(type="ByName", option="Callback")
    public void setThreadPool(ThreadPool pool) {
        ...
    }

    <bean name="propInj" class="com.acme.Example">
        <property name="threadPool"><inject type="ByName" option="Callback"/></property>
    </bean>

Sometimes you may want to prevent a bean from being injected automatically using auto-wiring. In these situations you can set its `autowire-candidate` attribute to false so that it's not included in the search for matching beans. This is not currently possible using annotations as there is no annotation to declare a bean.

    <bean name="ignored" class="com.acme.Example" autowire-candidate="false" />

### Defining dependencies

#### POJO dependencies

Dependencies between beans (POJO instances) are created when they are wired together through the use of the @Inject annotation or <inject> element. Specifically a bean which has another bean injected into it is said to be dependent on the other bean. For example here we have a Person bean that is dependent on an Address bean.

    public class Person {
        @Inject(bean="AddressBean")
        public void setAddress(Address address) {
            ...
        }
    }

    <bean name="Person" class="org.jboss.test.Person">
        <property name="address">
            <inject bean="AddressBean"/>
        </property>
    </bean>

The reason for the dependency is because the address property of the Person bean cannot be configured until the Address bean has been deployed. Internally JBoss Microcontainer enforces this by moving each bean through a series of states during deployment. Consequently the Person bean will be prevented from moving to the CONFIGURED state until the Address bean has reached the INSTALLED state representing a deployed bean.

By default there are 8 states that a bean can be in during deployment and undeployment:

- NOT_INSTALLED - Metadata describing the bean has been parsed from annotations or a deployment descriptor.

- PRE_INSTALL - the scope of the bean within the microcontainer has been discovered and classloading dependencies have been resolved.

- DESCRIBED - Any AOP dependencies have been added.

- INSTANTIATED -All dependencies have been resolved to construct the bean. These include; a classloader exists, the class can be found, a constructor or factory method can be found and any parameter injections can be resolved.

- CONFIGURED - All the property injections can be resolved. This includes any injections within collections.

- CREATE - All the beans metioned in the @Depends annotation or <depends> element have reached the CREATE state including any parameter injections in the create method.

- START - All the beans metioned in the @Depends annotation or <depends> element have reached the START state including any parameter injections in the start method.

- INSTALLED - Any deployment actions have been processed and the bean has been added to the list of items that the controller supplies.

You may notice that we refer to injections being resolved in the above list. This is a shorthand way of saying that an injected bean has reached a certain state. In our simple example we can say that the injected Address bean has been resolved when it reaches the INSTALLED state. If necessary you can change the state that an injected bean must reach before being considered resolved by using the `dependentState`/`state` attribute.

    public class Person {
        @Inject(bean="OtherBean",
                dependentState="Instantiated")
        public void setAddress(Address address) {
            ...
        }
    }

    <bean name="Person" class="org.jboss.test.Person">
        <property name="address">
            <inject bean="Address" state="Instantiated"/>
        </property>
    </bean>

Here we are saying the Address bean needs to reach the INSTANTIATED state before the Person bean can use it to configure the address property and thus move to the CONFIGURED state. Be aware that setting the state value to `Described` in this case would not be appropriate since we must first have an instance of the Address bean before we can inject a reference to it into another bean.

The following six values can be used for the `dependentState`/`state` attribute to control injection. If no value is specified then by default the Installed state is used.

- Described

- Instantiated

- Configured

- Create

- Start

- Installed

The ability to control when injection occurs is especially useful when dealing with circular dependencies. A circular dependency happens when one bean depends on another which in turn depends on the first bean:

    <bean name="Circular1" class="org.jboss.example.InjectionBean">
        <constructor>
            <parameter>Circular1</parameter>
        </constructor>

        <property name="other">
            <inject bean="Circular2"/>
        </property>
    </bean>

    <bean name="Circular2" class="org.jboss.example.InjectionBean">
        <constructor>
            <parameter>Circular2</parameter>
        </constructor>

        <property name="other">
            <inject bean="Circular1"/>
        </property>
    </bean>

In this configuration the microcontainer is unable to deploy either bean since each one is waiting in the INSTANTIATED state waiting for the other to reach the INSTALLED state. To solve this we can use the `state` attribute to specify that Circular1 can be injected into Circular2 as soon as it reaches the INSTANTIATED state.

    <bean name="Circular1" class="org.jboss.example.InjectionBean">
        <constructor>
            <parameter>Circular1</parameter>
        </constructor>

        <property name="other">
            <inject bean="Circular2"/>
        </property>
    </bean>

    <bean name="Circular2" class="org.jboss.example.InjectionBean">
        <constructor>
            <parameter>Circular2</parameter>
        </constructor>

        <property name="other">
            <inject bean="Circular1" state="Instantiated"/>
        </property>
    </bean>

Circular2 can thus progress to the INSTALLED state whereupon Circular1 will inject it into its `other` property and continue deploying.

#### Supply and Demand

Sometimes dependencies may exist between beans that are not wired together using injections. One example would be a bean representing a service that requires a transaction manager to be present in JNDI before it can start. In these situations we can use a @Demand annotation or <demand> element to specify that we need another bean to be deployed before we can reach a certain state.

    @Demands(@Demand("TransactionManager"))
    public class Example {
        ...
    }

    <bean name="TransactionManager" class="com.acme.TransactionManager"/>

    <bean name="Name2" class="com.acme.Example">
        <demand>TransactionManager</demand>
    </bean>

By default the bean declaring the demand will wait until the beans it requires have been deployed before it moves to the INSTANTIATED state. However you can change this using the `whenRequired`/`state` attribute to specify a different state that can only be reached once all the beans listed as demands have been deployed.

    @Demands(@Demand("TransactionManager", whenRequired="Start"))
    public class Example {
        ...
    }

    <bean name="TransactionManager" class="com.acme.TransactionManager"/>

    <bean name="Name2" class="com.acme.Example">
        <demand state="Start">TransactionManager</demand>
    </bean>

Here we are stating that the TransactionManager bean must be deployed before the Name2 bean can reach the Start state. To specify multiple dependencies on other beans you simply need to list @Demand annotations or nest <demand> elements:

    @Demands(@Demand("TransactionManager", whenRequired="Start"),
             @Demand("OtherBean"))
    public class Example {
        ...
    }

    <bean name="TransactionManager" class="com.acme.SomeSingleton">
        <property name="host">http://www.jboss.org</property>
    </bean>

    <bean name="Name2" class="com.acme.Example">
        <demand state="Start">TransactionManager</demand>
        <demand>OtherBean</demand>
    </bean>

In addition to specifying dependencies on other beans you can also specify dependencies on arbitrary objects that other beans supply. This can be useful if a bean depends on something that is provided by multiple beans but doesn't necessarily care which one provides it. To create these arbitrary objects you need to use the @Supply annotation or <supply> element.

    @Supplies(@Supply("SomethingUseful"))
    public class Provider {
        ...
    }

    @Demands(@Demand("SomethingUseful"))
    public class Consumer {
        ...
    }

    <bean name="Provider" class="com.acme.Provider">
        <supply>SomethingUseful</supply>
    </bean>

    <bean name="Consumer" class="com.acme.Consumer">
        <demand>SomethingUseful</demand>
    </bean>

A bean can also supply multiple objects if necessary:

    @Supplies(@Supply("SomethingUseful"),
              @Supply("SomethingElse"))
    public class Provider {
        ...
    }

    @Demands(@Demand("SomethingUseful"))
    public class Consumer {
        ...
    }

    @Demand(@Demand("SomethingElse"))
    public class OtherConsumer {
        ...
    }

    <bean name="Provider" class="com.acme.Provider">
        <supply>SomethingUseful</supply>
        <supply>SomethingElse</supply>
    </bean>

    <bean name="Consumer" class="com.acme.Consumer">
        <demand>SomethingUseful</demand>
    </bean>

    <bean name="OtherConsumer" class="com.acme.Consumer">
        <demand>SomethingElse</demand>
    </bean>

Behind the scenes JBoss Microcontainer creates a bean of type java.lang.Object for each @Supply annotation or <supply> element named after its value. These beans are then moved automatically through all of the states to reach the INSTALLED state and become deployed. From this point onwards the @Demand annotation and <demand> element work in exactly the same way as before, checking to see if the named bean has been deployed before allowing the bean declaring the demand/s to move to a certain state.

#### Service dependencies

So far we have considered how POJOs depend on each other either explictly through injections or implicitly through the use of arbitrary objects supplied during deployment. These dependencies help us to assemble POJOs in a well defined order to create services but what about when one service depends on another?

Services typically consist of many individual POJOs wired together in order to perform a well-defined function. Once a service is deployed it can be stopped and started as many times as necessary in order to make best use of valuable resources such as CPU and memory. This is possible thanks to the service lifecycle:

- create - the service has been deployed

- start - the service is started

- stop - the service is stopped

- destroy - the service is being undeployed

If one service depends on another then we need someway to ensure that they are created and started in the correct order. Similarly we also need to ensure that they are stopped and destroyed correctly. This is done by adding a @Depends annotation or <depends> element to the POJO that defines a service's public methods and specifying the name of the bean that represents the other service.

    @Depends("AnotherBean")
    public class MyBean {
        ...
    }

    <bean name="AnotherBean" class="org.jboss.test.Example"/>

    <bean name="MyBean" class="org.jboss.test.Example">
        <depends>AnotherBean</depends>
    </bean>

The microcontainer will then ensure that the beans, representing the two services, are deployed in the correct order. Specifically the beans named in the @Depends or <depends> values will reach their CREATE states before the bean declaring the dependencies reaches its CREATE state. The same is true for the START, STOP and DESTROY states. It's possible to define multiple dependencies on other services simply by listing names or nesting <depends> elements:

    @Depends("AnotherBean", "YetAnotherBean")
    public class MyBean {
        ...
    }

    <bean name="AnotherBean" class="org.jboss.test.Example"/>

    <bean name="MyBean" class="org.jboss.test.Example">
        <depends>AnotherBean</depends>
        <depends>YetAnotherBean</depends>
    </bean>

### Adding deployment behaviour

#### Deployment actions

In Part I - Getting Started we covered how to add behaviour to beans during the deployment and undeployment process using AOP lifecycle callbacks. This gave us a powerful way to apply common logic to a number of beans, identified using pointcut expressions, at various points in their lifecycles. However setting up AOP lifecycle callbacks for occasions when an individual bean needs to call arbitrary methods before deployment or after undeployment can be time consuming. Fortunately JBoss Microcontainer provides an alternative way to do this using deployment/undeployment actions.

To specify a method within a bean that should be called after the bean reaches the START state you should use the @InstallMethod annotation or <install> element as follows:

    @InstallMethod
    public String doSomething() {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <install method="doSomething"/>
    </bean>

Parameters can also be passed in using nested <parameter> elements or by defining values with annotations.

    @InstallMethod
    public String doSomething(@StringValue("10") Integer integer, @StringValue("my string") String string) {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <install method="doSomething">
            <parameter>10</parameter>
            <parameter>my string</parameter>
        </install>
    </bean>

If necessary multiple install methods can be defined. They will be called in the order in which they appear as annotations or in the deployment descriptor.

    @InstallMethod
    public String doSomething() {
        ...
    }

    @InstallMethod
    public String doSomethingElse() {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <install method="doSomething"/>
        <install method="doSomethingElse"/>
    </bean>

During undeployment uninstall methods can also be defined which will be called before the bean reaches the STOP state.

    @UninstallMethod
    public String doSomething() {
        ...
    }

    @UninstallMethod
    public String doSomethingElse() {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <uninstall method="doSomething"/>
        <uninstall method="doSomethingElse"/>
    </bean>

If you want a bean to call a method on another bean during deployment or undeployment then you can use the @ExternalInstalls/@ExternalUninstalls annotations or the `bean` attribute of the <install>/<uninstall> elements. You can also define parameters to pass in if necessary.

    @ExternalInstalls(@ExternalInstall(bean="OtherBean", method="doWork")
    @ExternalUninstalls(@ExternalInstall(bean="OtherBean", method="doBye", parameters="{@Value(string=@StringValue("Goodbye")),@Value(string=@StringValue("Saturday"))}"))
    public class MyBean {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <install bean="OtherBean" method="doWork"/>
        <uninstall bean="OtherBean" method="doBye">
            <parameter name="message">Goodbye</parameter>
            <parameter name="day">Saturday</parameter>
        </uninstall>
    </bean>

Currently both the @ExternalInstalls and @ExternalUninstalls annotations take a list of @ExternalInstall annotations.

By default the other bean must have reached the INSTALLED state before its method will be called. This can be changed by using the `dependentState`/`state` attribute.

    @ExternalInstalls(@ExternalInstall(bean="OtherBean", method="doWork", dependentState="Configured")
    public class MyBean {
        ...
    }

    <bean name="SimpleBean" class="org.jboss.example.SimpleBean">
        <install bean="OtherBean" method="doWork" state="Configured"/>
    </bean>

#### Deployment callbacks

Sometimes it is useful for a bean to know when other beans have been deployed. For example a manager bean might want to keep a list of all of the beans it manages. Rather than placing code into each managed bean to register itself with the manager when deployed, it would be better if the manager was automatically called back each time to notify it. JBoss Microcontainer allows such callbacks to occur during deployment and undeployment using the @Install/@Uninstall annotations and <incallback>/<uncallback> elements.

<incallback> is an abbreviation of installCallback and <uncallback> is an abbreviation of uninstallCallback.

    public class Example {
        @Install
        public void addEditor(Editor editor) {
            ...
        }

        @Uninstall
        public void removeEditor(Editor editor) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor"/>
        <uncallback method="removeEditor"/>
    </bean>

In the above example the addEditor method of the editorHolder bean will be called each time a bean of class Editor is deployed. Similarly the removeEditor method will be called each time a bean of class Editor is undeployed. By default the bean class to look for is determined by the class of the parameter in the callback method. If there are multiple methods with the same name but different parameter types then you can add a `signature` attribute to the <incallback>/<uncallback> element to specify the correct one. This is not required when using annotations as we simply annotate the method we want.

    public class Example {
        public void addEditor(Editor editor) {
            ...
        }

        @Install
        public void addEditor(DifferentEditor editor) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor" signature="org.jboss.example.DifferentEditor"/>
    </bean>

Multiple callback methods can be defined per bean. They will be called in the order that they appear as annotations or in the deployment descriptor.

    public class Example {
        @Install
        public void addEditor(Editor editor) {
            ...
        }

        @Install
        public void addViewer(Viewer viewer) {
            ...
        }

        @Uninstall
        public void removeEditor(Editor editor) {
            ...
        }

        @Uninstall
        public void removeViewer(Viewer viewer) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor"/>
        <incallback method="addViewer"/>
        <uncallback method="removeEditor"/>
        <uncallback method="removeViewer"/>
    </bean>

By default each callback will be executed when beans matching the parameter types reach the INSTALLED state. This can be changed if necessary using the `dependentState`/`state` attribute.

    public class Example {
        @Install(dependentState="Configured")
        public void addEditor(Editor editor) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor" state="Configured"/>
    </bean>

Here we are declaring that the addEditor method of the editorHolder bean should be called when any beans of class Editor reach the CONFIGURED state.

It is also possible to configure when the callback methods are executed during the deployment of the bean using the `whenRequired` attribute.

    public class Example {
        @Install(whenRequired="Installed")
        public void addEditor(Editor editor) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor" whenRequired="Installed"/>
    </bean>

Here we are declaring that the addEditor method will be called before the editorHolder bean reaches the INSTALLED state. By default the callbacks are exceuted before the bean reaches the CONFIGURED state.

Finally we can also control when the callback methods are executed depending on how many beans matching the parameter class have been deployed. This is done using the `cardinality` attribute.

    public class Example {
        @Install(cardinality="2..n")
        public void addEditor(Editor editor) {
            ...
        }
    }

    <bean name="editorHolder" class="com.acme.Example">
        <incallback method="addEditor" cardinality="2..n"/>
    </bean>

Here we are declaring that the addEditor method of the editorHolder bean will only be called when two or more beans of class Editor have been deployed.

When using callbacks with collection classes as parameters only the following basic interfaces are currently supported; List, Set and Queue. This is done using the `BasicCollectionCallbackItemFactory` implementation. You can change this if required by setting the `org.jboss.dependency.collectionCallbackItemFactory` system property to the fully-qualified class name of your `CollectionCallbackItemFactory` implementation.

#### Service lifecycle

So far we have discussed how to define deployment/undeployment actions for beans together with callback methods for notification when other beans have been deployed/undeployed. These features are useful for adding behaviours to POJOs but what about adding behaviour to services?

As explained in the previous chapter services have a lifecycle consisting of 4 stages; create, start, stop and destroy. The reason for this is because we want the ability to start and stop a deployed service repeatably at runtime to make best use of valuable resources such as CPU and memory. At each point in this lifecycle the microcontainer will look for a method to call in order to perform appropriate actions. For example starting a service may require that an object is bound into JNDI. By default these methods are named after the lifecycle stage that they represent.

    public class LifecycleBean {
        public void create() {
            ...
        }

        public void start() {
            ...
        }

        public void stop() {
            ...
        }

        public void destroy() {
            ...
        }
    }

If methods like these are defined in your bean then they will be called as the bean is deployed and undeployed. Specifically the create and start methods are called as the bean reaches the CREATE and START states during deployment. The stop and destroy methods are called when the bean passes through the START and CREATE states during undeployment. Only those methods that are defined will be called. For example if you omit the start method then the bean will move to the START state without anything happening.

If you want a different method to be called for any of the stages then you can provide an annotation or XML element to specify which one to use.

    public class Example {
        @Create
        public void initialize() {
            ...
        }

        @Start
        public void go() {
            ...
        }

        @Stop
        public void halt() {
            ...
        }

        @Destroy
        public void remove() {
            ...
        }
    }

    <bean name="Name1" class="com.acme.Example">
        <create method="initialize"/>
        <start method="go"/>
        <stop method="halt"/>
        <destroy method="remove"/>
    </bean>

You can also specify parameters if necessary.

    public class Example {
        @Start
        public void go(@StringValue("MyService") String serviceName,
                       @StringValue("5") Integer priority) {
            ...
        }
    }

    <bean name="Name1" class="com.acme.Example">
        <start method="go">
            <parameter>MyService</parameter>
            <parameter>5</parameter>
        </start>
    </bean>

Sometimes you may want lifecycle methods to be ignored. This can be done using the `ignore` attribute which if set to true prevents the microcontainer from calling the method when the corresponding lifecycle stage is reached.

    public class Example {
        @Stop(ignored="true")
        public void halt() {
            ...
        }
    }

    <bean name="Name1" class="com.acme.Example">
        <start method="stop" ignored="true"/>
    </bean>

## AOP Development

### Introduction

### Configuration

### Using Aspects

### Using Lifecycle Callbacks

### AOP Dependencies

## The Deployment Framework

### Introduction

JBoss Microcontainer at its core allows POJOs to be deployed into a runtime environment. It does this using a state machine to ensure that any dependencies on classloaders or other POJOs are satisfied before progressing through the various stages of creation and configuration. By design the state machine and dependency mechanisms are generic which means that we can also use them to deploy other types of runtime components such as MBeans or OSGi bundles. In order to do this we need a generic deployment framework to create the relevant metadata, handle different kinds of deployable components, and deal with any nested deployments.

To understand why we cannot achieve this using the BasicXMLDeployer let's take a closer look at what it actually does:

    public class BasicXMLDeployer extends BasicKernelDeployer
    {
       ...

       public KernelDeployment deploy(final URL url) throws Throwable
       {
          final boolean trace = log.isTraceEnabled();

          if (url == null)
             throw new IllegalArgumentException("Null url");

          if (trace)
             log.trace("Parsing " + url);

          long start = System.currentTimeMillis();

          Unmarshaller unmarshaller = factory.newUnmarshaller();
          KernelDeployment deployment = (KernelDeployment) unmarshaller.unmarshal(url.toString(), resolver);

          if (deployment == null)
              throw new RuntimeException("The xml " + url + " is not well formed!");

          deployment.setName(url.toString());

          if (trace)
          {
             long now = System.currentTimeMillis();
             log.trace("Parsing " + url + " took " + (now-start) + " milliseconds");
          }

          deploy(deployment);

          if (trace)
          {
             long now = System.currentTimeMillis();
             log.trace("Deploying " + url + " took " + (now-start) + " milliseconds");
          }

          return deployment;
       }

       ...
    }

Once we call the deploy() method with a URL to the XML deployment descriptor an unmarshaller is created to convert the XML into an object representation of type KernelDeployment. We then process the KernelDeployment using the deploy() method of the superclass BasicKernelDeployer:

    public class BasicKernelDeployer extends AbstractKernelDeployer
    {
        ...

       public void deploy(KernelDeployment deployment) throws Throwable
       {
          ...
          super.deploy(deployment);
          deployments.add(deployment);
          ...
       }

        ...

       public void shutdown()
       {
          ListIterator iterator = deployments.listIterator(deployments.size());
          while (iterator.hasPrevious())
          {
             KernelDeployment deployment = (KernelDeployment) iterator.previous();
             undeploy(deployment);
          }
       }
    }

As you can see the BasicKernelDeployer simply calls the deploy() method of its superclass AbstractKernelDeployer before adding the deployment to a list.

The reason for having BasicKernelDeployer is that it contains a shutdown() method which undeploys all the deployments in reverse order. This allows the microcontainer to shutdown gracefully.

    public class AbstractKernelDeployer
    {
        ...
       public void deploy(final KernelDeployment deployment) throws Throwable
       {
          if (deployment.isInstalled())
             throw new IllegalArgumentException("Already installed " + deployment.getName());

          try
          {
             deployBeans(controller, deployment);
             deployment.setInstalled(true);
          }
          catch (Throwable t)
          {
             undeploy(deployment);
             throw t;
          }
       }

       ...

       protected void deployBeans(KernelController controller, KernelDeployment deployment) throws Throwable
       {
          List<BeanMetaData> beans = deployment.getBeans();
          if (beans != null)
          {
             for (BeanMetaData metaData : beans)
             {
                KernelControllerContext context = deployBean(controller, deployment, metaData);
                deployment.addInstalledContext(context);
             }
          }
       }

       protected KernelControllerContext deployBean(KernelController controller, KernelDeployment deployment, BeanMetaData bean) throws Throwable
       {
          KernelControllerContext context = new AbstractKernelControllerContext(null, bean, null);
          if (requiredState != null)
             context.setRequiredState(requiredState);
          if (mode != null)
             context.setMode(mode);
          // Use any deployment classloader if present and the bean doesn't have one
          ClassLoaderMetaData beanClassLoader = bean.getClassLoader();
          if (beanClassLoader == null && deployment != null)
          {
             ClassLoaderMetaData deploymentClassLoader = deployment.getClassLoader();
             if (deploymentClassLoader != null)
                bean.setClassLoader(deploymentClassLoader);
          }
          controller.install(context);
          return context;
       }

        ...
    }

The deploy() method in AbstractKernelDeployer performs a check to see if the deployment has already been installed before calling deployBeans() to split it up into the individual BeanMetaData instances. These are then deployed into the runtime environment using the deployBean() method which creates a KernelControllerContext for each BeanMetaData and installs it into the controller. It also takes care of deciding which classloader to use based on information contained in the KernelDeployment object. For example if the bean doesn't declare a classloader of its own then the deployment classloader (if defined) is used instead.

The type hierarchy of BasicXMLDeployer restricts it to processing bean deployments of type KernelDeployment where each bean is represented by an instance of BeanMetaData. If we want to deploy other runtime components such as MBeans or OSGi bundles then we need to deal with other types of metadata and find a generic way to represent deployments containing them. Furthermore we need to find a flexibile way to process these deployments since each would have its own set of actions that need to take place. For example MBeans need to be registered with an MBean server before they can be considered 'deployed'.

It turns out that we can use the state machine to meet these requirements by creating a DeploymentControllerContext to represent a deployment in the same way that a KernelControllerContext represents a POJO. This allows us to associate a number of deployment actions to different stages of the deployment process:

- PARSE - convert one or more deployment descriptors into object representations containing metadata

- DESCRIBE - determine any dependencies

- CLASSLOADER - create classloaders

- POST_CLASSLOADER - apply AOP changes together with any other bytecode manipulations

- REAL - process the deployment components

As the state machine controller takes a DeploymentControllerContext through each of these stages it calls the associated actions to perform the relevant work. For example we could create multiple parsing actions; one to parse XML files and another to parse Java property files. Depending on the file suffix of the deployment descriptor; .xml or .property we can then choose which one to use during the PARSE stage.

Deployments are represented by DeploymentContexts which can be formed into a hierarchy to represent nested deployments of any depth. A reference to the top-level DeploymentContext is contained in the DeploymentControllerContext:

    public class DeploymentControllerContext extends AbstractControllerContext
    {
       /** The deployment context */
       private DeploymentContext deploymentContext;

       public DeploymentControllerContext(DeploymentContext context, DeployersImpl deployers)
       {
          super(context.getName(), deployers);
          this.deploymentContext = context;
          setMode(ControllerMode.MANUAL);
       }

       public DeploymentContext getDeploymentContext()
       {
          return deploymentContext;
       }
    }

Be careful not to get confused with the names of these types; DeploymentControllerContext and DeploymentContext, as they are very similar.

As deployment descriptors do not always describe runtime components directly, the notion of a deployment component is defined. For example an EJB deployment descriptor may describe a number of EJB containers from which individual EJBs are created. Here we refer to both the EJB containers and EJBs as deployment components but only the EJBs are thought of as runtime components. Deployment components are represented by an implementation of DeploymentContext called ComponentDeploymentContext which allows them to be hierarchical to any depth. For example an EJB container ComponentDeploymentContext could have multiple child ComponentDeploymentContexts representing its EJBs. Deployment components are added/removed to and from their containing deployment or parent deployment component and retrieved for processing using the following methods:

    public class ComponentDeploymentContext implements DeploymentContext
    {
       ...

       boolean isComponent() {
          return true;
       }

       List<DeploymentContext> getComponents() {
          return Collections.unmodifiableList(components);
       }

       void addComponent(DeploymentContext component) {
          ...
          components.add(component);
       }

       boolean removeComponent(DeploymentContext component) {
          ...
          boolean result = components.remove(component);
          component.cleanup();
          return result;
       }

       ...
    }

The deployment framework is therefore a collection of packages and classes that provides a generic way to represent deployments containing arbitrary deployment components. These could be runtime components such as POJOs, MBeans, and EJBs or non-runtime components such as EJB containers which act as factories for the EJBs. Deployments and deployment components can be nested within one another to any depth providing maximum flexibility during deployment.

Consequently it's possible to use the deployment framework instead of the BasicXMLDeployer to deploy POJO-based services specified with XML deployment descriptors. So why then do we need a BasicXMLDeployer? The answer is because the deployment framework itself a POJO-based service specified with an XML deployment descriptor (usually called bootstrap-beans.xml). We therefore need the BasicXMLDeployer to deploy it when the microcontainer is booted up. Once deployed then the framework is used to deploy everything else including any other POJO-based services.

Now that you understand the reasoning for the deployment framework and how it relates to the BasicXMLDeployer the following sections go on the cover the various parts in more detail.

### The Virtual File System

When you think about it all deployments can be broken down into three types of data:

- Deployment descriptors - contain configuration information

- Java classes - contain compiled Java bytecode

- Resources - any other files that are required at runtime

Sometimes only a single deployment descriptor is required although more often you create a deployment archive containing one or more descriptors together with a number of classes. In the case of a Web Archive (WAR) we also include any resources that are to be hosted by the web server.

During development it is convenient to be able to deploy such archives in an unpackaged rather than a packaged state. This means that files can be freely edited in their directories and the deployment processed again without having to re-package everything each time. Packaging is usually more appropriate during the test phase or when going to production as a way of keeping everything together.

Depending on the layout of the development, test or production system it's helpful to allow the deployment of packaged or unpackaged archives both locally, on the computer's hard drive, or remotely over a network. Support for nested deployments is also important so that related items can be deployed together.

To allow all of these concerns to be addressed in a maintainable and extendable way the deployment framework uses a Virtual File System (VFS). This provides a way to represent a deployment as a read-only hierarchical file system regardless of whether it is packaged or not. It also allows deployments to be accessed both locally and remotely using a pluggable design so that new protocols can easily be added to those supplied by default:

- File -

- JAR -

- Memory -

Finally the VFS takes care of generating physical URLs for classloading and debugging. Logical URLs can also be generated for configuration purposes, or codebase protection domains.

### Identifying the deployment structure

Before we can begin to process a deployment we must first determine its structure. This means finding out if it contains any deployment descriptors and/or classes, and if so where they are located relative to the deployment's root. Nested deployments must also be detected and their structures determined in the same way. The purpose of this is to help the parsing actions locate the deployment descriptors in a standard way and to assist in the creation of classloaders. Since we wish to use the Virtual File System (VFS) to represent our deployment we must first create a VFSDeployment using the deployment URI or URL:

    VirtualFile root = VFS.getRoot(deploymentURL);
    VFSDeploymentFactory deploymentFactory = VFSDeploymentFactory.getInstance();
    Deployment deployment = deploymentFactory.createVFSDeployment(root);

The deployment framework then determines the structure of the Deployment using classes that implement the StructureDeployer interface:

    public interface StructureDeployer extends Ordered
    {
    boolean determineStructure(VirtualFile root, VirtualFile parent, VirtualFile file, StructureMetaData metaData, VFSStructuralDeployers deployers) throws DeploymentException;
    }

As a deployment can contain nested deployments the determineStructure() method is meant to be called recursively. The root parameter represents the root of the top-level deployment, the file parameter represents the root of the current (possibly nested) deployment being analyzed and the parent parameter its parent (or null if it is the top-level). The deployers parameter represents a class containing a list of all the StructureDeployer implementations and is needed in order to process any nested deployments.

As each deployment is found a ContextInfo object is created to store the paths to any deployment descriptors and/or classes. These are then added to the StructureMetaData parameter so that the structure of the entire deployment is recorded. For example if we had a top-level deployment containing 2 nested deployments then we would create 3 ContextInfo objects, one for each deployment, and add these to the StructureMetaData object.

#### Deployment Descriptors

Deployment descriptors are files containing configuration information for deployments. They are detected using the FileStructure class by matching the file suffix or using a FileMatcher. Default file suffixes include:

- -beans.xml - contains bean definitions

- -aop.xml - contains aspect definitions

- -service.xml - contains mbean definitions

- -ds.xml - contains JCA datasource definitions

Each FileMatcher must implement the following interface:

    public interface FileMatcher
    {
       boolean isDeployable(VirtualFile file);
    }

Default implementations are:

- BshFileMatcher - checks whether the filename ends with .bsh (Bean Shell)

The purpose of the FileStructure class is to detect deployments that consist of a single deployment descriptor. As such it creates a single ContextInfo object when a known file is found and adds this to the StructureMetaData. Since no classes are present the list of classpaths within the ContextInfo is set to null.

Currently any top-level deployment that consists of a single file is always identified as a known deployment descriptor. This is done to avoid having to specify all of the known file suffixes in a configuration file. The file suffix and FileMatcher checks are only performed for nested deployments.

As the FileStructure class has a relative order of Integer.MAX_VALUE it is always called after any other StructureDeployer implementations such as JARStructure. This means that a deployment consisting of a single JAR file will be detected correctly.

Deployment descriptors that form part of a deployment together with other files, such as classes or resources are detected by other implementations of StructureDeployer such asJARStructure which is described next.

#### Java Archives (JARs)

The JARStructure class determines whether a deployment, in the form of a file or a directory, represents a packaged or unpackaged JAR archive. If the deployment is a single file then the filename suffix is checked against a list contained in the JarUtils class:

- .zip - a standard archive

- .jar - a java archive (defined by the Java SE specification)

- .ear - an enterprise archive (defined by the Java EE specification)

- .rar - a resource archive (defined by the Java EE specification)

- .war - a web archive (defined by the Java EE specification)

- .sar - a service archive (defined by JBoss)

- .har - a hibernate archive (defined by JBoss)

- .aop - an aspect archive (defined by JBoss)

If the deployment is a directory then the same check is performed using the directory name. If a match is found in either case then the deployment is determined to represent a JAR archive.

A top-level directory whose name doesn't match any of the file suffixes is still considered an unpackaged JAR archive as this allows it to be used as a container for multiple nested deployments.

In order to detect nested JAR deployments we iterate through all subdirectories checking whether their names end in a known suffix or if they contain META-INF directories. The check for a META-INF directory is required otherwise every subdirectory without a known filename would be classified as a nested deployment.

For each JAR deployment found we create a new ContextInfo object with its metadata path set to META-INF and the classpath set to the deployment root.

#### Nested deployments

Nested deployments are found by calling the addAllChildren() method in AbstractStructureDeployer and passing in a reference to the deployment root and the current nested deployment along with the StructureMetaData and VFSStructuralDeployers references:

    public abstract class AbstractStructureDeployer implements StructureDeployer
    {
        ...

       protected void addAllChildren(VirtualFile root, VirtualFile parent, StructureMetaData metaData, VFSStructuralDeployers deployers) throws Exception
       {
          addChildren(root, parent, metaData, deployers, null);
       }

       protected void addChildren(VirtualFile root, VirtualFile parent, StructureMetaData metaData, VFSStructuralDeployers deployers, VisitorAttributes attributes) throws Exception
       {
          if (parent == null)
             throw new IllegalArgumentException("Null parent");

          VirtualFileVisitor visitor = candidateStructureVisitorFactory.createVisitor(root, parent, metaData, deployers, attributes);
          parent.visit(visitor);
       }

        ...
    }

This in turn calls the addChildren() method which creates a VirtualFileVisitor that is passed to the virtual file representing the current deployment. Each child file or directory of the current deploment is then visited using the visitor which use the VFSStructuralDeployers object to iterate through the list of StructureDeployers. These then determine whether the child represents a nested deployment. If a nested deployment is found then the process is repeated in order to recurse through the entire directory structure. This happens regardless of whether the deployment is packaged or unpackaged as the Virtual File System takes care of accessing the actual files.

Due to this recursive algorithm you can freely nest any type of deployment within any other type of deployment to any level. There is one exection to this with WAR archives which cannot contain nested deployments. All you need to ensure is that you have defined a StructureDeployer implementation capable of recognising your deployment.

#### Declaring a custom deployment structure

JBoss Microcontainer provides two StructureDeployer implementations out-of-the-box to recognise the most common forms of deployments; standalone deployment descriptors and packaged/unpackaged JAR archives. In addition it also includes a third implementation called DeclaredStructure.

DeclaredStructure allows you to specify the structure of a deployment, including any nested deployments, using an XML file called jboss-structure.xml placed in the deployment's META-INF directory. The contents of this file are:

    <structure>
        <context>
            <path name=""/>
            <metaDataPath>
                <path name="OTHER-DIR"/>
            </metaDataPath>
            <classpath>
                <path name=""/>
            </classpath>
        </context>
    </structure>

This describes a top-level deployment and specifies that deployment descriptors can be found in the OTHER-DIR directory and classes in the root directory. If you want to describe nested deployments then you simply need to create additional <context> elements and specify their paths relative to the root deployment:

    <structure>
        <context>
            <path name=""/>
            <metaDataPath>
                <path name="OTHER-DIR"/>
            </metaDataPath>
            <classpath>
                <path name=""/>
            </classpath>
        </context>
        <context>
            <path name="nestedDeployment1"/>
            <metaDataPath>
                <path name="descriptors/xml/"/>
            </metaDataPath>
            <classpath>
                <path name="classes"/>
                <path name="thirdParty/classes"/>
            </classpath>
        </context
        <context>
            <path name="utils/nestedDeployment2"/>
            <metaDataPath>
                <path name="META-INF"/>
                <path name="config/descs/"/>
            </metaDataPath>
            <classpath>
                <path name="lib"/>
            </classpath>
        </context
    </structure>

Here we've added two nested deployments, one directly underneath the top-level deployment and another in a subdirectory called utils. The first nested deployment has deployment descriptors located in its descriptors/xml directory and classes in either the classes or thirdParty/classes directories. The second nested deployment has deployment descriptors in either the META-INF or config/descs directories and classes in the lib directory.

In order to ensure that any JAR files that you add META-INF/jboss-structure.xml to are correctly recognised by DeclaredStructure instead of JARStructure the DeclaredStructure has a relativeOrder of 0 and the JARStructure a relativeOrder of 10000. This means that the DeclaredStructure class will be consulted first when determining the structure of a deployment.

If you use the DeclaredStructure approach then you must specify all nested deployments in the META-INF/jboss-structure.xml file. This is because no recursion takes place once the structure has been determined. If you want the ability to nest other kinds of deployments within your custom deployment structure then it may be easier to create your own StructureDeployer implementation. Doing so will allow you to call the addAllChildren() method to perform the recursion.

#### Determining the deployment structure programmatically

Using the DeclaredStructure approach is convenient if you have an unusual deployment structure and don't mind adding the META-INF/jboss-structure.xml file to your deployment. However, if you have many deployments and want to avoid adding this file each time, or you want to nest arbitrary deployments inside your custom structure then you are better off creating your own StructureDeployer implementation.

The easiest way to do this is by extending the AbstractStructureDeployer class which already implements the StructureDeployer interface:

    public abstract class AbstractStructureDeployer implements StructureDeployer
    {
       ...
    }

This includes helper methods to see if a VirtualFile represents a file or a directory and whether it corresponds to a top-level deployment. It also has methods to recurse through all of the files within a deployment to find nested deployments and to create ContextInfo objects for each one found. The only method that you need to implement is the one defined by the StructureDeployer interface:

    public interface StructureDeployer extends Ordered
    {
       boolean determineStructure(VirtualFile root, VirtualFile parent, VirtualFile file, StructureMetaData metaData, VFSStructuralDeployers deployers) throws DeploymentException;
    }

If you recognise the structure of the deployment then you must create a ContextInfo object containing the details and add it to the StructureMetaData. If you extend AbstractStructureDeployer then you can use the createContext() and addClassPath() helper methods to help do this. You must then return true to prevent any other StructureDeployer from analysing the deployment again.

If you want to control when your StructureDeployer is called you can use the relativeOrder property. By default this is set to `Integer.MAX_VALUE` in AbstractStructureDeployer. Implementations with a lower value are called before those with a higher value. If two values are the same then the return values of each implementation's toString() method are compared. The relativeOrder values for the out-of-the-box StructureDeployer implementations are:

- DeclaredStructure - 0

- JARStructure - 10000

- FileStructure - Integer.MAX_VALUE

This means that DeclaredStructure is always called first followed by JARStructure and finally FileStructure.

### Creating Deployment Contexts

#### Introduction

Once the structure of a deployment has been determined then the next step is to create a number of DeploymentContext objects. A DeploymentContext is required for each deployment, whether top-level or nested, in order to store information such as:

- the location of any deployment descriptors - the metadata path

- the location of any classes - the classpath

- the relative path to the top-level deployment - the relative path

- the deployment name

- the order it should be deployed in relative to other deployments - the relative order

- a list of deployment types that it represents (including nested deployments) - the types

- the state of the deployment - whether it is deployed or not

- the deployment class loader

- the deployment resource loader

- dependencies on other deployments or runtime components

- references to any components that it deploys - POJOs, MBeans etc...

- references to any nested (child) deployments or the parent deployment

Since the StructureMetaData object created using the StructureDeployer implementations already contains some of this information we subsequently pass it to a StructureBuilder together with a reference to the original Deployment to populate the deployment with a tree of DeploymentContexts:

    public interface StructureBuilder
    {
       DeploymentContext populateContext(Deployment deployment, StructureMetaData metaData) throws DeploymentException;
    }

During this method call the information contained within the ContextInfo objects, found inside the StructureMetaData, is transferred to new instances of DeploymentContext that are assembled into a hierarchy. A reference to the top-level DeploymentContext is then returned.

#### Accessing a deployment

The deployment framework uses DeploymentContext objects to access the internal details of a deployment during processing. However, if you wish to access a deployment yourself then you should use a wrapper called DeploymentUnit.

This prevents you from getting or setting the deployment state, changing the deployment classloader if it already exists, changing any parent/child relationships between nested deployments and accessing any exceptions that have occurred during deployment. You are also prevented from calling the visit() method that allows you to visit all of the contexts in the hierarchy or the cleanup() method that removes deployment metadata from the metadata repository.

#### Attaching extra information

Since each instance of DeploymentContext contains generic deployment information we need a way to store and retrieve additional information generated during the deployment process. This is done using the DeploymentUnit wrapper which extends the MutableAttachments interface:

    public interface DeploymentUnit extends MutableAttachments
    {
        ...
    }

    public interface MutableAttachments extends Attachments
    {
       Object addAttachment(String name, Object attachment);
       <T> T addAttachment(String name, T attachment, Class<T> expectedType);
       <T> T addAttachment(Class<T> type, T attachment);

       Object removeAttachment(String name);
       <T> T removeAttachment(String name, Class<T> expectedType);
       <T> T removeAttachment(Class<T> type);

       void setAttachments(Map<String, Object> map);

       void clear();

       int getChangeCount();
       void clearChangeCount();
    }

As you can see the MutableAttachments operations allow you to store arbitrary objects (referred to as attachments) inside a map using a String for the key. For convenience you can pass in the type of the object instead of a string and the return value of type.getName() will be used as the key. If you pass in a type for the key, or you specify an expectedType argument, then the return value will be cast to an object of that type.

If you wish to retrieve any objects then you can use operations from the Attachments interface:

    public interface Attachments extends Serializable
    {
       Map<String, Object> getAttachments();

       Object getAttachment(String name);
       <T> T getAttachment(String name, Class<T> expectedType);
       <T> T getAttachment(Class<T> type);

       boolean isAttachmentPresent(String name);
       boolean isAttachmentPresent(String name, Class<?> expectedType);
       boolean isAttachmentPresent(Class<?> type);

       boolean hasAttachments();
    }

Again if you pass a type for the key, or specify an expectedType argument, then the return value will be cast to an object of that type. In the case of the isAttachmentPresent() methods the return value is only true if both the object can be located using the key and it can be cast to the specified type.

DeploymentUnit also contains a convenience method that allows you to retrieve all objects of a particular type from the map of attachments:

    public interface DeploymentUnit extends MutableAttachments
    {
        ...
       <T> Set<? extends T> getAllMetaData(Class<T> type);
        ...
    }

#### Deployment components

Deployments usually contain one or more runtime components in addition to configuration information and resource files. By runtime components we mean any classes that require a container in which to run. Containers take care of controlling a component's lifecycle in addition to providing common behaviours so that component developers do not have to do this themselves. By leveraging the work of the container, components allow you to concentrate on developing the business logic of your application without having to continually write code for common tasks. This typically reduces the time needed to develop systems with advanced behaviour.

The simplest example of a component is a POJO. In this case the container controls when the POJO is created based on when a client performs a lookup. It can also take care of wiring different POJOs together based on information in a deployment descriptor so that the developer doesn't have to hard-code any relationships. This makes configuration of the runtime environment easier to change.

Another example is an MBean. Here the container (an MBeanServer) takes care of routing all method calls through a bus so that clients never reference the MBean directly. This allows MBeans to be replaced at runtime without impacting any clients. It also allows the management interface of an MBean, the attributes and operations exposed to clients, to change at runtime without needing to redeploy it.

A further example is an OSGi service bundle. Here the container ensures that the classes required by the bundle are available in the runtime before the service is started. It also takes care of making classes within the bundle available to others when deployed and removing them again when undeployed. This makes the runtime environment easier to construct and maintain with fewer classloading issues.

In order to provide support for deploying different types of runtime components, JBoss Microcontainer requires that each one is represented by its own ComponentDeploymentContext:

    public class ComponentDeploymentContext implements DeploymentContext
    {
        ...
    }

This is similer to a normal DeploymentContext implementation but with some important differences:

- Components always have a relative order of 0

- Components do not have a metadata path

- Components always use the classloader of the containing deployment

- Components cannot change their parent once constructed

- Components can contain other components

- Components are never considered top-level deployments

In addition ComponentDeploymentContexts delegate to their parent DeploymentContext for information such as:

- simple name

- relative path

- deployment types

- deployment state

- class loader

- Resource class loader

- Deployment Resource Loader

- Dependency Info

- get/setProblem

The reason we use the DeploymentContext interface is so that we can process components together with normal deployments. This ensures that when a deployment is deployed any components that it contains are deployed with it. Similarly undeploying a deployment causes its components to be undeployed at the same time.

An additional motivation is that we can easily create separate ControllerContexts for each component which we can then process using the state machine. This allows us to perform a well-defined set of deployment actions to deploy/undeploy each component in and out of the runtime.

Having separate ControllerContexts for each component also allows you to manage the components individually, possibly via an Admin console. Furthermore each component can have its own dependencies allowing fine-grained control of how the runtime is constructed and destructed.

ComponentDeploymentContexts are added to a DeploymentUnit using the addComponent() method whenever a component is discovered during the deployment process:

    public class AbstractDeploymentUnit extends AbstractMutableAttachments implements DeploymentUnit
    {
        ...

       public DeploymentUnit addComponent(String name)
       {
          DeploymentContext component = createComponentDeploymentContext(name, deploymentContext);
          DeploymentUnit unit = createComponentDeploymentUnit(component);
          component.setDeploymentUnit(unit);
          deploymentContext.addComponent(component);
          return unit;
       }

       ...

       protected DeploymentContext createComponentDeploymentContext(String name, DeploymentContext parent)
       {
          return new ComponentDeploymentContext(name, parent);
       }

        ...
    }

As components are usually accessed with the DeploymentUnit interface they can also have attachments just like any other deployment:

    public interface DeploymentUnit extends MutableAttachments
    {
        ...
    }

    public interface MutableAttachments extends Attachments
    {
        ...

       Object addAttachment(String name, Object attachment);

        ...
    }

An attachment may well be metadata associated with the component. In this way the metadata can be processed using deployment actions as the component's ControllerContext passes through the state machine.

#### Deployment dependencies

Sometimes a deployment may have dependencies on other deployments or on a runtime component such as a classloader. In these cases we need to be able to define the dependencies so that the state machine can decide whether or not to progress the deployment to the next stage. This is done using the following methods of the DeploymentUnit interface:

    public interface DeploymentUnit extends MutableAttachments
    {
        ...

       DependencyInfo getDependencyInfo();
       void addIDependOn(DependencyItem dependency);
       void removeIDependOn(DependencyItem dependency);
    }

AbstractDeploymentUnit delegates these calls to the DeploymentContext implementation that it wraps:

    public class AbstractDeploymentUnit extends AbstractMutableAttachments implements DeploymentUnit
    {
       ...

       public void addIDependOn(DependencyItem dependency)
       {
          getDependencyInfo().addIDependOn(dependency);
       }

       public DependencyInfo getDependencyInfo()
       {
          return deploymentContext.getDependencyInfo();
       }

       public void removeIDependOn(DependencyItem dependency)
       {
          getDependencyInfo().removeIDependOn(dependency);
       }

       ...
    }

This in turn delegates them to the corresponding ControllerContext implementation which is stored as an attachment:

    public class AbstractDeploymentContext extends ManagedObjectsWithTransientAttachmentsImpl implements DeploymentContext
    {
       ...

       public DependencyInfo getDependencyInfo()
       {
          ControllerContext controllerContext = getTransientAttachments().getAttachment(ControllerContext.class);
          if (controllerContext != null)
             return controllerContext.getDependencyInfo();
          else
          {
             DeploymentContext parent = getParent();
             if (parent == null)
                throw new IllegalStateException("Deployment ControllerContext has not been set");
             return parent.getDependencyInfo();
          }
       }

       ...
    }

If a ControllerContext object is not found within the deployment's attachments then the parent deployment is tried. In this way DependencyItems are added/removed to the underlying ControllerContext implementation for the deployment.

### Processing a deployment

#### Introduction

So far we have established the structure of a deployment using StructureDeployer classes and created a corresponding DeploymentContext using a StructureBuilder. Nested deployments have been dealt with by creating additional DeploymentContexts and adding these as children of the parent DeploymentContext.

The next step in the deployment framework is to process the deployment. The objective being to extract any metadata from the deployment descriptors and create a classloader. Components must also be identified during this process and a ComponentDeploymentContext created for each one so that they can be deployed into the runtime.

The Deployers interface defines the operations that need to take place:

    public interface Deployers
    {
       ...

       void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy);

       void checkComplete(Collection<DeploymentContext> errors, Collection<Deployment> missingDeployer) throws DeploymentException;

       void checkComplete(DeploymentContext... contexts) throws DeploymentException;

       void checkStructureComplete(DeploymentContext... contexts) throws DeploymentException;
    }

In the default implementation DeployersImpl the process() method creates new DeploymentControllerContexts for each DeploymentContext in the deploy list and installs them into the microcontainer controller:

    public class DeployersImpl implements Deployers, ControllerContextActions
    {
        ...

       public void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy)
       {
            ...

          // There is something to deploy
          if (deploy != null && deploy.isEmpty() == false)
          {
             // Create the controller contexts
             for (DeploymentContext context : deploy)
             {
                DeploymentControllerContext deploymentControllerContext = new DeploymentControllerContext(context, this);
                try
                {
                   controller.install(deploymentControllerContext);
                   context.setState(DeploymentState.DEPLOYING);
                   ...
                   context.getTransientAttachments().addAttachment(ControllerContext.class, deploymentControllerContext);
                   ...
                }
                catch (Throwable t)
                {
                   // Set the error on the parent
                   context.setState(DeploymentState.ERROR);
                   context.setProblem(t);
                   // Set the children to not deployed
                   setState(context, DeploymentState.UNDEPLOYED, DeploymentState.DEPLOYING);
                }
             }

             // Go through the states in order
             List<ControllerState> states = controller.getStates();
             for (ControllerState state : states)
             {
                for (DeploymentContext context : deploy)
                {
                   if (DeploymentState.ERROR.equals(context.getState()) == false)
                   {
                      DeploymentControllerContext deploymentControllerContext = context.getTransientAttachments().getAttachment(ControllerContext.class.getName(), DeploymentControllerContext.class);
                      try
                      {
                         controller.change(deploymentControllerContext, state);
                      }
                      catch (Throwable t)
                      {
                         context.setState(DeploymentState.ERROR);
                         context.setProblem(t);
                      }
                   }
                }
             }
           }
        }

        ...
    }

Notice that a reference to the DeploymentControllerContext is stored as an attachment to the DeploymentContext so that it can be retrieved later and passed to the controller.install() method.

Undeployment happens in a similar way. First of all the DeploymentControllerContexts associated with the DeploymentContexts in the undeploy list are extracted into a separate list. The microcontainer controller is then used again to push them through the deployment states in reverse order. Finally the DeploymentControllerContexts are removed from the DeploymentContext attachments where they were initially stored and uninstalled from the controller:

    public class DeployersImpl implements Deployers, ControllerContextActions
    {
        ...

       public void process(List<DeploymentContext> deploy, List<DeploymentContext> undeploy)
       {
          // There is something to undeploy
          if (undeploy != null && undeploy.isEmpty() == false)
          {
             // Build a list in reverse order
             List<DeploymentControllerContext> toUndeploy = new ArrayList<DeploymentControllerContext>();
             for (int i = undeploy.size()-1; i >= 0; --i)
             {
                DeploymentContext context = undeploy.get(i);
                if (DeploymentState.ERROR.equals(context.getState()) == false)
                   context.setState(DeploymentState.UNDEPLOYING);
                ...
                DeploymentControllerContext deploymentControllerContext = context.getTransientAttachments().getAttachment(ControllerContext.class.getName(), DeploymentControllerContext.class);
                if (deploymentControllerContext == null)
                {
                   log.debug("DeploymentContext has no DeploymentControllerContext during undeploy request, ignoring: " + context);
                }
                else
                {
                   toUndeploy.add(deploymentControllerContext);
                }
             }

             // Go through the states in reverse order
             List<ControllerState> states = controller.getStates();
             for (int i = states.size()-1; i >= 0; --i)
             {
                ControllerState state = states.get(i);
                for (DeploymentControllerContext deploymentControllerContext : toUndeploy)
                {
                   DeploymentContext context = deploymentControllerContext.getDeploymentContext();
                   if (ControllerState.ERROR.equals(context.getState()) == false)
                   {
                      try
                      {
                         controller.change(deploymentControllerContext, state);
                      }
                      catch (Throwable t)
                      {
                         ...
                         context.setState(DeploymentState.ERROR);
                         context.setProblem(t);
                      }
                   }
                }
             }

             // Uninstall the contexts
             for (DeploymentControllerContext deploymentControllerContext : toUndeploy)
             {
                DeploymentContext context = deploymentControllerContext.getDeploymentContext();
                context.getTransientAttachments().removeAttachment(ControllerContext.class);
                try
                {
                   controller.uninstall(deploymentControllerContext.getName());
                   setState(context, DeploymentState.UNDEPLOYED, null);
                   ...
                   cleanup(context);
                  ...
                }
                catch (Throwable t)
                {
                   ...
                   context.setState(DeploymentState.ERROR);
                   context.setProblem(t);
                }
             }
          }

          ...
       }

       ...
    }

Undeployments are actually processed before deployments to ensure that we don't end up in a situation where a deployment that depends on a subsequently undeployed deployment has to be undeployed again straight away.

You should hopefully see from this breakdown that each deployment is processed by creating a DeploymentControllerContext that is then installed into the microcontainer controller and pushed through a series of deployment stages. What these stages are and how they are created is the subject of the next section.

#### Deployment stages

By default the DeployersImpl class creates the following deployment stages on construction:

- NOT_INSTALLED - the deployment is ready to be installed or has been uninstalled

- PARSE - deployment descriptors are parsed into deployment metadata

- DESCRIBE - dependencies on other deployments or runtime components are determined

- CLASSLOADER - a classloader for the deployment is created

- POST_CLASSLOADER -

- REAL - components are deployed into the runtime

- INSTALLED - the deployment is fully deployed

Each DeploymentStage has a name and indicates which stages it comes before and after:

    public class DeploymentStage
    {
       private String name;

       private String after;

       private String before;

       ...
    }

This allows a new ControllerState to be created for each DeploymentStage which can then be added in the correct place to the list of ControllerStates associated with the controller:

    public class DeployersImpl implements Deployers, ControllerContextActions
    {
        ...

       public DeployersImpl(AbstractController controller, Set<Deployer> deployers)
       {
          if (controller == null)
             throw new IllegalArgumentException("Null controller");
          this.controller = controller;

          // Add the standard stages
          addDeploymentStage(DeploymentStages.NOT_INSTALLED);
          addDeploymentStage(DeploymentStages.PARSE);
          addDeploymentStage(DeploymentStages.DESCRIBE);
          addDeploymentStage(DeploymentStages.CLASSLOADER);
          addDeploymentStage(DeploymentStages.POST_CLASSLOADER);
          addDeploymentStage(DeploymentStages.REAL);
          addDeploymentStage(DeploymentStages.INSTALLED);

          ...
       }

       ...

       protected synchronized void addDeploymentStage(DeploymentStage stage)
       {
          if (stage == null)
             throw new IllegalArgumentException("Null stage");
                // Already done?
          String stageName = stage.getName();
          if (stages.containsKey(stageName))
             return;

          ControllerState preceeds = null;
          String before = stage.getBefore();
          String after = stage.getAfter();
          if (before != null || after != null)
          {
             // Determine where to put the stage
             List<ControllerState> states = controller.getStates();
             for (int i = 0; i < states.size(); ++i)
             {
                ControllerState state = states.get(i);
                String stateName = state.getStateString();
                if (before != null && before.equals(stateName))
                {
                   preceeds = state;
                   break;
                }
                if (after != null && after.equals(stateName))
                {
                   if (i < states.size()-1)
                   {
                      preceeds = states.get(i+1);
                      break;
                   }
                }
             }
          }

          controller.addState(new ControllerState(stageName), preceeds);
          stages.put(stageName, stage);
          ...
       }

       ...
    }

The DeploymentStages are also stored in a map, using the stage name as a key, to prevent duplicate stages from being added.

#### Deployment actions

#### Ordering (Inputs and outputs)

#### Deploying components

### Putting it all together

#### Introduction

#### Defining the deployment framework

#### Defining deployment structures

#### Defining deployment actions

## Managing Deployments

## Classloading

### Defining Policies

## Developing OSGi services

## Extending the Microcontainer

### Introduction

### Guice Extension

### Identity Extension

### jBPM Extension

### Drools Extension

## Additional Resources

### Wiki

### Forums