Friday, 13 February 2009

Getting Class values from Annotations in an AnnotationProcessor

In annotation processors one common use case is to read the values contained within an Annotation. In most cases this works fine, however there are some caveats when it comes to accessing values within Annotations that are either Class or a Class array. It’s even worse if you are trying to access an annotation on a method within a super type of the class you are processing. Here I’ll go through how to access those Class values and how to get those values when they are in a super type - specifically when a method has been overridden.

First why?

Well inside retepTools we have an AnnotationProcessor that checks to ensure that certain annotations are used correctly, specifically the @ReadLock and @WriteLock annotations. It’s invalid for those annotations to be used together on the same method. It’s also invalid for a method to be annotated with one and then overridden in another class but annotated with the other, so the processor checks the overridden method and generates an error if the rules have been violated.

Now this caused be a big headache in reading the overridden annotations, because although the annotations were present, the values (and specific the Class ones) were null. Although @ReadLock and @WriteLock do not use values, another related annotation @Contract does, so here’s how I finally solved the problem.

The usual way of reading annotation values

In most cases, when you have an javax.lang.model.element.Element you can use the getAnnotation() method to return your annotation and then you have access to the values contained within it. For example say we have an annotation called Action which holds a single String value:

@Documented @Retention( RetentionPolicy.RUNTIME )

@Target(ElementType.METHOD)

public @interface Action

{

    String value();

}

We annotate a class with that annotation against the run method:

public class A {

    @Action( “do something” )

    public void run() {

    }

}

Now within your AnnotationProcessor, you can obviously get the value easily by calling getAnnotation( Action.class ) and if it returns an instance call the value() method:

@SupportedAnnotationTypes( "*" )

@SupportedSourceVersion( SourceVersion.RELEASE_6 )

@ProhibitAnnotationProcessing

public class Processor

        extends AbstractProcessor

{

    @Override

    public boolean process( final Set<? extends TypeElement> annotations,

                            final RoundEnvironment env )

    {

        if( !env.processingOver() )

        {

            for( Element e : env.getRootElements() )

            {

                TypeElement te = findEnclosingTypeElement( e );

                System.out.printf( "\nScanning Type %s\n\n",

                                   te.getQualifiedName() );

                for( ExecutableElement ee : ElementFilter.methodsIn(

                        te.getEnclosedElements() ) )

                {

                    Action action = ee.getAnnotation( Action.class );

                    

                    System.out.printf(

                            "%s Action value = %s\n",

                            ee.getSimpleName(),

                            action == null ? null : action.value() );

                }

            }

        }

        return false;

    }

    public static TypeElement findEnclosingTypeElement( Element e )

    {

        while( e != null && !(e instanceof TypeElement) )

        {

            e = e.getEnclosingElement();

        }

        return TypeElement.class.cast( e );

    }

}

This generates the following output when run:

------------------------------------------------------------------------

Building scratch

   task-segment: [clean, install]

------------------------------------------------------------------------

[clean:clean]

Deleting directory /Users/peter/dev/retep/scratch/target

[compiler:compile {execution: compileAnnotations}]

Compiling 2 source files to /Users/peter/dev/retep/scratch/target/classes

[resources:resources]

Using default encoding to copy filtered resources.

[compiler:compile]

Compiling 2 source files to /Users/peter/dev/retep/scratch/target/classes

Scanning Type scratch.A

run Action value = do something

Reading annotation values from an overridden method

Now this is fine, but what happens if you are looking at an annotation thats in an overridden class?

Say we have class B which extends A and overrides run():

public class B extends A {

    @Override

    public void run() {

    }

}

