Last updated September 14, 2009 08:43, by Peter Mount
Feedicon  

Deploying a bean

There's two methods available to deploy a bean within the kernel environment. The first is to create traditional Spring xml configuration and to place that xml under the applications etc directory, the second is by annotating the bean's source, which is what this document describes.

The traditional xml method is supported because this is useful for beans who's configuration you want to be able to change post compilation (for example deploying DataSource's) or for beans in third party libraries which cannot be annotated.

How beans are deployed

The kernel provides a set of annotations which you can use to define how that bean is deployed. Then when javac compiles those classes, an annotation processor generates a spring xml file and places it into the jar's META-INF/services directory. At run time the kernel then uses that xml file to deploy your beans.

Deploying a simple bean

The simplest way to deploy a bean is to annotate it with @Bean providing just the beans name within the kernel:

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

@Bean( name = "myBean" )
public class MyBean
{
}

This simple example will cause an instance of MyBean to be deployed into the kernel. Now this bean is lazy, so it will not be instantiated until it is referenced by another deployed bean - so if nothing else uses it then it would never be instantiated within your application.

If you need the bean to be eager - i.e. it will always be instantiated by the kernel at startup then you simply set the lazyInit parameter on @Bean to false:

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

@Bean( name = "myBean", lazyInit = false )
public class MyBean
{
}

Service Beans

As of 9.10, a new class of bean is available, in the guise of a @ServiceBean. Service beans are beans which provide some core service, rather than a compontent of the application. A ServiceBean is effectively the same as @Bean with lazyInit set to false. Having a separate annotation makes documentation easier as you can easily identify application vs service beans from the javadocs.

Example of @ServiceBean in the form of a JSR311 Rest Service

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import uk.org.retep.kernel.annotations.ServiceBean;

@Path( "/myPath" )
@ServiceBean( name="kernel/rest/kernel" )
public class MyBean
{
    @GET
    @Produces( "text/plain" )
    public String getApplicationName()
    {
        return getClass().getSimpleName();
    }
}

Bean life cycle

A bean can have methods invoked at various points within it's life cycle simply by annotating those methods.

Initialisation

When a bean is initialised you can have a method invoked so that it can perform some form of initialisation by annotating it with either @Init or @PostConstruct. Once annotated this method is called once all referenced beans have been injected into your bean.

Bean initialisation

The two annotations have different behaviours. @Init represents the init attribute within Spring's bean element in the xml whilst @PostConstruct is detected at run time. Also @PostConstruct can be inherited so it can be defined in a super class whilst @Init can only be used in the same class as the @Bean annotation.

Example using @Init

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

@Bean( name = "myApp", lazyInit = false )
public class App
{

    @Init
    public void start()
    {
        // perform initialisation here
    }
}

Example using @PostConstruct

import javax.annotation.PostConstruct;
import uk.org.retep.kernel.annotations.Bean;

@Bean( name = "myApp", lazyInit = false )
public class App
{

    @PostConstruct
    public void start()
    {
        // perform initialisation here
    }
}

You may add a throws clause to your method. If you do then if that Exception is thrown it will be logged and the application will shutdown.

Post initialisation

The @PostInit annotation is detected at run time and marks a method to be called once the application has deployed and started all beans. It is used when you need to know that the application has been started successfully.

For example you have a desktop application and you want the associated JFrame to be made visible only when your application has started and is ready for use.

import javax.swing.JFrame;
import uk.org.retep.kernel.annotations.Bean;
import uk.org.retep.kernel.annotations.Destroy;
import uk.org.retep.kernel.annotations.Init;
import uk.org.retep.kernel.annotations.PostInit;

@Bean( name = "myApp", lazyInit = false )
public class App
{
    private JFrame frame;

    @Init
    public void start()
    {
        frame = new JFrame();
    }

    @PostInit
    public void show()
    {
        frame.pack();
        frame.setVisible( true );
    }

    @Destroy
    public void stop()
    {
        if( frame!=null )
        {
            frame.setVisible( false );
        }
    }
}

Important Note The above example is incorrect as it accesses the Swing JFrame object outside of the Swing/AWT thread. This is intentional to keep the example simple.

Destruction

Like initialisation you can annotate a method so that it is called when the application shuts down. This method will only be called if your bean has been deployed and it initialised correctly (if initialisation was used).

There are three annotations available - @PreShutdown, @Destroy and @PreDestroy.

Pre-Shutdown

@PreShutdown marks a method that is called as soon as the application starts to shutdown. When it is called, all beans that have been deployed are still present and it's primary use is to complement the @PostInit annotation and as such close resources which require the entire application to be running - like clustering. Example of @PreShutdown

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

@Bean( name = "myApp", lazyInit = false )
public class App
{
    private boolean running = false;
    private Writer writer;

    /**
     * Send xml over to network. this only sends over some network
     * once the application is running, not during startup/shutdown.
     */
    public void send( String xml )
        throws IOException
    {
        if( running ) writer.write( xml );
    }

    @Init public void start()
        throws Exception
    {
        // Create a socket of some sort
        writer = new Writer( );
    }

    @PostInit
    public void postInit()
    {
        running = true;
    }

    @PreShutdown
    public void preShutdown()
    {
        running = false;
    }

    @Destroy
    public void destroy()
    {
        // release any resources
        writer.close();
    }
}

Bean destruction

@Destroy maps to the bean elements destroy attribute whilst @PreDestroy is detected at run time. The inheritance also matches those in initialisation.

Example of @Destroy

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

@Bean( name = "myApp", lazyInit = false )
public class App
{
    @Destroy
    public void stop()
    {
        // release any resources
    }
}

Example of @PreDestroy

import javax.annotation.PreDestroy;

@Bean( name = "myApp", lazyInit = false )
public class App
{
    @PreDestroy
    public void stop()
    {
        // release any resources
    }
}

Deploying singletons

You may have a bean that uses the Singleton pattern. Now this pattern is obsolete with Spring as you would usually just reference it in the classes you are using it from, however if it's used by legacy or non spring code then you need to annotate it with both the @Bean and @FactoryMethod annotations so that the singleton reference is also deployed within Spring.

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

@Singleton
@Bean( name = "myApp", lazyInit = false )
public class App
{

    private static final App INSTANCE = new App();

    @FactoryMethod
    public static App getInstance()
    {
        return INSTANCE;
    }

    private App()
    {
    }
}

Bean factories

Occasionally you have a deployed bean that provides additional beans which you want deployed at the same time. This can be accomplished by providing getter methods and annotating those methods with @Bean.

In this example our myApp bean also defines myAppName which is provided by the getMyAppname method. Spring will call that method to get the bean instance - in this case a simple String:

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

@Bean( name = "myApp", lazyInit = false )
public class App
{

    private String myAppName;

    @Bean( name = "myAppName" )
    public String getMyAppName()
    {
        return myAppName;
    }
}

  • Mysql
  • Glassfish
  • Jruby
  • Rails
  • Nblogo
Terms of Use; Privacy Policy;
© 2010, Oracle Corporation and/or its affiliates
(revision 20120518.3c65429)
 
 
Close
loading
Please Confirm
Close