SpringOne 2GX 2011

Chicago, October 25-28, 2011

Bruce Snyder's complete blog can be found at: http://bruceblog.org/

Items:   1 to 5 of 182   Next »

Tuesday, January 10, 2012



Have you ever had a need to create your own JMS consumer? Or will you have this need in the future? If you answered yes to either one of these questions, this post will simplify your life.

In the previous post, I discussed Using the Spring JmsTemplate to Send JMS Messages. As a follow-on, in this post I will demonstrate how to receive messages using Spring JMS. Although the previously mentioned JmsTemplate can receive messages synchronously, here I will focus on asynchronous message reception using the Spring message listener container architecture, specifically the DefaultMessageListenerContainer.

The DefaultMessageListenerContainer (DMLC) is another wonderful convenience class that is part of the Spring Framework's JMS package. As you can see in the Javadoc, the DMLC is not a single class, but a well-abstracted hierarchy for the purpose of receiving messages. The reason for this is that the DMLC takes its inspiration from Message Driven Beans (MDB).

MDBs were originally defined in the EJB 2.0 spec as a stateless, transaction aware message listener that use JMS resources provided by the Java EE container. MDBs can also be pooled by the Java EE container in order to scale up. In short, MDBs were designed for asynchronous message reception in a way that the Java EE container could manage them. Although the intention was good, unfortunately the disadvantages of MDBs are numerous including:
  • MDBs are static in their configuration and creation (they cannot be created dynamically)
  • MDBs can only listen to a single destination
  • MDBs can only send messages after first receiving a message
  • MDBs require an EJB container (and therefore the Java EE container)
Although the Spring DMLC took its inspiration from MDBs, it did not replicate these disadvantages; quite the opposite, in fact. The Spring DMLC is commonly used to create what have become known as Message-Driven POJOs (MDP). MDPs offer all of the same functionality as MDBs but without the disadvantages listed above. The Spring DMLC provides many features including:
  • Various levels of caching of the JMS resources (connections and sessions) and JMS consumers for increased performance
  • The ability to dynamically grow and shrink the number of consumers to concurrently process messages based on load (see setConcurrentConsumers and setMaxConcurrentConsumers) for additional performance
  • Automatically re-establishes connections if the message broker becomes unavailable
  • Asynchronous execution of a message listener using the Spring TaskExecutor
  • Support for local JMS transactions as well as an external transaction manager around message reception and listener execution
  • Support for various message acknowledgement modes, each providing different semantics
For some situations, it is important to understand the additional error handling and the redelivery semantics that are provided by the DMLC. For more information, see the AbstractMessageListenerContainer JavaDoc.

The reason I recommend the DMLC (or even the SimpleMessageListenerContainer) is because writing JMS consumers can be a lot of work. In doing so, you must manually handle and mange the JMS resources and the JMS consumers, any concurrency that is necessary and any use of transactions. If you've ever done such work you know how arduous and error prone it can be. Certainly MDBs provide some of these features but with all their disadvantages. By creating MDPs using the Spring DMLC, I have seen users save a tremendous amount of time and increase their productivity significantly. This is because the DMLC offers much flexibility, robustness, a high amount of configurability and it has widespread deployment in businesses all over the world (so it has been widely tested).

Compared to MDBs, use of the Spring DMLC is actually surprisingly simple. The easiest way to get started is to using an XML configuration as the Spring DMLC provides JMS namespace support. Below is a Spring application context that demonstrates the configuration to use the Spring DMLC with Apache ActiveMQ:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">

<!-- A JMS connection factory for ActiveMQ -->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="tcp://foo.example.com:61616" />

<!-- A POJO that implements the JMS message listener -->
<bean id="simpleMessageListener" class="com.mycompany.SimpleMessageListener">

<!-- The Spring message listener container configuration -->
<jms:listener-container
container-type="default"
connection-factory="connectionFactory"
acknowledge="auto">
<jms:listener destination="TEST.FOO" ref="simpleMessageListener" method="onMessage" />
</jms:listener-container>
</beans>


For folks who are already familiar with the Spring Framework, the XML above is quite straightforward. It defines a connection factory bean for ActiveMQ, a message listener bean and the Spring listener-container. Notice that the jms:listener contains the destination name and not the listener-container. This level of separation is important because it means that the listener-container is not tied to any destination, only the jms:listener is. You can define as many jms:listener elements as is necessary for your application and the container will handle them all.