Now when we run the processor, for each ExecutableElement we’ll first look for an annotation and then if not found we’ll look for an overridden method and check there. 

    @Override

    public boolean process( final Set<? extends TypeElement> annotations,

                            final RoundEnvironment env )

    {

        if( !env.processingOver() )

        {

            for( Element e : env.getRootElements() )

            {

                TypeElement te = findEnclosingTypeElement( e );

                System.out.printf( "\nScanning Type %s\n\n",

                                   te.getQualifiedName() );

                for( ExecutableElement ee : ElementFilter.methodsIn(

                        te.getEnclosedElements() ) )

                {

                    Action action = ee.getAnnotation( Action.class );

                    if( action == null )

                    {

                        // Look for the overridden method

                        ExecutableElement oe = getExecutableElement( te,

                                                                     ee.getSimpleName() );

                        if( oe != null )

                        {

                            action = oe.getAnnotation( Action.class );

                        }

                    }

                    System.out.printf(

                            "%s Action value = %s\n",

                            ee.getSimpleName(),

                            action == null ? null : action.value() );

                }

            }

        }

        return false;

    }

    public ExecutableElement getExecutableElement( final TypeElement typeElement,

                                                   final Name name )

    {

        TypeElement te = typeElement;

        do

        {

            te = (TypeElement) processingEnv.getTypeUtils().asElement(

                    te.getSuperclass() );

            if( te != null )

            {

                for( ExecutableElement ee : ElementFilter.methodsIn(

                        te.getEnclosedElements() ) )

                {

                    if( name.equals( ee.getSimpleName() ) && ee.getParameters().isEmpty() )

                    {

                        return ee;

                    }

                }

            }

        } while( te != null );

        return null;

    }

Now when we run we get the annotated value on A.run() when we are processing B.run():

[compiler:compile]

Compiling 2 source files to /Users/peter/dev/retep/scratch/target/classes

Scanning Type scratch.A

run Action value = do something

Scanning Type scratch.B

run Action value = do something

The problem with Class

Now this is fine, but what happens if the annotation’s value is Class instead of String? Well the problem here is that Javac does not load classes in the normal manner. In fact it doesn’t at all for classes that are in the source - it’s all contained within a model.

Now say our Action annotation had value defined as Class instead of String. In that case when we call action.value() it would fail:

[compiler:compile]

Compiling 2 source files to /Users/peter/dev/retep/scratch/target/classes

Scanning Type scratch.A

javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror java.lang.Runnable

So we have to find another way to get the value, and there are two available to us. The first is not to use getAnnotation() but getAnnotationMirrors(), and the second is a neat trick with MirroredTypeException.

Solution 1 use getAnnotationMirrors()

This solution is a little long winded but is the most reliable. When getAnnotationMirrors() is used, it returns a set of AnnotationMirror instances, one for each annotation on that Element, so the first step is to locate the correct AnnotationMirror for the annotation you require. The next step is to extract the AnnotationValue’s from that mirror which represents the values stored in the annotation. This is held in a map keyed by an ExecutableElement.

Why ExecutableElement? Well it’s because the annotation values are actually defined as methods - hence why in our Action value is defined as value().

So in the next example we run through the AnnotationMirrors on a method until we find the one for our annotation then run through until we find the required value.

Once we have the AnnotationValue we simply print it to System.out but normally you would use the getValue() method which returns the value as an Object. If the value is an array it returns a java.util.List containing the values. Oh and if the values are of type Class then it returns a TypeMirror or a List of TypeMirrors.

Element actionElement = processingEnv.getElementUtils().getTypeElement(

        Action.class.getName() );

TypeMirror actionType = actionElement.asType();

for( ExecutableElement ee : ElementFilter.methodsIn(

        te.getEnclosedElements() ) )

{

    ExecutableElement oe = ee;

    AnnotationValue action = null;

    while( action == null && oe != null )

    {

        for( AnnotationMirror am : oe.getAnnotationMirrors() )

        {

            if( am.getAnnotationType().equals( actionType ) )

            {

                for( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am.getElementValues().entrySet() )

                {

                    if( "value".equals(

                            entry.getKey().getSimpleName().toString() ) )

                    {

                        action = entry.getValue();

                        break;

                    }

                }

            }

        }

        // Look for the overridden method

        oe = getExecutableElement(

                findEnclosingTypeElement( oe ),

                ee.getSimpleName() );

    }

    System.out.printf(

            "%s Action value = %s\n",

            ee.getSimpleName(),

            action == null ? null : action );

}

