OSGi/JMS/MDB Example
Here is an example of yet another hybrid (OSGi + Java EE) application. This is a complete JMS consumer/producer example using OSGi and GlassFish. You can download the complete sample from here.
How to use the sample:
1. Download osgi-jms-mdb-1.zip and unzip it. 2. cd osgi-jms-mdb-1/ 3. mvn clean install 4. Start GlassFish (something like "asadmin start-domain" or "java -jar glassfish.jar" will do) 5. Download OSGi/EJB container support bundle for GlassFish and install it by just copying to modules/autostart/: wget http://download.java.net/maven/glassfish/org/glassfish/osgi-ejb-container/3.1-SNAPSHOT/osgi-ejb-container-3.1-SNAPSHOT.jar cp osgi-ejb-container-3.1-SNAPSHOT.jar $glassfish/modules/autostart/ 6. Create a couple of JMS resources by executing the following commands (you can use the admingui if you prefer GUI) asadmin create-jms-resource --restype javax.jms.Topic jms/osgi.Topic1 asadmin create-jms-resource --restype javax.jms.ConnectionFactory jms/osgi.ConnectionFactory1 7.tail -f $glassfish/domains/domain1/logs/server.log. 8. Deploy the bundles and configure them as shown below (Although, you can copy them in any order you like, but I suggest you copy them in the following order to them in action and after each step, watch server.log). cp ./message-consumer/target/osgijms1.consumer.jar $glassfish/domains/domain1/autodeploy/bundles/ cp ./message-producer/target/osgijms1.producer.jar $glassfish/domains/domain1/autodeploy/bundles/ cp ./osgijms1.producer.cfg $glassfish/domains/domain1/autodeploy/bundles/
Description of the sample

As the diagram above shows, there are two bundles, viz:
a) A JMS message consumer bundle - This is also an OSGi bundle. It contains a single class which is the message consumer or listener. It is implemented as a Message Driven Bean (MDB). There is nothing OSGi-specific in the bean. The jar file contains OSGi metadata and an additional GlassFish specific header called Export-EJB to indicate to the server that the OSGi bundle contains EJBs that need to be processed. Refer to my earlier blogs about deploying ejb jars as OSGi bundles in glassfish.
The relevant metadata for the EJB OSGi bundle looks like this:
[MANIFEST osgijms1.consumer.jar] Export-EJB NONE
Bundle-ManifestVersion 2 Bundle-SymbolicName sahoo.osgijms1.consumer Bundle-Version 1.0.0.SNAPSHOT Import-Package javax.ejb,javax.jms Manifest-Version 1.0
The MDB looks like this:
@MessageDriven(mappedName = "jms/osgi.Topic1")
public class AnMDB implements MessageListener {
public void onMessage(Message message) {
String str = null;
if (message instanceof TextMessage) {
try {
str = TextMessage.class.cast(message).getText();
} catch (JMSException e) {
// ignore
}
}
if (str == null) str = message.toString();
System.out.println("AnMDB Received: " + str);
}
}
b) A JMS message producer bundle - This contains a single class which is the the BundleActivator. The bundle activator is configured about JMS destination via OSGi Config Admin service. Upon configured, it sends messages to the JMS destination. The complete source code for the message producer is given below:
public class Activator1 implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Message producer started - waiting to be configured with topic name");
Properties props = new Properties();
props.put(Constants.SERVICE_PID, "osgijms1.producer");
context.registerService(ManagedService.class.getName(), new ManagedService() {
public void updated(Dictionary properties) throws ConfigurationException {
if (properties != null) {
String destinationName = (String) properties.get("osgijms1.Destination");
String connectionFactoryName = (String) properties.get("osgijms1.ConnectionFactory");
int noOfMsgs = Integer.valueOf((String) properties.get("osgijms1.NoOfMsgs"));
sendMessage(connectionFactoryName, destinationName, noOfMsgs);
}
}
}, props);
}
private void sendMessage(String connectionFactoryName, String destinationName, int noOfMsgs) {
Connection connection = null;
try {
InitialContext ctx = new InitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup(connectionFactoryName);
connection = connectionFactory.createConnection();
Session session = connection.createSession(
false,
Session.AUTO_ACKNOWLEDGE);
Destination dest = (Destination) ctx.lookup(destinationName);
MessageProducer producer = session.createProducer(dest);
TextMessage message = session.createTextMessage();
for (int i = 0; i < noOfMsgs; i++) {
message.setText("This is message " + (i + 1));
System.out.println("Sending message: " + message.getText());
producer.send(message);
}
/*
* Send a non-text control message indicating end of
* messages.
*/
producer.send(session.createMessage());
} catch (JMSException e) {
System.err.println("Exception occurred: " + e.toString());
} catch (NamingException e) {
System.err.println("Exception occurred: " + e.toString());
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
}
}
}
}
public void stop(BundleContext context) throws Exception {
}
}
What's coming next
We will make the JMS resources available as OSGi services just like we make JDBC resources available as OSGi services. Once we do that, our message producer can track the service and send message once the resource is deployed.
As usual, if you have questions, please ask us in our forum or mailing lists.
| Attachment | Size |
|---|---|
| uml.png | 9.93 KB |
| osgi-jms-mdb-1.zip | 20.25 KB |
- Login or register to post comments
- Printer-friendly version
- ss141213's blog
- 6018 reads






Comments
Little problem with bundle osgi-ejb-container bundle
by badcheese - 2010-04-26 08:38
Salutation !When I'm starting glassfish, it's displaying every 5 seconds in server.log :
[#|2010-04-26T16:09:19.051+0200|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName=Thread-1;|Error while starting bundle: file:/julien/osgi/glassfish/glassfishv3/glassfish/modules/autostart/osgi-ejb-container-3.1-SNAPSHOT.jar: org.osgi.framework.BundleException: Unresolved constraint in bundle org.glassfish.osgi-ejb-container [217]: package; (&(package=com.sun.enterprise.deploy.shared)(version>=3.1.0))|#]
[#|2010-04-26T16:09:19.051+0200|INFO|glassfishv3.0|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=21;_ThreadName=Thread-1;|org.osgi.framework.BundleException: Unresolved constraint in bundle org.glassfish.osgi-ejb-container [217]: package; (&(package=com.sun.enterprise.deploy.shared)(version>=3.1.0)) at org.apache.felix.framework.Felix.resolveBundle(Felix.java:3263) at org.apache.felix.framework.Felix.startBundle(Felix.java:1597) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:915) at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:902) at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:1027) at org.apache.felix.fileinstall.internal.DirectoryWatcher.start(DirectoryWatcher.java:1013) at org.apache.felix.fileinstall.internal.DirectoryWatcher.startAllBundles(DirectoryWatcher.java:1006) at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:396) at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:206) |#]
One or many other bundles are they necessary for autostart ?