Below is the message listener implementation:


import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;

public class MyMessageListener implements MessageListener {

private static final Logger LOG = Logger.getLogger(MyMessageListener.class);

public void onMessage(Message message) {
try {
TextMessage msg = (TextMessage) message;
LOG.info("Consumed message: " + msg.getText());
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

The message listener implementation is deliberately simple as its only purpose is to demonstrate receiving the message and logging the payload of the message. Although this listener implements the javax.jms.MessageListener interface, there are a total of three options available for implementing a message listener to be used with the Spring DMLC:
  • The javax.jms.MessageListener - This is what was used in the example above. It is a standardized interface from the JMS spec but handling threading is up to you.
  • The Spring SessionAwareMessageListener - This is a Spring-specific interface the provides access to the JMS session object. This is very useful for request-response messaging. Just be aware that you must do your own exception handling (i.e., override the handleListenerException method so exceptions are not lost).
  • The Spring MessageListenerAdapter - This is a Spring-specific interface that allows for type-specific message handling. Use of this interface avoids any JMS-specific dependencies in your code.


So not only is the Spring message listener container easy to use, it is also full of options to adapt to many environments. And I've only focused on the DefaultMessageListenerContainer here, I have not talked about the SimpleMessageListenerContainer (SMLC) beyond a simple mention. At a high level the difference is that the SMLC is static and provides no support for transactions.

One very big advantage of the Spring message listener container is that this type of XML config can be used in a Java EE container, in a servlet container or stand alone. This same Spring application context will run in Weblogic, JBoss, Tomcat or in a stand alone Spring container. Furthermore, the Spring DMLC also works with just about any JMS compliant messaging middleware available. Just define a bean for the JMS connection factory for your MOM and possibly tweak a few properties on the listener-container and you can begin consuming messages from different MOMs.

I should also note that the XML configuration is certainly not a requirement either. You can go straight for the underlying Java classes in your own code if you wish. I've used each style in various situations, but to begin using the Spring DMLC in the shortest amount of time, I find the Spring XML application context the fastest.

Update: I have made all of the code for these examples available via a GitHub repo.

Wednesday, January 4, 2012



Even though I've used Macs for over 20 years now, I have never developed a native app for the Mac OS. So over the holiday break, I finally spent some time getting ramped up on Objective-C to develop apps for Mac OS X and IOS. This meant reading a lot about Objective-C, XCode and Cocoa.

I'm primarily a Java developer these days but I'm familiar with writing C code (though I haven't written it in many years) so this knowledge helped me quite a bit. The syntax for Objective-C was a bit strange at first but I got the hang of it after a bit and I'm continuing to learn. I managed to develop a command line app and a GUI app using XCode. Building the command line app was much more understandable for me because you are writing all the code by hand. Constructing the GUI app was a rather nebulous task mainly because you rely upon the IDE to handle many things for you. XCode is the IDE for building Objective-C apps for Mac OS X and IOS. When developing a GUI app, XCode provides a visual tool called Interface Builder that is amazing. It provides a standard set of widgets for your apps and allows you to do visually design the UI. Interface Builder simplifies the creation of connections from the code to the GUI widgets via dialogs and selections in those dialogs. Because the actual code to handle these things is hidden behind the IDE, the experience was rather cloudy in my mind. At some point, I plan to dig down into what is actually happening behind the curtain here to solidify it in my mind. I also used the XCode debugger and profiler which were both very nice tools and were both included in the IDE.

I forgot to mention that I am using Objective-C 2.0 and XCode 4.2. This is not only a new release of Objective-C but it's also a new release of XCode with a dramatically improved set of functionality. My prior experience was with XCode 3.x, it was minimal and I was not writing Objective-C, so I didn't really get to experience the power of XCode. Now that I've been through a couple of tutorials with XCode 4.2 and Objective-C, I must say that I'm duly impressed. In fact, Eclipse could stand to learn a few things from XCode. Objective-C 2.0 is a big improvement over the previous version. There's now automatic reference counting to help you with memory management (the big thing I hated about C/C++) and much more.

The apps I created run on Mac OS X. They are both very minimal and not very useful overall, but it is invigorating to delve into new territory for a platform that I have known and loved for over 20 years already. I plan to keep at it as time allows and build some useful apps. Perhaps I will even develop some IOS apps.

For those who are interested, here are the two tutorials that I followed:

I've also been reading many blogs from Objective-C and Cocoa developers. I also found some items for Java developers who want to learn Objective-C:

I will try to keep adding info about resources here as I think about them. Not only is this a record for myself, but hopefully it will help other folks as well.

Wednesday, January 4, 2012



Here's another quick set of notes for myself for posterity. I always clone and build a project on the command line before I import it into the IDE to begin hacking code. Right now I have to handle a hairy merge so I need a visual tool to make things a bit easier. For this purpose, I want to make Eclipse git aware so that I can use the visual diff in the IDE. Hopefully these notes will help out someone else, too.

For this situation I'm dealing with a Java project that uses git. First some quick items to set the stage:

  • IDE:For Java development, my IDE of choice is the SpringSource Tool Suite (STS). If you develop Spring-based Java apps and you like Eclipse, you should really be using STS.
  • SCM: The majority of projects I have worked with over the last few years use git for SCM. It is vastly superior to any other SCM tools I've used and documentation abounds for it, but it is a bit like a razor blade.
  • IDE+SCM: The standard git tool for Eclipse is EGit


To make the Eclipse project git aware, follow these steps:

  1. Go to Window->Show View->Other
  2. In the filter field, enter the word git
  3. Select Git Repositories and click OK
  4. Click on the icon whose tooltip reads 'Add an existing local Git Repository to this view'
  5. Click on the browse button and navigate to the directory that contains the project source code
  6. Click the Search button
  7. Click OK
  8. Right-click on the project in the Package Explorer
  9. Go to Team->Share Project
  10. Select Git and click Next
  11. Check the box for 'Use or create Repository in parent folder of project - this should automatically find the .git directories
  12. Click Finish and let EGit complete the integration


After following these steps, the projects should be connected to their git repository. This allows you to handle the vast majority of git commands right from inside the IDE.

For more info about EGit, check out the EGit User Guide.

Tuesday, January 3, 2012



This morning I got up at 5am to ride up Flagstaff Mountain with a friend. Soon after I got up I dropped my iPhone in water, totally submerging it. Great. What a wonderful start to my day. Obviously this rendered the phone completely dead. Excellent. So I rode this morning with my old iPod Shuffle, so that wasn't a big deal. But I didn't have a clock so I took my wristwatch and put it in my jersey pocket.

In my second hour of riding I pulled the watch out of my jersey pocket (pockets are on the back of a bike jersey) and I dropped it on the rode. When I circled back and picked it up, I realized that one of the pins had bent and needed to be replaced. Not a big deal really as I've had this happen many times over the years. And there's a jewelry place right near the Apple Store I typically use. Still, that's strike number two for the day. I rode the third hour just waiting for the third bad thing to happen, but it never did.

I just returned from the Apple Store and I'm glad to say that I was quite happily surprised. This phone was covered under AppleCare but it doesn't cover dropping your phone in water. Matteo at the Flatirons Crossing Apple Store informed me that Apple has a policy of leniency when it comes to your first major accident with your iPhone so he was able to basically give me a get out of jail free card and save me $200 (the cost of replacing an iPhone 3GS). What a surprise!!! I was prepared to pay the cost of replacement and be on my way. So I was very pleasantly surprised.

As Matteo was filling out the necessary forms for the replacement, we chatted a bit. He asked me if I upgraded to Mac OS X Lion yet. I explained that I had not because I was speaking a conference in Portland last week and I didn't want to chance any issues with my laptop until that was done. This led him to asking me more about speaking at conferences and what I do for a living. After explaining that I'm a software engineer at VMware, his response was, 'We all love VMware Fusion!" I agreed and explained that I use it often for testing and running other operating systems on Mac OS X. He said that folks inside Apple really prefer VMware because it's so reliable, which was nice to hear.

Before leaving, I asked Matteo to help me find the AC adapter that plugs into the end of a USB cable. I left one in my hotel room in Portland last week so I needed to replace it. Unfortunately you cannot buy just the AC adapter, you must buy a new USB cable as well. But Matteo said, 'Hold on a minute, I'll be right back.' A minute later he returned with the very AC adapter I needed and said, 'Here you go, free of charge. Because you work for a cool company that we love. And I can see that you need a change of luck today." Wow! Yet another pleasant surprise!!! I think this might be a good day after all. Thanks, Matteo!

Monday, September 19, 2011



While installing PostgreSQL 9.0 on Mac OS X again, I had to figure out all these steps yet again. So I'm documenting this process for my own sake because I have been through this now twice on two computers recently, having to hunt down all of these commands each time. I'm hopeful that this will help others as well.

Use the MacPorts command port to install PostgreSQL 9.0, then create and own a data directory and a logs directory:

$ sudo port install postgresql90-server
$ sudo mkdir -p /opt/local/var/db/postgresql90/defaultdb
$ sudo chown -R postgres:postgres /opt/local/var/db/postgresql90
$ sudo mkdir -p /opt/local/var/log/postgresql90
$ sudo chown -R postgres:postgres /opt/local/var/log/postgresql90

Now you need to initialize the database using the data directory that was created above:

$ sudo -u postgres /opt/local/lib/postgresql90/bin/initdb -D /opt/local/var/db/postgresql90/defaultdb

I prefer to change the postgres user's shell to bash:

$ sudo dscl . -create /Users/postgres UserShell /bin/bash

View the postgres user account just to make sure it all looks OK:

$ dscl . -read /Users/postgres
AppleMetaNodeLocation: /Local/Default
GeneratedUID: 5B38F583-CBBF-4082-A32D-C17947394A27
NFSHomeDirectory: /opt/local/var/db/postgresql90
Password: *
PrimaryGroupID: 501
RealName:
PostgreSQL-90 Server
RecordName: postgres
RecordType: dsRecTypeStandard:Users
UniqueID: 502
UserShell: /bin/bash

Also check the postgres group:

$ dscl . -read /Groups/postgres
AppleMetaNodeLocation: /Local/Default
GeneratedUID: 715FEB22-D0F1-443F-BC93-55896210DB44
Password: *
PrimaryGroupID: 501
RealName: postgres
RecordName: postgres
RecordType: dsRecTypeStandard:Groups

Now edit the pg_hba.conf file to add the appropriate permissions:

# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust

This should allow you to connect easily using the psql utility.

I prefer to use the pg_ctl command to start and stop PostgreSQL. This is simply because I learned PostgreSQL on Linux and that's all there was. To prevent having to retype the full command every time I want to start or stop the database, create a start script and a stop script in the postgres user's home directory named pg_start and pg_stop. Below are the contents of the pg_start file. Make sure to create these files as the postgres user in the home directory:

$ sudo su - postgres
$ vim ./pg_start
#!/bin/sh
/opt/local/lib/postgresql90/bin/pg_ctl -D /opt/local/var/db/postgresql90/defaultdb -l /opt/local/var/log/postgresql90/postgres.log start &

Below are the contents of the pg_stop file:

$ vim ./pg_stop
#!/bin/sh
/opt/local/lib/postgresql90/bin/pg_ctl -D /opt/local/var/db/postgresql90/defaultdb -l /opt/local/var/log/postgresql90/postgres.log stop

Don't forget to make them executable:

$ chmod +x ./pg_start
$ chmod +x ./pg_stop

(There is a Mac OS X way of starting PostgreSQL using launchctl but I don't tend to use that because I'm used to the standard pg_ctl command.)

Now use the pg_start script to start up PostgreSQL. Execute it as the postgres user (sudo su - postgres) I tend to cat the log file just to make sure it's running correctly:

$ ./pg_start
$ server starting

$ cat ../../log/postgresql90/postgres.log
LOG: database system is ready to accept connections
LOG: autovacuum launcher started

Looks good so we'll create my user:

$ /opt/local/lib/postgresql90/bin/createuser bsnyder
Shall the new role be a superuser? (y/n) y

Because I made my user a superuser, I can create my own db schema, so log out of the postgres user account and back to my own account first:

$ exit
$ /opt/local/lib/postgresql90/bin/createdb
CREATE DATABASE

The createdb command automatically uses my username as the schema name.

The only thing left to do before starting up the database is edit your ~/.profile or ~/.bash_profile to put the path to the PosgreSQL bin directory into the PATH:

export PATH=/opt/local/lib/postgresql90/bin:$PATH

Now just log into the PostgreSQL server using psql to make sure we're ready to roll:

$ psql
-bash: psql: command not found
bsnyder@skunk [darwin](DARWIN-1527) $ /opt/local/lib/postgresql90/bin/psql
psql (9.0.4)
Type "help" for help.

bsnyder=# select version();
version
------------------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 9.0.4 on x86_64-apple-darwin10.8.0, compiled by GCC i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664), 64-bit
(1 row)

bsnyder=#

And we're good to go!

Items:   1 to 5 of 182   Next »