Now at first that appears to work, and in most use cases it does - if we have a method thats overridden then we get the annotation values from the overridden method.

However, although its not obvious, if the super type is not part of the same CompilationUnit - i.e. it’s in a third party jar or from a previous call to javac then it will not find anything outside of that CompilationUnit.

The trouble with TypeMirrors

Now the cause on why the solution above fails isn’t obvious. The problem here is actually down to the TypeMirror’s. In the above example we get a TypeMirror for the annotation called actionType then search the AnnotationMirror set of each element using that TypeMirror.

Now TypeMirror acts in a similar way to how Class works at runtime. At run time Class is equal if it’s in the same ClassLoader, so here TypeMirror is equal if it’s in the same CompilationUnit. So the example above fails because they are different instances.

So the solution here is not to use TypeMirror.equals() but to convert the TypeMirror into a String representing the fully qualified class name and use equals() on that String. Now, no matter what  source the super type comes from, it will always match.

Here’s the new version:

final String actionName = Contract.class.getName();

for( ExecutableElement ee : ElementFilter.methodsIn(

        te.getEnclosedElements() ) )

{

    ExecutableElement oe = ee;

    AnnotationValue action = null;

    while( action == null && oe != null )

    {

        for( AnnotationMirror am : oe.getAnnotationMirrors() )

        {

            if( actionName.equals(

                    am.getAnnotationType().toString() ) )

            {

                for( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am.getElementValues().entrySet() )

                {

                    if( "value".equals(

                            entry.getKey().getSimpleName().toString() ) )

                    {

                        action = entry.getValue();

                        break;

                    }

                }

            }

        }

        // Look for the overridden method

        oe = getExecutableElement(

                findEnclosingTypeElement( oe ),

                ee.getSimpleName() );

    }

    System.out.printf(

            "%s Action value = %s\n",

            ee.getSimpleName(),

            action == null ? null : action );

}

Now that one works. The lesson here is to use the String version of TypeElement when searching as two TypeElement’s representing the same class are not always equal.

Solution 2 - Single Class values

Now if your value contains just one Class (i.e. not Class[] ) then there’s a much simpler solution. This one isn’t that obvious, but I found that someone had a similar problem in the sun forums[1]. There the trick is to actually use getAnnotation() and catch the MirroredTypeException. Surprisingly the exception then provides the TypeMirror of the required class:

for( ExecutableElement ee : ElementFilter.methodsIn(

        te.getEnclosedElements() ) )

{

    Action action = ee.getAnnotation( Action.class );

    if( action == null )

    {

        // Look for the overridden method

        ExecutableElement oe = getExecutableElement( te,

                                                     ee.getSimpleName() );

        if( oe != null )

        {

            action = oe.getAnnotation( Action.class );

        }

    }

    TypeMirror value = null;

    if( action != null )

    {

        try

        {

            action.value();

        }

        catch( MirroredTypeException mte )

        {

            value = mte.getTypeMirror();

        }

    }

    System.out.printf(

            "%s Action value = %s\n",

            ee.getSimpleName(),

            value );

}

Notice getTypeMirror() method call? Here’s the output of the above loop:

[compiler:compile]

Compiling 2 source files to /Users/peter/dev/retep/scratch/target/classes

Scanning Type scratch.A

run Action value = java.lang.Runnable

Scanning Type scratch.B

run Action value = java.lang.Runnable

This trick works fine for individual classes, but sadly it does not work for Class[] arrays. According to the javadocs it should work for Class[] as it should then throw the MirroredTypesException instead and that exception contains an alternate method that returns a List of TypeMirrors.

However it doesn’t - it simply throws MirroredTypeException for the first element in the array. I think it’s where it’s running through the array to populate it and the first element is then throwing MirroredTypeException before it gets chance to throw MirroredTypesException.

