<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
      "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">

<section>
   <title>AOP Configuration and Usage</title>

   <para>When writting new version of Kernel, there was always a need for
      simple usage of advanced AOP features in the Kernel itself.
      With the version 2.0.0 of Microcontainer there is an elegant way of
      binding your aspect to wired POJOs, using all the advantages of full
      dependency state machine. Meaning that even aspect behave as installed
      services, having full lifecycle and dependency support in the Microcontainer.
      And it's all a matter of configuration if you want to use aspectized Microcontainer
      or just plain POJO behaviour. To find out more about JBoss AOP, please see the JBoss
      AOP documentation
   </para>

   <sect2>
      <title>Configuration</title>
      <para>To leverage the JBoss AOP integration in the Microcontainer you need to make sure
         that <literal>jboss-aop-mc-int.jar</literal> is available on the classpath. The
         Microcontainer will decide how whether to use AOP depending on if classes
         from this jar are present.
      </para>

      <para>To use the AOP integration we must include the <literal>AspectManager</literal> bean.
         in our configuration. It is included as follows
      </para>

      <programlisting><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="urn:jboss:bean-deployer:2.0">
   <bean name="AspectManager" class="org.jboss.aop.AspectManager">
      <constructor
         factoryClass="org.jboss.aop.AspectManager"
         factoryMethod="instance"/>
   </bean>

   <!-- declare beans and aspects -->
</deployment>
      ]]></programlisting>

   </sect2>

   <sect2>
      <title>Using Aspects</title>
      <para>We can apply aspects to any beans we like. This can either be done by using already woven
         classes (loadtime or compile-time weaving). If the bean class is not already woven, but should
         have aspects applied to it, a proxy will be generated. If the class is not woven, field level
         aspects will not get triggered, you will only get constructor and method-level interception.
      </para>

      <programlisting><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<deployment 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="FooAdvice"
               class="org.jboss.test.microcontainer.support.TestAspect"
               method="foo"
               pointcut="execution(* *.SimpleBeanImpl->someMethod(..))">
   </aop:aspect>

   <bean
      name="Intercepted"
      class="org.jboss.test.microcontainer.support.SimpleBeanImpl"/>
   <!-- declare beans and aspects -->
</deployment>
      ]]></programlisting>
      <programlisting><![CDATA[
import org.jboss.aop.joinpoint.Invocation;

public class TestAspect
{
   public static boolean fooCalled;
   public static boolean barCalled;
   boolean shouldInvoke;

   public Object foo(Invocation inv) throws Throwable
   {
      System.out.println("--- foo");
      return inv.invokeNext();
   }
}
      ]]></programlisting>

      <para>In the above example, whenever we call the method <literal>someMethod()</literal>
         in the <literal>Intercepted</literal> bean, we will get intercepted by the
         <literal>FooAdvice</literal> bean's <literal>foo()</literal> method. The aspect
         methods must have the signature shown. If the <literal>method</literal> attribute
         is left out for the <literal>aop:aspect</literal> advice, it will look for an advice
         method called <literal>invoke()</literal>. Please see the JBoss AOP documentation for
         more information about advice methods, and the pointcut expressions used to pick out
         methods/constructors/fields that should have aspects applied.
      </para>

   </sect2>

   <sect2>
      <title>AOP Lifecycle callbacks</title>
      <para>We can also aspectize the installs and uninstalls of a bean. The following
         snippet shows a AOP lifecycle callback handler that gets triggered once
         <literal>StartBean</literal> enters the <literal>start</literal> state upon
         deployment, and when it leaves the <literal>start</literal> state upon
         undeployment.
      </para>

      <programlisting><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<deployment 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:lifecycle-start xmlns:aop="urn:jboss:aop-beans:1.0"
               name="InstallAdvice"
               class="org.jboss.test.microcontainer.support.LifecycleCallback"
               classes="@org.jboss.test.microcontainer.support.Start">
   </aop:lifecycle-start>

   <bean name="StartBean"
      class="org.jboss.test.microcontainer.support.SimpleBeanImpl">
      <annotation>@org.jboss.test.microcontainer.support.Start</annotation>
   </bean>

