Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Implementing an EJB3-based endpoint for Mule

By Savas Ali Tokmen, Bull S.A.S.

About Mule, JASMINe and EJB3 support


Mule is a light-weight integration framework for Java based on messaging platforms. Its major feature is
pluggable connectivity and data transformation together with flexible routing; with various connectivity
options (VM, TCP, HTTP, JMS tens in total) provided out of the box.

The JASMINe project aims to develop an administration tool dedicated to Java EE, MOM or SOA
distributed applications in order to facilitate the job of the system administrator. JASMINe uses Mule as
an event switch: various JASMINe components (logging, analysis, decision-making, storage, etc.) use it
for messaging.

One feature thats been unfortunately been found missing by many is an EJB3 connector. One point of
view for an EJB3 connector is that the connectors aim is to obtain a reference to a stateful or a stateless
EJB. This document details one such implementation.

Implementation
The implementing class works the following way:

- The connectors configuration, i.e. the environment to use when creating the InitialContext
and the name of the EJB to look for, is set using a standard Java Map instance (note that Mule
already provides methods for describing this map in the mule-config.xml file).
- At connection, the endpoint sets this configuration, looks up for the EJB and stores the EJB
reference.
- At disconnection, the connectors nulls the EJB reference and the garbage collector will
automatically end connection.

Usage
A user of this class needs to take the following actions:

1. Inherit from the MuleEJB3Wrapper template class and specify the type of the stateful or
stateless EJB to look for.
2. In the Mule configuration, specify the connectors properties:
a. All Context options, for example "Context.INITIAL_CONTEXT_FACTORY", by
putting the adequate entry in the Map.
b. The name of the EJB to look for, using the "Wrapper.LOOKUP_BEAN" key string.
3. Call any method on the EJB using the inherited getBean() method.

1
Example
Heres a concrete example detailing one usage:

The class:
/**
* A wrapper class that accesses JasmineEvent objects via EJB3.
*/
public class JasmineEventEJB3Wrapper extends MuleEJB3Wrapper<JasmineEventSLBRemote> {
/**
* Saves each event detail in a JASMINe Event.
*
* @param e JasmineEvent to save.
*/
public void saveJasmineEvent(final JasmineEvent e) {
for(JasmineEventDetails d: e.getEvents()) {
getBean().saveEvent(new JasmineEventEB(e.getDomain(), e.getServer(), d.getSource(),
d.getProbe(), d.getValue(), d.getTimestamp()));
}
}
}

The configuration:
<!-- EJB3 Wrapper for JasmineEvent messages -->
<mule-descriptor name="JasmineEventEJB3Wrapper"
implementation="org.ow2.jasmine.monitoring.eventswitch.endpoints.JasmineEventEJB3Wrapper">
<inbound-router>
<endpoint address="vm://JasmineEventEJB3Wrapper"/>
</inbound-router>
<properties>
<map name="configuration">
<property name="Context.INITIAL_CONTEXT_FACTORY"
value="org.ow2.easybeans.component.smartclient.spi.SmartContextFactory"/>
<property name="Wrapper.LOOKUP_BEAN"
value="org.ow2.jasmine.monitoring.eventswitch.beans.JasmineEventSLBImpl_org.ow2.jasmine.monitoring.eve
ntswitch.beans.JasmineEventSLBRemote@Remote"/>
</map>
</properties>
</mule-descriptor>

MuleEJB3Wrapper source code


This source code is part of the JASMINe projects Event Switch, http://jasmine.ow2.org/
import org.mule.umo.UMOException;
import org.mule.umo.endpoint.EndpointException;
import org.mule.umo.lifecycle.Startable;
import org.mule.umo.lifecycle.Stoppable;

/**
* Defines an abstract EJB3 wrapper for Mule.
*
* @param <BeanType> Type of bean accessed using this wrapper. This must be
* set to the remote interface of the bean, bean can be
* stateful or stateless.
*/
public class MuleEJB3Wrapper<BeanType> implements Startable, Stoppable {
/**
* Reference to the bean.
*/
private BeanType remote = null;

/**
* Configuration.
*
* @see MuleEJB3Wrapper#setConfiguration(Map)
*/
private Map<String, String> configuration = null;

2
/**
* Map containing Context configuration matches.
*/
private static Map<String, String> keys = null;
static {
keys = new TreeMap<String, String>();
for(Field f : Context.class.getFields()) {
try {
if(f.getType().equals(java.lang.String.class)) {
keys.put(f.getName(), (String) f.get(null));
}
} catch(Exception e) {
// Nothing
}
}
}

/**
* Sets the configuration to use for the EJB connection.
*
* @param conf Configuration: configures all Context environment
* variables as well as the object name to look for.
* It contains mappings to:
* - Any number of string constants defined in Context.
* Example: to set the Context.INITIAL_CONTEXT_FACTORY
* on the Map conf to factory, use:
* conf.put("Context.INITIAL_CONTEXT_FACTORY", factory);
* - The "Wrapper.LOOKUP_BEAN" key, the value of which is
* looked up on the server and set as remote bean. That
* bean is at @link MuleEJB3Wrapper#getBean()}.
*/
public final void setConfiguration(final Map<String, String> conf) {
configuration = conf;
}

/**
* @return Reference to the stateful or stateless bean. Don't store it.
*
* @throws NullPointerException If bean is not set.
*/
protected final BeanType getBean() throws NullPointerException {
if(remote == null) {
throw new NullPointerException("Bean is null: make sure setConfiguration and "
+ "start have been called before calling getBean");
}
return remote;
}

/**
* Obtains the reference to the wanted stateless or stateful bean
* using a given configuration. This will create the initial Context
* and set the bean reference. If no security manager has been defined,
* the default RMI security manager will be created.
*
* @see MuleEJB3Wrapper#setConfiguration(Map)
* @see MuleEJB3Wrapper#getBean()
*
* @throws NamingException On naming failure.
* @throws IOException On configuration file failure.
*/
public void connect() throws NamingException, IOException {
if (System.getSecurityManager() == null) {
if(System.getProperty("java.security.policy") == null) {
File temp = File.createTempFile("java.security.policy.", ".tmp");
FileOutputStream s = new FileOutputStream(temp);
s.write("grant { permission java.security.AllPermission; };".getBytes());
s.close();
System.setProperty("java.security.policy", temp.toString());
}
System.setSecurityManager(new RMISecurityManager());
}
Hashtable<String, Object> env = new Hashtable<String, Object>(configuration.size() - 1);
for(String k: keys.keySet()) {
String value = configuration.get("Context."+k);
if(value != null) {
env.put(keys.get(k), value);
}
}
Context initialContext = new InitialContext(env);
remote = (BeanType) initialContext.lookup(configuration.get("Wrapper.LOOKUP_BEAN"));
}

/**
* Sets the reference to the wanted stateless or stateful bean to null.
*/
public void disconnect() {
remote = null;
}

3
/**
* Calls {@link MuleEJB3Wrapper#connect()}.
*
* @see org.mule.umo.lifecycle.Startable#start()
*
* @throws UMOException On naming failure.
*/
public void start() throws UMOException {
try {
connect();
} catch(Exception e) {
throw new EndpointException(e);
}
}

/**
* Calls {@link MuleEJB3Wrapper#disconnect()}.
*
* @see org.mule.umo.lifecycle.Stoppable#stop()
*/
public void stop() {
disconnect();
}
}

Note that the cited endpoint is part of the JASMINe projects Event Switch, http://jasmine.ow2.org/

You might also like