Conclusion

Well, hopefully this article will save someone hours of trouble when they hit the same problem. I’ve spent about 20 hours of time searching the net and dabbling for these solutions - and at least these solutions use just the documented public APIs.

References

  1. http://forums.sun.com/thread.jspa?threadID=791053

Sunday, 4 January 2009

Using the retepMicroKernel - Part 2

In Part 1 I gave a brief overview of the microkernel and how the application is constructed on disk. In this article I will go through how to actually write an application to run within the retepMicroKernel, from a simple application, one who’s beans are configurable after compile time, to integrating existing Spring applications and ending with how to build the application using Apache Maven.


Firstly, an application is simply a collection of beans deployed by Spring. However unlike a normal Spring application the microKernel provides additional services which make writing an application easier taking away the necessity to write those services into your application and enabling you to concentrate on writing your application.


Writing a deployed bean


Declaring the bean


A bean can be deployed within the kernel in one of two ways - by writing a standard Spring deployment descriptor which we will show later in this article, and by annotating the class with a @Bean annotation.


For example say you have a bean called myBean and you want it to be deployed in your application then simply annotate the class with the @Bean annotation:


import uk.org.retep.kernel.annotations.Bean;


@Bean( name=“myBean” )

public class MyBean

{

// bean implementation

}


Once annotated your bean will be deployed and constructed when it’s first referenced by another bean. Because beans are created lazily, your application must have at least one bean that is not lazily instantiated otherwise your application would do nothing. So for your core bean (or any bean you want to exist at startup) you need to tell the kernel that the bean is to be instantiated at startup. This is simply setting the lazyInit parameter to the @Bean annotation to false, ie.


@Bean( name=“myBean”, lazyInit=false )


In this way the bean is instantiated at startup.


Bean references and initial values


You can define initial values to your bean in two ways, in the constructor and by a bean accessor method. For both methods the kernel supplies two annotations for predefining values in your bean. @Value simply defines a constant value whilst @Reference defines a reference to another deployed bean.


For bean accessor methods, you simply add the annotation to the setter method:


import uk.org.retep.kernel.annotations.Bean;

import uk.org.retep.kernel.annotations.Reference;

import uk.org.retep.kernel.annotations.Value;


@Bean( name=“myBean” )

public class MyBean

{

private int myInteger;

private MyOtherBean myOtherBean;


public int getMyInteger()

{

return myInteger;

}


@Value( “10” )

public void setMyIntegr( finaly int myInteger )

{

this.myInteger = myInteger;

}


public MyOtherBean getMyOtherBean()

{

return myOtherBean;

}


@Reference( “myOtherBean” )

public void setMyOtherBean( final MyOtherBean myOtherBean )

{

this.myOtherBean = myOtherBean;

}

}


For a constructor you simply annotate the parameters of the constructor:


import uk.org.retep.kernel.annotations.Bean;

import uk.org.retep.kernel.annotations.Reference;

import uk.org.retep.kernel.annotations.Value;


@Bean( name=“myBean” )

public class MyBean

{

private int myInteger;

private MyOtherBean myOtherBean;


public MyBean(

@Value( “10” ) final int myInteger,

@Reference( “myOtherBean” ) final MyOtherBean myOtherBean )

{

this.myInteger = myInteger;

this.myOtherBean = myOtherBean;

}

}


Bean lifecycle


As the kernel uses Spring internally it supports the @PostCreate and @PreDestroy annotations for invoking methods when the bean is instantiated or destroyed. However as the Spring deployment descriptor supports defining the methods in the <bean> element, the kernel supplies two additional annotations @Init and @Destroy which like @Bean are detected at compile time so those methods will be called at instantiation or when it’s destroyed.


import uk.org.retep.kernel.annotations.Bean;

import uk.org.retep.kernel.annotations.Init;


@Bean( name=“myBean” )

public class MyBean

{


@Init

public void start()

throws Exception

{

// initialisation code

}

}


