Like I said here we are evaluating Mule to see if we can use it in our situation. One of the things we must do with Mule is to call our business services that are implemented by EJB3 classes based on a message that was put on a JMS topic. To my surprise this isn’t a standard thing in Mule (the creators of Mule want to be JDK1.4 compliant, so there is no room for standard support EJB3, as far as I understand it).
After some searching I came up with several possible solutions of which I think the next one is the best (at least in our situation):
- Create the EJB3 bean
Of course, you have to build the EJB3 beans that implement your business services. I have the following interface:
package net.pascalalma.mule.ejb; import javax.ejb.Remote; @Remote public interface SquareRemote { public Integer calculate(Integer number); } </pre> and this implementating class: <pre lang='java'> package net.pascalalma.mule.ejb; import javax.ejb.Stateless; @Stateless public class SquareBean implements SquareRemote { public Integer calculate(Integer number) { return number * number; } }
In a separate Maven module I defined my Mule config file. To create this module I make use of a specific Maven archetype for Mule projects as I described here.
This is my Mule Config file:
<?xml version="1.0" encoding="UTF-8"?> <mule xmlns="http://www.mulesource.org/schema/mule/core/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2" xsi:schemaLocation=" http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"> <spring:beans> <jee:remote-slsb id="squareEJB" jndi-name="net.pascalalma.mule.ejb.SquareRemote" business-interface="net.pascalalma.mule.ejb.SquareRemote"> <jee:environment> java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory java.naming.provider.url=rmi://localhost:1099 openejb.jndiname.format={interfaceClass} </jee:environment> </jee:remote-slsb> </spring:beans> <model name="main"> <service name="EjbCall" > <inbound> <vm:inbound-endpoint path="square" synchronous="true" /> </inbound> <component> <spring-object bean="squareEJB"/> </component> </service> </model> </mule>
As you see I added a spring-bean definition. With this, I create a ‘Spring’ wrapper around my EJB3 class and that wrapper is used lateron in the config to inject the component in Mule.
In the configuration of the Spring bean I set up my initial context for OpenEJB in this case, because that is where this set up will be tested with. I also set the jndiname format property, so it matches the format that is used in Glassfish which is our application server in the ‘real’ world.
In the test class we will run Mule as a standalone process by using the MuleClient object. And we will put a value on the inbound endpoint of our defined service, like this:
package net.pascalalma.mule.mathservice; import org.mule.api.MuleMessage; import org.mule.module.client.MuleClient; import org.mule.tck.FunctionalTestCase; public class MathServiceTestCase extends FunctionalTestCase { protected String getConfigResources() { return "mule-config.xml"; } public void testMathService() throws Exception { MuleClient client = new MuleClient(); MuleMessage result = client.send("vm://square", new Integer(5), null); assertNotNull(result.getPayloadAsString()); assertEquals("25",result.getPayloadAsString()); } }
We will deploy the EJB in OpenEJB at runtime so we need the OpenEJB depencies with the ‘test’ scope. Here is the snippet of the pom.xml:
<dependency> <groupId>org.apache.openejb</groupId> <artifactId>openejb-core</artifactId> <version>3.1</version> <scope>test</scope> <exclusions> <exclusion> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> </exclusion> </exclusions> </dependency>
As you can see I make use of OpenEJB3.1 instead of OpenEJB1.0 that is used with the supplied examples in Mule (to use the 3.1 version you must exclude the commons-lang dependency to avoid a NoSuchMethodError).
The complete pom can be found here.
To have our EJB3 classes deployed in OpenEJB I added an empty ejb-jar.xml to the classpath by adding the file to the /test/resources/META-INF directory. Here is a snippet of my project in Netbeans:

Now you can perform a mvn clean install
to test your Mule configuration. You will get a result like this:
——————————————————-
T E S T S
——————————————————-
Running net.pascalalma.mule.mathservice.MathServiceTestCase========================================================================
= Testing: math service (net.pascalalma.mule.mathservice.MathServiceTestCase) =
========================================================================
Apache OpenEJB 3.1 build: 20081009-03:31
http://openejb.apache.org/
Result: 25Results :
[jar:jar]
Building jar: /Users/pascal/projects/mathService/target/mathservice-1.0-SNAPSHOT.jar
[install:install]
Installing /Users/pascal/projects/mathService/target/mathservice-1.0-SNAPSHOT.jar to /Users/pascal/.m2/repository/net/pascalalma/mule/mathservice/1.0-SNAPSHOT/mathservice-1.0-SNAPSHOT.jar
————————————————————————
BUILD SUCCESSFUL
————————————————————————
Total time: 19 seconds
Finished at: Sat Mar 28 15:30:13 CET 2009
Final Memory: 27M/48M
————————————————————————
Hi Pascal,
Nice entry, thanks for this post. I’ve noticed some discrepancies though:
1. Mule has been targeted for Java 5 for several releases now, not 1.4.
2. I’m not sure what you mean by ‘ejb3 is not OOTB functionality’. There’s nothing Mule can do here, ejb3 don’t make remote interfaces mandatory, it’s up to a user to provide and expose those if needed.
3. We deliberately didn’t duplicate lookup functionality already available and working fine in Spring.
In this blog an ejb is simply injected as a service component (and could come from anywhere). Another option could be to use Mule’s ejb transport, however it requires ejb2-style interfaces exposed (again, this is the optional compatibility layer in ejb3 spec).
Cheers!
Hi Andrew,
Thx for your comment.
About the discrepancies:
1. I only guessed for a reason why EJB3 connector wasn’t supplied as OOTB functionality. I read somewhere that JDK1.4 had to be supported by Mule but I guess that was an outdated article (always the risk when looking for info on the net, I guess)
2. I guess you have a point here. But the first thing I tried when I wanted to call an EJB3 bean from within Mule is to google around and all you find is ‘complaints’ that there is no OOTB functionality for it. So that’s why I looked further and came to the above ‘solution’.
3. Yep, I understand. And there is nothing wrong with it I guess, as soon as you know that this is the way to do it. That’s why I wrote this post: to show others who are running into the same issue how they can solve it.
In this post (http://www.mail-archive.com/user@mule.codehaus.org/msg10294.html) the writer says the component way is the natuaral way to go. Since I am fairly new to Mule I assumed that this meant it is also the ‘best ‘ way to accomplish this, that’s why I went for this solution.
So, I hope this clarifies the thing a little. But nevertheless I am still impressed by the functionality that Mule offers and I will certainly look into it in more detail!