</deployment>
      ]]></programlisting>
      <programlisting><![CDATA[
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 install(ControllerContext ctx){
      System.out.println("Bean " + ctx.getName() + " is being uninstalled";
   }
}
      ]]></programlisting>

      <para>The <literal>install</literal> and <literal>uninstall</literal> methods
         are required, and must have the signature shown. The names of these methods can be
         overridden by passing in the <literal>installMethod</literal> and
         <literal>uninstallMethod</literal> attributes as part of the
         <literal>aop:lifecycle-start</literal> tag.
      </para>

      <para>We can also intercept the install/uninstall upon entering/leaving other states, by
         substituting <literal>aop:lifecycle-start</literal> with one of the following.
      </para>

      <itemizedlist mark="bullet">
         <listitem><literal>aop:lifecycle-configure</literal> -
            Triggered when the target beans enter/leave the <literal>configure</literal>
            lifecycle state upon deployment/undeployment</listitem>
         <listitem><literal>aop:lifecycle-create </literal> -
            Triggered when the target beans enter/leave the <literal>create</literal>
            lifecycle state upon deployment/undeployment</listitem>
         <listitem><literal>aop:lifecycle-describe</literal> -
            Triggered when the target beans enter/leave the <literal>describe</literal>
            lifecycle state upon deployment/undeployment</listitem>
         <listitem><literal>aop:lifecycle-install</literal> -
            Triggered when the target beans enter/leave the <literal>install</literal>
            lifecycle state upon deployment/undeployment</listitem>
         <listitem><literal>aop:lifecycle-instantiate</literal> -
            Triggered when the target beans enter/leave the <literal>instantiate</literal>
            lifecycle state upon deployment/undeployment</listitem>
      </itemizedlist>

   </sect2>

   <sect2>
      <title>Aspect dependencies</title>
      <para>Aspects and AOP lifecycle callbacks configured via the microcontainer can have
         dependencies just as normal beans can have. Beans which have these aspects applied
         inherit the aspect's dependencies.
      </para>

      <programlisting><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<deployment 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:lifecycle-configure xmlns:aop="urn:jboss:aop-beans:1.0"
               name="JMXAdvice"
               class="org.jboss.aop.microcontainer.aspects.jmx.JMXLifecycleCallback"
               classes="@org.jboss.aop.microcontainer.aspects.jmx.JMX">
      <property name="mbeanServer"><inject bean="MBeanServer"/></property>
   </aop:lifecycle-configure>

   <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
               name="TxAdvice"
               class="org.acme.aspects.TxAspect"
               pointcut="execution(* *->@org.acme.Tx(..))">
      <property name="txManager"><inject bean="TxManager"/></property>
   </aop:aspect>

   <bean name="BeanWithAspects"
      class="org.jboss.test.microcontainer.support.SimpleBeanImpl">
      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX</annotation>
      <annotation>@org.acme.Tx</annotation>
   </bean>

   <bean name="PlainBean"
      class="org.jboss.test.microcontainer.support.SimpleBeanImpl">
   </bean>

</deployment>
      ]]></programlisting>

      <para><literal>JmxAdvice</literal> depends on a
      bean called <literal>MBeanServer</literal> having been deployed, and
      <literal>TxAdvice</literal> depends on a bean called <literal>TxManager</literal>
      having been deployed. <literal>BeanWithAspects</literal> has been annotated with both
      <literal>@JMX</literal> and <literal>@Tx</literal>. Using this configuration,
      <literal>BeanWithAspects</literal> gets both <literal>JMXAdvice</literal> and
      <literal>TxAdvice</literal> applied. <literal>BeanWithAspects</literal> inherits the dependencies
      of all applied aspects and AOP lifecycle callbacks, so it cannot be started until
      <literal>JMXAdvice</literal> and <literal>TxAdvice</literal> have their dependencies
      satisfied. <literal>PlainBean</literal> on the other hand, has no aspects applied, and
      so has no extra dependencies from the AOP layer.
      </para>

   </sect2>
</section>