Although not really useful, this does mean you can annotate two methods with @PostCreate and @Init and both would be called. The same goes for @PreDestroy and @Destroy. The order these methods are called is indeterminate, hence why this is not really useful.


There is a third lifecycle annotation available - @PostInit. This annotation is unique to the kernel and indicates that the method should be called once all beans have been deployed and the application has been started. This annotation is useful when you want something to happen but you don’t know what beans are going to be available.


For example, say you are writing a desktop application with components implemented as plugins implemented as deployed beans. You have a bean that manages the main JFrame of your application. Your bean would have an @Init method that initialises the JFrame but does not make it visible. You then write each plugin component as a deployed bean with references to your frame bean, and they add themselves to the frame. Finally you then create another method in the frame bean annotated with @PostInit which then pack’s the JFrame and make it visible.


Because of how the kernel works, your plugins can be in additional jar’s within the application’s lib directory, so to add a new plugin you can simply place it’s jar into the applicartion’s lib directory and when the application runs your new plugin is available.


Bean Factories


The kernel supplies two annotations for implementing bean factories - @BeanFactory and @FactoryMethod.


For a deployed bean who’s instance is returned by a static method then you annotate the class with @Bean and the static method with @FactoryMethod. You can imagine this is making a traditional singleton bean deployed:


import uk.org.retep.kernel.annotations.Bean;

import uk.org.retep.kernel.annotations.FactoryMethod;


@Bean( name=“myBean” )

public class MyBean

{

private static final MyBean INSTANCE = new MyBean();


@FactoryMethod

public static MyBean getInstance()

{

return INSTANCE;

}


private MyBean()

{

}

}


The other type of factory is where the bean is returned by a getter method of another deployed bean. For example here MyBean is created by MyAnotherBean.getMyBean()


import uk.org.retep.kernel.annotations.Bean;

import uk.org.retep.kernel.annotations.Reference;

import uk.org.retep.kernel.annotations.Value;


@Bean( name=“myBean” )

@BeanFactory( factory=“myAnotherBean”, method=“getMyBean” )

public class MyBean

{

}


@Bean( name=“myAnotherBean” )

public class MyAnotherBean

{

private MyBean myBean;


public MyBean getMyBean()

{

return myBean;

}


}


Using Spring deployment descriptors


For existing applications that have their beans defined in a standard Spring deployment descriptor, the kernel can deploy those beans as long as the descriptor is placed in the etc directory. If the application is called myapp, then this descriptor should be called etc/myapp.xml, so if that file exists, it’s beans are included with any beans that have been annotated. Spring will then determine the deployment order and load the application.


Internally the annotations actually generate a standard Spring deployment descriptor, however this is placed in the jar file as META-INF/services/uk.org.retep.kernel.Kernel.xml When the kernel starts Spring it looks for all instances of this file along side the myapp.xml file to get the complete set of beans to deploy. This is how the plugin example above would work - adding a new jar file into the classpath makes it’s beans deployable automatically.


Now an alternate reason to provide a standard Spring deployment descriptor is for beans that require configuring after compilation, or for providing beans in classes in third-party jar files not compiled with the annotations.


For example, you have a bean that will open a socket on a port and listen for new connections. Although you could define that bean with the annotations, doing so would mean it would always use the same port number. To make it configurable you would write the bean without any annotations and define the bean in the traditional way in the myapp.xml file.


Logging


The kernel uses Apache’s log4j framework for logging. To support log4j, you can configure the file myapp.log4j.xml and the kernel will use that configuration for log4j. If the file is not available, the kernel will use a default configuration which logs to the console.


Here’s an example of logging to a file - in this case system.log in the current directory when the application is started:


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

<!DOCTYPE log4j:configuration SYSTEM “log4j.dtd”>

