Adding a Runtime Extension Point

From DOC

Jump to: navigation, search

When writing EJB code in a plug-in environment, you may need to allow custom beans to be called from your session bean without knowing the name of those beans. In essence, an extendable bean, known to you, needs to call one or more other beans, extensions, whose names are not know to you.

Since the code being plugged-in to your bean cannot be known in advance, The Tolven Plugin Framework provides a convenient mechanism to allow this to work without creating unnecessary dependencies. The following steps are needed to make this work:

  1. In most cases, you will want to require that the extension bean(s) implement some interface specified by you.
  2. The extendable bean will acquire a list of interface names specified in a properties file.
  3. Write extension code that will be called by the extendable bean
  4. Specify one or more beans in the appropriate properties file
  5. Add the extension code to Tolven. See: Customize tolvenEJB Plugin

We will now take a deeper look at each of these steps.

Contents

Creating an Interface

Your extendable bean will need to call each of the extension beans. We will use a simple interface as an example:

public interface Auditor {
  public void doAudit( String text );
}

Each of the extension beans will need to implement this interface.

Making a bean extendable

This is typically done in two methods. One method initializes the list of interfaces and the other dispatches to those interfaces.

An initializer method does the job of looking up the list of extensions.

 public final static String AUDITOR_NAME = "auditorJNDI";
 private String auditors[];

 public void initializeAuditors() {
   try {
     if (auditors==null) {
        Properties properties = new Properties();
        String propertyFileName = this.getClass().getSimpleName()+".properties"; 
        properties.load(this.getClass().getResourceAsStream(propertyFileName));
        String auditorNames = properties.getProperty(AUDITOR_NAME);
        auditors = auditorNames.split(",");
      }
   } catch (Exception e) {
      throw new RuntimeException( "Error initializing auditors", e);
   }
 }

The dispatcher will call each of the specified extensions when requested.

public void dispatchToAuditors(String text) throws Exception {
   initializeAuditors();
   InitialContext ctx = new InitialContext();
   for (String auditorName : auditors ) {
      Auditor auditor = (Auditor) ctx.lookup(auditorName);
      auditor.doAudit( text );
   }
}

The dispatcher should not depend on the order or number of extensions. If a priority scheme is needed, then you should provide a two-phase approach where the first phase asks each extension about its intent and then in the second phase, call one or more of the extensions to actually perform the action based on an analysis of those intentions.

Writing the extension

The extension will look like any other EJB session bean. It will contain an interface as well as an implementation bean. the interface will extend the interface expected by the extendable class (Auditor).

public interface MyAuditor extends Auditor {

}

The implementation will be a regular session bean:

@Stateless
@Local( MyAuditor.class )
public class MyAuditorBean implements MyAuditor {
 private Logger logger = Logger.getLogger(this.getClass());

 public void doAudit( String text ) {
   logger.info("Got this " + text);
 }
}

Configuring the classes to be included in the properties file

The manifest of the plugin carrying each extension will need to specify that it should be included in the list of audit classes called by the extendable class.

  <extension id="property2" plugin-id="org.tolven.component.tolvenejb" point-id="property">
    <parameter id="class" value="full-name-of-extendable-class" />
    <parameter id="name" value="auditorJNDI" />
    <parameter id="value" value="java:global/tolven/myAuditor!org.tolven.MyAuditor" />
  </extension>

Add the extension code to Tolven

As usual, the manifest of the plugin containing the extension must also require that it be included in the EJB jar file for inclusion in the EAR file.

<extension id="ejbclasses" plugin-id="org.tolven.component.tolvenejb" point-id="classes">
  <parameter id="dir" value="ejb/classes" />
</extension>

Transaction Semantics

The standard behavior in Tolven is that extensions will execute as part of a larger transaction. In other words, extensions should never try to begin a new transaction or commit the current transaction. If the extension initiate an exception and wants to set rollbackOnly, it will apply to the entire transaction, not just the extension.

In other respects, an extension bean has all the power of any normal Session Bean and can even be its own extendable bean with additional extensions.

Threading Issues

The EJB container handles threading transparently. Your code should be written as if it were single threaded. However, it is important to follow certain guidelines:

  1. Do not use static variables
  2. Each instance of you class will operate in a single thread. Therefore, it is safe to "remember" extensions in an instance variable for the life of the class instance.
Personal tools