Accessing JBoss Session beans from python using QMF

Posted: June 12, 2009 in geek stuff
Tags: , , , ,

My current project is looking at how to expose Enterprise Java Beans to other technologies. I am most concerned with C#, but any other languages would be cool. We looked at the WS-* standards (and CXF which is a great tool) but the different versions across the vendors provided difficult.

We then looked at QMF, which is an management framework written on top of the QPID messaging fabric. You can learn about QMF here. This post will walk you through an eaxmple of exposing an EJB in jboss over the QMF Bus. Gregory Mostizky is working on a deployer, so this should get easier.. but this is a good enough to criticize.. so I am posting it.

To get started, you will need the gcc tools, ant, and jboss5 installed. Next.. get the code:

# Get the latest QPID Code
svn co http://svn.apache.org/repos/asf/qpid/trunk
# Get my example Code:
git clone git://github.com/bkearney/qmfExample.git

Build the latest qpidd broker and java code

cd trunk/qpid/cpp
./bootstrap
./configure --prefix ~/qpidlocal
make install
cp ../java
ant

Once this is done, you should be able to launch the most current qpidd

export LD_LIBRARY_PATH=~/qpidlocal/lib
~/qpidlocal/sbin/qpidd

Now…. build the example code:

cd ~/qmfExample/javaAgent
# Edit the build.properties file to point to your local
# installation
ant install

You can now start up jboss, and run the example python script to access the bean

export PYTHONPATH=~/trunk/qpid/python
cd ~/qmfExample/pythonConsole
python ./qmfExample.py

Thats all there is. Python is now calling EJBs! Now… lets see how we did it. All the code below is in the qmfExample/javaAgent/src
directory. Lets first look at the Session Bean we created:

package qmf.example.ejb;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateless;
import org.apache.qpid.agent.annotations.QMFHide;
import org.apache.qpid.agent.annotations.QMFObject;
import qmf.example.BaseClass;
import qmf.example.DerivedClass;

@Stateless(name="ServiceBean")
@QMFObject(className="ExampleService", packageName="qmf.example.ejb")
public class ServiceClassBean implements ServiceClass
{

    public BaseClass getBase(String name, String description) {
        BaseClass bc = new BaseClass() ;
        bc.setName(name) ;
        bc.setDescription(description) ;
        return bc ;
    }

    
    public DerivedClass getDerived(String name, String description, int count) {
        DerivedClass dc = new DerivedClass() ;
        dc.setName(name) ;
        dc.setDescription(description) ;
        dc.setCount(count) ;
        return dc ;        
    }

    
    public List findMany() {
        ArrayList list= new ArrayList() ;
        list.add(getBase("JarJar", "My Friend")) ;
        list.add(getDerived("Binks", "Not My Friend", 12)) ;
        ArrayList data = new ArrayList() ;
        data.add(11) ;
        data.add("Info") ;
        data.add(getBase("Wotto", "Also My Friend")) ;
        list.get(0).setStuff(data) ;
        return list ;
    }
    

    @QMFHide
    public void doHokeyPokey() {
        System.out.println("Turn yourself around") ;
    }
}

This is pretty normal except for 2 annotations. One, @QMFObject, gives
the name and package to expose. The second, @QMFHide, causes the method
to be ignored. The bean returns 2 classes, a base class and a derived
class. We have annotated the base class so that the marshalling code
knows about the derived class. This is a similar pattern to JAXB:

package qmf.example;

import java.util.ArrayList;

import org.apache.qpid.agent.annotations.QMFSeeAlso;

@QMFSeeAlso({DerivedClass.class})
public class BaseClass
{
.....

The final magic, is a beans.xml file which tells the JBoss microcontainer to start up the agent. Here is the code for that:

<deployment xmlns="urn:jboss:bean-deployer:2.0">    

	<bean name="QPIDConnection" class="org.apache.qpid.client.AMQConnection">
		<constructor>
			<parameter>amqp://guest:guest@/?brokerlist='tcp://localhost'</parameter>
		</constructor>
	</bean>
	
    <bean name="ServiceBean" class="org.apache.qpid.agent.ManagedEJB">
        <property name="name">ServiceBean</property>
        <property name="className">qmf.example.ejb.ServiceClassBean</property>        
        <property name="jndiLocation">qmfExample/ServiceBean/local</property>
    </bean>	    

	<bean name="QMFAgent" class="org.apache.qpid.agent.Agent">
		<property name="label">agent</property>
		<property name="sessionTransacted">false</property>
		<property name="connection">
			<inject bean="QPIDConnection" />
		</property>
		<property name="managedObjects">
			<list elementClass="org.apache.qpid.agent.ManagedObject">
				<inject bean="ServiceBean" />		
			</list>
		</property>
		<property name="registeredClasses">
			<list elementClass="java.lang.String">	
			</list>
		</property>
	</bean>

</deployment>

As I said earlier, the deployer should make this easier. Specifically.. it will remove the need for the beans file. But.. this will work until the deployer is done.

Advertisements
Comments
  1. Matt says:

    This post appears mad on Planet Fedora http://planet.fedoraproject.org/

  2. bryankearney says:

    Updated the example paths a bit based on some other languages I am adding to the example.

  3. […] Categories: Uncategorized Tags: C#, ejb, java, JBoss, qmf This is a follow up to the earlier post about accessing EJBs from python.. In this post, we will build the CSharp Console and use that to […]

  4. […] consoles in various languages to connect to EJBs running in a JBoss 5 container. There hass been python, C#, and Java. Now, lets add ruby to the list. Steps for building and deploy the Java agent can be […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s