<log4j:configuration xmlns:log4j=”http://jakarta.apache.org/log4j/“>

    <appender name=”FILE” class=”org.apache.log4j.DailyRollingFileAppender”>

        <param name=”File” value=”system.log”/>

        <param name=”Append” value=”true”/>

        <param name=”Threshold” value=”INFO”/>

        <param name=”DatePattern” value=”’.’yyyy-MM-dd”/>

        <layout class=”org.apache.log4j.PatternLayout”>

            <param name=”ConversionPattern” value=”%d %-5p [%c] %m%n”/>

        </layout>

    </appender>

    <root>

        <appender-ref ref=”FILE”/>

    </root>

</log4j:configuration>


Building the application with maven


To compile the application with the annotations simply ensure that the kernel Jar file is present in the classpath. Doing so ensures that the annotation processors provided by the kernel run within javac and it will generate all the metadata required by the kernel at runtime.


However unless you are using Apache Maven you have to build the application yourself, however the kernel provides a Maven mojo that will build your application for you, ensuring that the relevent artifacts are in the correct place.


Say you have your application called myapp and you have the following structure for your sources:


myapp/pom.xml

myapp/src/main/java

myapp/src/main/etc


As for norml maven projects the java directory contains your source code, the etc directory contains the configuration destined to go into the etc directory of your application.


As for pom.xml, here’s an example that would build a simple application:


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

<project xmlns=”http://maven.apache.org/POM/4.0.0” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0                       http://maven.apache.org/xsd/maven-4.0.0.xsd”>

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.mydomain</groupId>

    <artifactId>myapp</artifactId>

    <name>myApp</name>

    <version>1.0-SNAPSHOT</version>


<!-- The maven repositories -->

    <repositories>

        <repository>

            <id>maven.retep.org</id>

            <name>retep.org Maven 2 Repository</name>

            <url>http://maven.retep.org/content/groups/public</url>

        </repository>

    </repositories>

    <pluginRepositories>

        <pluginRepository>

            <id>maven.retep.org</id>

            <name>retep.org Maven 2 Repository</name>

            <url>http://maven.retep.org/content/groups/public</url>

        </pluginRepository>

    </pluginRepositories>


<!-- the minimum dependencies -->

    <dependencies>

        <dependency>

            <groupId>junit</groupId>

            <artifactId>junit</artifactId>

            <version>3.8.1</version>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>uk.org.retep</groupId>

            <artifactId>retepTools</artifactId>

            <version>[8.12,)</version>

        </dependency>

        <dependency>

            <groupId>uk.org.retep.microkernel</groupId>

            <artifactId>core</artifactId>

            <version>[8.12,)</version>

        </dependency>

    </dependencies>

    <build>

        <plugins>


<!-- All retep projects need JDK 1.6 as a minimum -->

            <plugin>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>2.0.2</version>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                </configuration>

            </plugin>


<!-- plugin to generate the final application -->

            <plugin>

                <groupId>uk.org.retep.microkernel</groupId>

                <artifactId>maven</artifactId>

                <executions>

                    <execution>

                        <id>assemble-application</id>

                        <phase>package</phase>

                        <goals>

                            <goal>assemble-application</goal>

                        </goals>

                        <configuration>

                            <applicationName>myapp</applicationName>

                            <!-- generate a zip containing the application -->

                            <zip>true</zip>

                            <!-- generate a tar containing the application -->

                            <tar>false</tar>

                            <!-- generate a tar compressed with GZip containing the application -->

                            <tarGz>true</tarGz>

                            <!-- generate a tar compressed with BZip2 containing the application -->

                            <tarBZip2>false</tarBZip2>

                        </configuration>

                    </execution>

                </executions>

            </plugin>

        </plugins>

    </build>

</project>


The pom above defines a reference to my public repository, a dependency on the kernel nd my tools library (which all of my projects use), sets the jdk to 1.6 and then uses the kernel’s maven mojo. The mojo generates the application ready to run under the target directory.


Under the configuration element the applicationName property sets the final application name, in this case myapp. With this set it would generate the following structure under the target directory:


myapp-1.0-SNAPSHOT/bin

myapp-1.0-SNAPSHOT/etc

myapp-1.0-SNAPSHOT/lib

