Skip navigation.
Arch2Arch Tab BEA.com

Building an Advanced Beehive Control

by Lawrence Jones
01/10/2006

Abstract

Beehive is a new Apache project aimed at making J2EE programming easy. The controls sub-project provides a model for programming business functionality that leverages lightweight JavaBeans and declarative configuration through JDK1.5 annotations.

The programmer writes a simple interface and one or more implementations of the interface that provide the business functionality. At the programmer's choice, the control can provide for extensible versions of itself—which again are simple annotated interfaces. The business functionality is then usable from many different places, each instance of which can be declaratively configured either through the annotations or through automatically generated property setters on the bean. This latter approach also lends itself to configuration by administrators at deployment time and programmatic configuration at runtime.

This article presents a behind-the-scenes look at how controls are built. It examines the role of the annotation processor, artifact generation, and eventual control assembly. By understanding this process you will be in a strong position to understand how the control architecture works in general and to build advanced controls where the control client needs to be customized to the controls it uses.

Introduction to Simple Controls and Control Extensions

This section introduces how controls are created and referenced. I'll start by creating a simple control, move on to how to reference a control (how to create a control client), and finish by describing how to create and use the more advanced form of controls, control extensions. This section lays the groundwork for looking at how these artifacts are processed in the build process.

Simple controls

A simple control consists of a public interface file and an implementation file. The Control Public Interface (CPI) file is defined as a file (with extension .java) containing a Java interface with the annotation @org.apache.beehive.controls.api.bean.ControlInterface applied to the interface. A Control Implementation (CI) file is defined as a file (with extension either .java or .jcs) containing a public Java class with the annotation @org.apache.beehive.controls.api.bean.ControlImplementation applied to the class.

Suppose you have a CPI com.dev2dev.controls.HelloWorld.java and a CI com.dev2dev.controls.impl.HelloWorldImpl.jcs you wish to use as the implementation. Then the top of the HelloWorld.java file looks like this:

package com.dev2dev.controls;

import org.apache.beehive.controls.api.bean.ControlInterface;

@ControlInterface (
 defaultBinding = "com.dev2dev.controls.impl.HelloWorldImpl"
)
public interface HelloWorld
{
 public void doSomething();
 .
 .
 .
}

The CI must implement the CPI. An example of an implementation is shown below:

package com.dev2dev.controls.impl;

import com.dev2dev.controls.HelloWorld;
import org.apache.beehive.controls.api.bean.ControlImplementation;

@ControlImplementation (
 assembler = HelloWorldAssembler.class
)
public class HelloWorldImpl implements HelloWorld
{
 public void doSomething()
 {
 .
 .
 .
 }

 .
 .
 .
}

The assembler member of the @ControlImplementation annotation above is an optional member defining a class that can be called at assembly time (see more on this subject later in this article).

Control clients

A Control Client (CC) is any file that utilizes a control. The normal way of doing this is to define an instance variable as a control by annotating it with the @org.apache.beehive.controls.api.bean.Control annotation:

package com.dev2dev.control.clients;

import org.apache.beehive.controls.api.bean.Control;
import com.dev2dev.controls.HelloWorld;

public class MyControlClient
{
 @Control
 private HelloWorld _helloWorldControl;
 
 public void callControl {
 _helloWorldControl.doSomething();
 }

 .
 .
 .
}

The inclusion of the @Control annotation (or a similar one called @ControlReferences) results in the generation of a Control Client Initializer class. This class is called by the runtime before the control is accessed, and results in the _helloWorldControl variable being initialized such that a call to the control is properly passed into the control architecture.

Control extensions

If the resource that you wish to access through the control is configurable (for example, a database control where you want to configure which database table to access, or a Web service control where you want to configure which Web service you want to access), then you want to make use of extensible controls.

A control indicates that extensions to itself are allowed via the CI. The CI must additionally implement the interface org.apache.beehive.controls.api.bean.Extensible that defines one method:

public Object invoke(Method method, Object[] args) throws Throwable;

This method then gets called whenever a method on the control extension is invoked.

A Control Extension (CE) file is defined as a file (with extension .java or .jcx) containing a Java interface with the annotation @org.apache.beehive.controls.api.bean.ControlExtension applied to the interface. The extension interface must extend the CPI. So, for instance, an extension to the above HelloWorld CPI called MyHelloWorld looks like this:

package com.dev2dev.control.extensions;

import com.dev2dev.controls.HelloWorld;
import org.apache.beehive.controls.api.bean.ControlExtension;

@ControlExtension
public interface MyHelloWorld extends HelloWorld
{
 public void doSomethingElse();
 .
 .
 .
}

At runtime, any invocation of those methods causes the CI's invoke() method to be called. The java.lang.reflect.Method you called on the CE (the doSomethingElse() method above) and the arguments to that method are passed as arguments to the invoke() method. Therefore, although CEs can be created long after the CI was authored, it is the author of the CI that decides what an invocation of those methods will do. It can ignore the call completely, throw an exception, take action dependent solely on the method and its arguments, or, more commonly, take action dependent on the method name, its arguments, and any annotations that are applicable either to that method or to the CE as a whole.

Take for instance DatabaseControl. The CPI consists of an interface defining general things that are useful for access to all database tables (getConnection()). The CI provides an implementation of those methods and also an implementation of the invoke() method.

You could then define CustomerDatabaseControl—an extension of DatabaseControl—that provides additional methods that are appropriate only when accessing the CUSTOMER database table. An annotation on each method could define the precise SQL to be executed when that method was invoked and the CI invoke() method simply looks up that annotation, executes the SQL, and provides the "glue" to pass in the appropriate parameters and return the results as a typed class.

A control client that uses a control extension looks identical to that for a simple control. The only difference is the name of the class to which the member variable points:

package com.dev2dev.control.clients;

import org.apache.beehive.controls.api.bean.<small>Control</small>;
import com.dev2dev.control.extensions.MyHelloWorld;

public class MyControlClient
{
 @Control
 private MyHelloWorld _myHelloWorldControl;

 
 public void callControl {
 _myHelloWorldControl.doSomethingElse();
 }

 .
 .
 .
}

Pages: 1, 2

Next Page »

Article Tools

Email E-mail
Print Print
Blog Blog

Related Products

Check out the products mentioned in this article:

Related Technologies

Bookmark Article

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit