Retep MicroKernel

uk.org.retep.kernel.annotations
Annotation Type PostInit


@Target(value=METHOD)
@Retention(value=RUNTIME)
public @interface PostInit

A method marked with this annotation will be called after the application has been started.

This is the same as the @Init and @PostConstruct annotations except that when this method is run, all beans within the application have been deployed.

The methods are run in the order that they were deployed.

Only one method in the bean can be annotated by this annotation.

For example: You have an application where you have plugin components that automatically register themselves to a plugin manager bean. Each plugin provides a Swing JComponent to display within a JFrame which is provided by the manager bean.

First we'll create an interface defining a plugin.

 public interface Plugin {
     JComponent getComponent();
 }
 

Now we'll define a plugin for this component. Here it has a dependency on the pluginManager bean and we annotate the init() method with @Init. The init() method then creates the component and registers the plugin with the PluginManager bean. We also disable lazy initialisation in the @Bean annotation because no other bean depends on our plugin - without this the plugin will never start.

 @Bean( name="aPlugin", lazyInit=false )
 public class SimplePlugin implements Plugin {
     private PluginManager pluginManager;
     private JPanel panel;
     private JTextField url;
     private JButton button;

     public PluginManager getPluginManager() {
         return pluginManager;
     }

     @Reference( "pluginManager" )
     public void setPluginManager( final PluginManager pluginManager ) {
         this.pluginManager = pluginManager;
     }

     @Init
     @DispatchThread( invocationType=InvocationType.INVOKE_AND_WAIT )
     public void init() {
         // create subcomponents here
         panel = new JPanel();
         panel.setLayout( new FlowLayout() );
         panel.add( new JLabel( "Url" ) );
         url = new JTextField( "http://retep.org/" );
         panel.add( url );
         button = new JButton( "Go" );
         panel.add( button );

         // register the plugin
         getPluginManager().registerPlugin( this );
     }

     public JComponent getComponent() {
         return panel;
     }
 }
 

Now we have our PluginManager. Here it creates a JFrame, a JPanel to contain our plugins and a PostInit method to finally pack and display the JFrame.

 @Bean( name="pluginManager", lazyInit=false )
 public class PluginManager {
     private JFrame frame;
     private JPanel pluginPanel;

     @Init
     @DispatchThread( invocationType=InvocationType.INVOKE_AND_WAIT )
     public void init() {
         // create the frame for the application but don't show it
         frame = new JFrame( "My Application" );
         pluginPanel = new JPanel();
         pluginPanel.setLayout( new FlowLayout() );
         frame.getContentPane().add( pluginPanel, BorderLayout.NORTH );
     }

     @PostInit
     @DispatchThread( invocationType=InvocationType.INVOKE_LATER )
     public void makeVisible()
     {
         // Our application is now running so pack and display it to the user
         frame.pack();
         frame.setVisible( true );
     }

     @DispatchThread( invocationType=InvocationType.INVOKE_AND_WAIT )
     public void registerPlugin( Plugin plugin ) {
         // here just add it to the pluginPanel
         pluginPanel.add( plugin.getComponent() );
     }
 }
 

Note: Because the above example uses Swing components, you must access those components from within the Swing dispatch thread (even when constructing them) because swing is single threaded. The @DispatchThread annotation is part of the retepTools library and ensures that the methods are invoked within the Swing thread rather than the thread that Spring is running under.

Author:
peter
See Also:
Bean, Init, DispatchThread


Retep MicroKernel

Copyright © 2007-2009. All Rights Reserved.