myapp-1.0-SNAPSHOT/lib/myapp


The other configuration properties define how the application is bundled. Here we have tarGz and zip set to true so it would generate .tgz and .zip archives of the built application. The tar property is false but if it was true then an uncompressed .tar archive would be generated. Similarly tarBZip2 indicates if a .tar.bz2 archive is generated.


So with the above settings set to true then under target will be myapp-1.0-SNAPSHOT.zip and myapp-1.0-SNAPSHOT.tgz archives.


Note: Currently the generated application is not deployed to the local or remote repositories as an artifact. This is planned for a future release as soon as I can work out how to get maven to include additional artifacts to the deployment.


JNDI


The kernel provides a simple in-memory JNDI server which can be used by an application. By default it exposes all deployed beans within JNDI by prefixing the bean name with “kernel/” so if you have a bean called myBean then it’s accessible from JNDI using the name kernel/myBean


Binding by annotations


The kernel provides the @LocalBinding annotation which when applied against a bean’s class defines the name for binding the bean into JNDI.


Binding legacy beans into JNDI


In addition to the automatic JNDI binding provided by the kernel, you can bind a bean into any name. Usually this is used by binding a DataSource into JNDI with the DataSource deployed from within Spring. For example we have a DataSource that connects to a PostgreSQL database called mydb and the DataSource will be called ds/mydb.


To do this, within myapp.xml we define two beans. One is the actual DataSource with all of its required configuration - we will call it realds/mydb for this example. The other is a bean provided by the kernel called JNDIBinder. We will call tht jndi/mydb and it will bind the DataSource into JNDI. Once done then existing code expecting to use JNDI can access the DataSource using ds/mydb


<!-- The DataSource provided by PostgreSQL -->

<bean name="realds/tux" class="org.postgresql.ds.PGPoolingDataSource">

    <property name="serverName" value=“postgresql.mydomain.com"/>

    <property name="portNumber" value="5432"/>

    <property name="databaseName" value="mydb"/>

    <property name="user" value="username"/>

    <property name="password" value="password"/>

</bean>


<!-- Deployment bean that will bind the DataSource into JNDI on startup -->

<bean name="jndi/mydb" class="uk.org.retep.kernel.naming.JNDIBinder" lazy-init="false">

    <property name="jndiName" value="ds/mydb"/>

    <property name="value" ref="realds/mydb"/>

</bean>


JMX


If a deployed bean implements an interface who’s name ends with MBean or MXBean or if the interface is annotated by javax.management.MXBean then the kernel will deploy that bean into the local JMX server.  The ObjectName defaults to retep.kernel.beans:id= and the bean name unless the bean is annotated with @ObjectName in which case it will use that ObjectName when registering into JMX.


Thats all for Part 2. The next article will show how to use the optional manager module which provides a web interface to your application utilising the built in http server provided by Java 6.

How to change the Blue Screen of Death into another colour

We have all had a BSOD (Blue Screen Of Death) when something catastrophic has happened with Windows - which is usually when you try to do anything useful, but if you get tired of it being the standard Blue or if you have a visual imparement so the default settings are useless for you, here’s how to change it.


First open the SYSTEM.INI file found in the %systemroot% folder (usually C:\Windows) and locate the [386enh] section.


Add the following two entries if they are not present:


MessageBackColor=

MessageTextColor=


Each of those entries take a single hexadecimal digit defining the colour:

  • 0 - Black
  • 1 - Blue
  • 2 - Green
  • 3 - Cyan
  • 4 - Red
  • 5 - Magenta
  • 6 - Yellow
  • 7 - White
  • 8 - Grey
  • 9 - Bright blue
  • A - Bright green
  • B - Bright cyan
  • C - Bright red
  • D - Bright magenta
  • E - Bright yellow
  • F - Bright white


So to change it to Cyan and bright white text, then use the following:


MessageBackColor=3

MessageTextColor=F


The settings will take effect the next time you restart Windows.


NB: The values must be in upper case hence using F and not f in the above example.