Who’s On Phirst

Official blog of Phurnace Software.

Wesley Willard's Blog
Description:
My name is Wesley Willard, and I am a Staff Engineer at Phurnace. I have been a software developer for 22+ years. The first 13 years of my career were spent working in C/C++, primarily in the area of Oil/Gas software development. For the last 9 years, I have been doing mostly Java, both client and server-side development, with various companies in Austin.

Posted by: Wesley Willard on

At this year's No Fluff Just Stuff conference, presenter Matthew McCullough, the managing partner of Ambient Ideas, LLC, gave an interesting talk on Open Source Debugging Tools, which touched on usage of freely-available tools such as cURL. cURL is a command-line tool which supports file transfer operations for a variety of protocols (HTTP, HTTPS, FTP, SFTP, SCP, etc.) and can be used for a variety of useful tasks, such as retrieving the real source page of a web site:
curl -i -H Accept:text/xml http://www.phurnace.com

You can also determine your public IP (useful for those running behind a firewall/router) with the command:
curl -q http://checkip.dyndns.org

This command will return an HTML page with your public IP address embedded.

Okay, here's an example of how you can use cURL to take advantage of Google's mail feed to obtain information about your unread e-mail, without ever using the web browser. In this example, I will show how to take the output from the mail feed, parse it with a Groovy script, and then send a text message to your cell phone number.

First the script:


#!/bin/sh
rm -f /tmp/unread.txt

export PHONE_NUMBER=5555555555
export JAVA_HOME=/usr/lib/jvm/java-6-sun

curl -K .pwd https://mail.google.com/mail/feed/atom/unread > /tmp/unread.xml 

groovy -classpath /home/admin/jars/postgresql-8.4-701.jdbc4.jar \
    /home/admin/bin/Feed.groovy /tmp/unread.xml if [ -e /tmp/unread.txt ]; then echo "Sending notification of unread mail " `date` cat /tmp/unread.txt | mail -s "Unread" $PHONE_NUMBER@txt.att.net fi
This shell script uses a script written in Groovy to parse the curl output. There is nothing particularly fancy about it. It does depend on the -K option to curl to pass in the username and password credentials. This is a more secure method than passing them directly on the command line, or worse, including them in the script itself. If the output file from the Groovy script exists after its execution, the contents are emailed to the cell phone number's text message address. Ideally, this script will run as a cron job, checking the mail feed at a specified interval.

Before you run the script, set up a database called 'mail', with one table 'processed_mail'. The table schema is:

 Column  |          Type          | Modifiers 
---------+------------------------+-----------
 issued  | character varying(100) | not null
 author  | character varying(100) | 
 summary | character varying(255) | 
Indexes:

    "processed_mail_pkey" PRIMARY KEY, btree (issued)

The Groovy script is documented, but in a nutshell, here's what it does:
  • Connect to the database. I am using PostgreSQL in this case, but any database will do.
  • Set up a namespace for accessing the XML elements
  • Create an output file
  • Process each entry the XML file that is passed in as the first argument
  • For each entry, check to see if it has been processed, i.e. it is in the database
  • If it has not been processed, add an entry to the database, and output to the file
  • After processing the unread entries, delete any entries in the database which were not in the unread list
  • Delete the output file if it is empty

import groovy.util.*
import groovy.sql.*;

//
// Setup a database connection
// using Postgres
//
def DB='jdbc:postgresql://localhost/mail'
def USER='postgres'
def PASSWORD='mypassword'
def DRIVER='org.postgresql.Driver'

Class.forName(DRIVER)
def sql = Sql.newInstance(DB,USER,PASSWORD)
assert sql

//
// The XML that comes back needs a namespace
//
def ns = new groovy.xml.Namespace("http://purl.org/atom/ns#")

//
// Process each unread email
// If the unread email has not been processed then
// add an entry to the database
//
def processEntry = { it, outputFile ->
    //
    // Look for an aleady processed entry
    // If found then get out
    //
    def found = false
    def issued = it[ns.issued].text()
    sql.eachRow("select * from processed_mail where issued=${issued}") {
        found = true 
    }
    if (found) {
       return
    }

    //
    // Add the entry and output for the email text
    // 
    println "Issued on " + issued
    def author = it[ns.author][ns.name].text()
    def summary = it[ns.summary].text()
    println "Date: " + issued
    println "From: " + author 
    println summary 
    sql.execute(
    "insert into processed_mail (issued, author, summary) values(${issued}, ${author}, ${summary})")
    outputFile.append("From:  " + author + "\n")
    outputFile.append("Date:  " + issued + "\n")
    outputFile.append("Summary: " + summary  + "\n")
}

//
// Search in the list of entries for the 
// issued date passed in
//
def searchUnread = { dbIssued, entries ->
    def itFound = false
    entries.each {
        def xmlIssued = it[ns.issued].text()
        if (dbIssued.equals(xmlIssued)) {
            itFound = true
            return
        }
    }
    itFound;
}

//
// Process each row in the processed table
// If there is no entry in the list of unread email
// then delete the database row to prevent further processing
//
def cleanupDatabase = { dbIt, entries ->
    def dbIssued = dbIt.issued
    def entryFound = searchUnread(dbIssued, entries)
    if (! entryFound) {
        println "Deleting entry for " + dbIssued
        sql.execute("delete from processed_mail where issued=${dbIssued}")
    }
}

//
// Main body of code
//
def newFile = new File(args[0])
if (newFile.length() == 0) {
   println "Empty new file"
   System.exit(0)
}

//
// Create the output file
//
def output=new File("/tmp/unread.txt")

//
// Parse the input file
//
def parser = new XmlParser()
def feed = parser.parse(newFile)

//
// Gather the entries 
//
def xmlEntries = feed[ns.entry]

//
// Process each entry and output if 
// it has not already been processed
//
xmlEntries.each { processEntry(it, output) }

//
// Clean up the database
//
sql.eachRow("select * from processed_mail") { cleanupDatabase(it, xmlEntries) } 

//
// If the output file is empty then delete
//
if (output.length() == 0) {
   output.delete()
   println "Deleted empty file"
}

This mail feed utility illustrates the usefulness of the combination of a common system utility and a modern script language. This script could be modified to include finer-grained decisions about the destinations of the mail notifications.

Both cURL and Groovy are available on Windows, Linux, and other platforms, so this example can be tried out in almost any environment.

In Untagged 
Comment (0) Read More...


Posted by: Wesley Willard on

Amazon Elastic Compute Cloud (EC2) has generated enormous amounts of buzz in the last couple of months. EC2 allows scalable deployment of applications by providing a way for customers to create server “instances” which can run any number of operating systems, such as Windows XP and Vista, and any number of Linux distributions. The customer can load any software of their choice on to the machines, and customize them at will. A customer can create, launch, and terminate server instances as needed, paying only for usage.

In addition to providing a Amazon Management Console to manage these instances, Amazon also provides command line tools which allow for the automation of instance administration. By combining these tools with some basic shell commands, you can customize the startup of your EC2 instances. I will provide an example that shows how this can be accomplished.

This example assumes you have the following available:


Okay, let's get started. First of all, we'll define some basic shell variables:

export EC2_HOME=/opt/ec2/tools/ec2-api-tools-1.3-30349/
export EC2_PRIVATE_KEY=~/ec2/pk-HGHEBCKY657B2ZUH7YIVXZKT5QVNBWFM.pem
export EC2_CERT=~/ec2/cert-HGHEBCKY657B2ZUH7YIVXZKT5QVNBWFM.pem
export amiid="ami-cccb2ca5"
export key="mykey"
export zone="us-east-1c"
export group="server"
export id_file="mykey.pem"
export vol_name="vol-8abe59e3"
export mount_point="/mnt/vol"
export device_name="/dev/sdf"
export ip="174.129.232.50"

The variables that start with the name “EC2” are used by the Tools API. They are the directory where you downloaded your Tools installation and the key and cert files provided to you by Amazon when you created your instance. The other variables are used by the shell commands in this example, and include:
  • Amazon Image ID
  • Key name associated with this instance
  • The zone in which this instance was created
  • The group associated with this instance
  • The name of the user's EC2 identity file
  • The ESB volume ID
  • The mount directory within the EC2 instance
  • The device name to associate with the ESB volume when attached
  • The Elastic IP address to associate with the instance

Now it's time to start the instance, and then loop until it is running.

#
# Start the instance
# Capture the output so that
# we can grab the INSTANCE ID field
# and use it to determine when
# the instance is running 
#
echo Launching AMI ${amiid}
${EC2_HOME}/bin/ec2-run-instances ${amiid} -z ${zone} -k ${key} --group ${group} 
--group default > /tmp/a if [ $? != 0 ]; then echo Error starting instance for image ${amiid} exit 1 fi export iid=`cat /tmp/a | grep INSTANCE | cut -f2` # # Loop until the status changes to “running” # sleep 30 echo Starting instance ${iid} export RUNNING="running" export done="false" while [ $done == "false" ] do export status=`${EC2_HOME}/bin/ec2-describe-instances ${iid} | grep INSTANCE | cut -f6` if [ $status == ${RUNNING} ]; then export done="true" else echo Waiting... sleep 10 fi done echo Instance ${iid} is running

Now we have the running instance ID, which we will use going forward. We next attach the ESB volume to the running instance, associating a device name. After we attach the volume, we wait until its status indicates that it is attached.

#
# Attach the volume to the running instance
#
echo Attaching volume ${vol_name}
${EC2_HOME}/bin/ec2-attach-volume ${vol_name} -i ${iid} -d ${device_name} 
sleep 15

#
# Loop until the volume status changes
# to "attached" 
#
export ATTACHED="attached"
export done="false"
while [ $done == "false" ]
do
   export status=`${EC2_HOME}/bin/ec2-describe-volumes | grep ATTACHMENT | grep ${iid} | cut -f5`
   if [ $status == ${ATTACHED} ]; then
      export done="true"
   else 
      echo Waiting...
      sleep 10
   fi
done
echo Volume ${vol_name} is attached

Now we associate the Elastic IP address with the running instance. This capability is important in an environment where instances are being started and stopped at various points for scalability reasons, so these operations will happen with no interruption for the user.

#
# Associate the Elastic IP with the instance
# After this operation we just sleep a bit
#
echo Associating elastic IP address ${ip}
${EC2_HOME}/bin/ec2-associate-address 174.129.232.50 -i ${iid}
sleep 30

Our final step for starting our instance is to copy and execute some additional commands within the running instance. These operations will create a mount point and mount the volume. Our commands assume that any partitioning and file system type creation has already been setup in the Amazon image’s /etc/fstab file. We use SSH to copy and execute these commands. Because EC2 does not allow username/password authentication, we must provide our identity file to SSH.

#
# Start the operations within the instance
# Copy over the mount script and execute it
# The script setup_vol does:
#     mkdir /mnt/vol
#     mount /mnt./vol
# 
scp -i ${id_file} setup_vol root@${ip}:/root
ssh -i ${id_file} root@${ip} . ./setup_vol

Finally, because this instance was created with an Ubuntu Desktop image, we can set up an NX Server to allow us to access our running instance with a remote desktop:

ssh -i ${id_file} root@${ip} /usr/NX/bin/nxserver --stop
ssh -i ${id_file} root@${ip} /usr/NX/bin/nxserver --start

Last, but not least, tell the user that we are ready to start using the running instance.

echo Image ${amiid} instance ${iid} is ready to go!
echo ${iid} > current_instance

I have attempted to demonstrate how you can use automation to facilitate the easy startup of your Amazon EC2 instance. This example can serve as a starting point for further customizations specific to your environment.

In Amazon Web ServicesAmazon EC2
Comment (6) Read More...


Posted by: Wesley Willard on

My family and I took a last-minute New Year's vacation this year to Angel Fire Resort, in New Mexico for a few days of skiing. We drove from Austin to Angel Fire, stopping in Clovis, New Mexico, both going out and coming back. On the way back to Austin, we stopped for a delicious family-style meal at Allen Family Style Meals, in Sweetwater, Texas. If you ever get near this place, you have to stop and try it out, if you like an incredible Southern-style home-cooked meal.

Angel Fire is a great place to ski for both beginners and intermediates, with lots of green and blue runs, most of which are nice and wide. The area had received snow fall during Christmas, and still had a significant base of 40+ inches. The skiing was great, although we did experience wind gusts on the last day of up to 50 MPH. The wind was so strong, in fact, that my daughter was stopped in her tracks while skiing straight downhill! Skiing is something that we enjoy a lot, as it is an activity that all four of us can do together. My kids can handle almost all the greens and blues, and my wife and I can ski all the greens, along with some of the blues. This gives us a wide enough range of courses to try, to avoid boredom of doing the same runs over and over.

We have been skiing to New Mexico at least once a year since 2003, but the last couple of times have been particularly enjoyable, as my wife and I have discovered the joy of parallel turn skiing. Previously, we sort of muddled through by using, the "wedge", or snowplow turn technique, which is effective for easy runs, but less effective for steeper courses. Wedging down a hill is also hard on the inside of the knees, as they are under almost constant strain. Skiing parallel greatly reduces strain on the knees, since the turn is affected by rolling the skiis, and shifting your weight from once side to the other. When skiing with the parallel turn, the moment of truth for me is when you come out of the turn, pointing your skis downhill in order to begin setting up for the next turn. To me, it is basically a controlled fall down the hill for a couple of seconds, and it doesn't take long to build up speed. While this is a bit frightening for a low-level intermediate skier like myself, it is also exhilarating for that couple of seconds. This process of falling and turning allows you to really control your speed, which is best way to prevent nasty falls.

This same sort of thing happens in an Agile, iterative software development environment that we practice at Phurnace. The turn is akin to the period of planning that takes place before the iteration, where you control your speed and recover, while the fall downhill is the iteration itself, where your use your speed to make progress in getting down the mountain. Without proper execution of both of these segments, you will most likely end up in an Epic Fail, which can cause injury to both your physical and emotional well-being. On the other hand, non-iterative development is like trying to do that wedge down a steep hill. Since you are in a constant attempt to control your speed, you can't get down the mountain as fast, and inevitably you wear out, unless of course, you have the knees of my ten-year old daughter.

So, in skiing, or software development, remember, you have to try to fall down the hill, if you are going to make the most efficient effort to achieve your goal.

In Untagged 
Comment (0) Read More...


Posted by: Wesley Willard on

Scala is yet another modern programming language which has received a lot of attention in the last few years. It compiles down to Java bytecode, therefore can take full advantage of existing Java libraries.

I'd like to take a few moments to share a couple of examples of one area that I think Scala shows great strength, processing of XML data. For my examples, I will be using XML data that has been aquired through using the WebSphere Portal tool, xmlaccess. This tool accesses a portal instance's configuration data and returns an XML file that can in turn be used to modify the portal's configuration.

So, assuming we have an XML file that has been created via xmlaccess, we can then use Scala to process it. To load the file, we define a Scala object, import some library packages, and then call :

object ScalaXML extends Application {
import scala.xml._
import scala.collection.mutable.HashMap
import scala.collection.jcl.ArrayList
import java.util.Set
import java.util.HashSet
import java.util.Map
import java.util.TreeMap

//
// Load the XML file
//
val xml = XML.loadFile("test.xml")


In Scala, the '_' symbol serves the same purpose as the '*' in Java in an import statement. The XML.loadFile takes a file path, and creates a val variable, which is immutable. The value in the variable 'xml' is now the parsed XML data. This statement displays the simplicity of coding that is also makes Scala very powerful. Java would require several lines of code to do the same thing.

Next, we do a simple XML pattern match to find the version of the XML data that is in the xmlaccess file.

//
// Search for an XML element with an attribute named
// 'version', and print out the value of that attribute
//
println("Version " + ( xml \\ "@version").text)


The text method is a method on the Node class, and is used to access the 'version' attribute's value. The method println is a method on the Scala class scala.Console, which is implicitly imported.

Here is an example of creating a Scala Map of the elements from the file:

//
// Create a Scala Map by pattern matching 'Skin' elements
// The map's value object is the map of attributes
//
var oidMap = new HashMap[String, MetaData]
for (val entry <- xml \\ "skin") {
val objectid = (entry \\ "@objectid").text
val attributes = entry.attributes
oidMap += (objectid -> attributes)
}


The Scala Map functions the same as a Java Map, but uses some different syntax for adding objects. The '+=' symbol is actually a method defined on the class HashMap. In this example, the variable 'objectid' is the map's key, and 'attributes' is the map's value for each entry. We have a for loop here, in which the values of an XML pattern match are assigned to the val variable 'entry'.

To illustrate usage of a Java class in Scala, here is the same for loop, but now we are creating a Java TreeMap:

//
// Create a Java Map of the same elements
// The Set's value object is again the attributes
//
var oidJavaMap = new TreeMap[String,MetaData];
for (val entry <- xml \\ "skin") {
val objectid = (entry \\ "@objectid").text
val attributes = entry.attributes
oidJavaMap.put(objectid, attributes)
}

Now, let's process the Scala Map:

//
// Now iterate through the Scala Map to create
// a new List of Node which contains new Element
// objects replicating the original XML for the Skin
//
println("Iterating through Scala Map");
var nodes = new ArrayList[Elem]()
oidMap.foreach{ (nvPair) =>
val objectid = nvPair._1
val attributes = nvPair._2
var elem =
var newElem = elem.%(attributes)
nodes += newElem
}

This loop will create a new Scala ArrayList. The foreach construct allows you to iterate through the Scala Map, executing the body of code enclosed in the braces (a closure) with the argument 'nvPair'. Closures are common in functional languages like Scala, where functions can be passed around as arguments. The elements of our new list are of type Elem, even though we do not explicitly declare a variable of this type. Scala is able to infer the type of the variable from the text on the right side of the '=', which is a well-formed XML tag. The '%' operator is a method on Elem, an returns a new Element that contain the updated attributes in the variable 'attributes'. Because we are operating on a Map, the variable 'nvPair' is a key-value pair, which can be access with the _1 and _2 syntax for key and value, respectively.

We can output our new list as XML by doing the following:



//
// Create a new XML snippet with the Node objects from above
//
def xmlString =

xsi:noNamespaceSchemaLocation="PortalConfig_6.0.1_1.xsd">
{nodes}

//
// Output a prettied-up version of the new XML
//
println( new PrettyPrinter(80 /*width*/,4 /*indent*/).format(xmlString) )




This code shows us again how you create an XML object by simply in-lining the XML data. You can also embed the values of variables in this XML, as we do with the variable 'nodes'. Scala provides a built-in "pretty print" class, PrettyPrinter, which is used to make the output more readable.

The last bit of example code shows how you can use what looks like plain old Java to iterate through our previously created Java Map.

//
// Iterate through the Java Map and print out some attributes
//
cnt = 0;
println("Iterating through Java Map");
var iterMap = oidJavaMap.keySet().iterator();
while (iterMap.hasNext()) {
var key = iterMap.next();
var attributes = oidJavaMap.get(key)
var objectid = attributes.get("objectid")
println("Objectid " + cnt + " is " + objectid.get)
var resourceroot = attributes.get("resourceroot")
println("Resourceroot " + cnt + " is " + resourceroot.get)
var uniquename = attributes.get("uniquename")
println("Unique name " + cnt + " is " + uniquename.get)
cnt += 1
}


This is pretty straight-forward code, and look almost identical to Java code. You might notice how we access indvidual attribute values with two different get methods. This first is a method on the class MetaData, which is the abstract base class for the element's attributes. This returns an Option object, which also has a get method. This second invocation returns the value of the attribute.

In WebSphere Portal xmlaccessScala
Comment (0) Read More...


Posted by: Wesley Willard on

One of the hottest technologies right now in server-side development right now is OSGi (formerly known as the Open Services Gateway initiative). As the underlying framework on which the Eclipse Project's runtime is based (since 3.0), this technology is starting to garner a lot of attention for its abilities to allow the development of "bundles" (or, "plugins"). This has enabled the popularity of Eclipse to grow by leaps and bounds, as plugins can be quickly added or updated.

OSGi has moved beyond being "just" a very powerful piece of the Eclipse Project, and is rapidly gaining traction amongst enterprise application servers. It offers a mechanism for resolving complex classloading issues, which often cause problems for the developers of services for the application servers. It also provides the ability to control the visibility of the implementation details, which serves to prevent unintended coupling between bundles. By default, all packages in a bundle is private, and can only be visible outside of the bundle by explicit exporting. By enforcing these visibility rules, unnecessary dependencies in the software are avoided, allowing for independent development, and versioning of bundles. OSGi manages the life cycle of a bundle, from start to stop, and enforces security concerns at each step of the way. Also, OSGi is capable of functioning as a standalone container, which allows bundles to be tested without the need for a full-blown application server environment.

With the release of the SpringSource Application Platform, SpringSource has embraced OSGi in a big way, building its application server on top of the Eclipse Project's Equinox OSGi runtime environment. From the release announcement, these quotes from SpringSource CEO Rod Johnson stand out with regard to SpringSource's commitment to OSGi:

"It is the first product that built on a modern technology basis. Java EE compliance is no longer the be all and end all. We've got a competitive advantage because we have a clean new code base. We have designed and delivered to meet the requirements of today and not those from the last 10 years."

"The OSGi technology used is a fundamental next generation technology."

JBoss Application Server 5 is nearing its long-awaited release. In contrast to SpringSource's approach, JBoss is definitely hedging its bets, that while OSGi is definitely a major technology force, it might be prudent to be a little cautious in adopting it wholesale. By abstracting its interface to the component model, the JBoss Microcontainer will allow native support of POJO's, legacy MBeans, as well as OSGi. Its pluggable architecture model will also allow the flexibility to work with other component models that will be developed in the future.

In this article, Open Source analyst firm Redmonk's Michael Cote is quoted as saying:

"Rather than build their core on OSGi, they're building the core on their own stuff, and supporting OSGi as a sort of way of using that JBoss-specific core," he said. "The hedge there being that they can add on support for whatever comes into fashion if OSGi becomes tomorrow's bell-bottoms. If you have the time to build an architecture that lets you hedge like that, it's usually a good thing."

So, while both Spring and JBoss are definitely adding OSGi to the mix, their approaches reflect very different approaches. It will be interesting to see if one approach is better than the other.

In Spring FrameworkOSGiJBoss
Comment (0) Read More...


Posted by: Wesley Willard on

When I was younger, I considered running to stay in shape to be about as much fun as a root canal. Tennis, basketball, and softball occupied my time, as they provided the diversion of the particular ball that the sport involved. Now a days, however, I find myself enjoying the sheer simplicity of running. The uniform is simple, just shoes, shorts, and an optional shirt, and in Austin, you don't even have to leave your neighborhood to enjoy a great course. I'd like to share a couple of runs that I really enjoy.

Most of my running starts from the legendary "Rock", which is located underneath the Mopac foot bridge near Austin High. From here, one of my favorite runs is to head out Lake Austin Boulevard until it hits Scenic Drive. Scenic provides a very nice view of Lake Austin, and several nice, but very runnable hills. I like to follow Scenic until it hits Pecos Street, and then take a right. Pecos runs right through the heart of Tarrytown, which used to be considered a suburb in Old Austin. Pecos hits Enfield Road, which has a nice hill right before you get to Exposition Boulevard. From the top of this hill, you can see the Texas State Capitol in downtown Austin. Enfield crosses under Mopac again, where you can take a right and run through Clarksville, a neighborhood founded by freed slaves. Clarksville to me is the kind of neighborhood that really represents the funky-cool character of Austin. From the western edge of Clarksville, you are treated to a great view of the Texas Hill Country, right before you descend back to the Rock. This run comes in at just over 8 miles.

One of the newer runs that I just started doing in the last year is one that takes me south of the Colorado River. This is another great neighborhood in Austin, which despite fairly rapid gentrification, has still managed to maintain its look-and-feel. The absolute highlight of this run is a viewing of the Mary Street Goat. I kid you not, this is a live goat, complete with horns and a beard. Most mornings, he's out in the front yard of his owner's house, located near Congress Avenue. You can then take Congress north to the Lady Bird Lake Hike and Bike Trail, while enjoying a great view of the unofficial Main Street of Texas, and another view of the State Capitol. This run covers between 8-9 miles.

My early morning running puts me in the perfect frame of mind to write some kick-butt software here at Phurnace, while trying to avoid the middle-age spread. I've made some great friends, and I'm able to experience an Austin that a lot of people aren't fortunate enough to get to enjoy.

In Untagged 
Comment (0) Read More...


Posted by: Wesley Willard on

To a non-geek, spending a weekend in hotel conference rooms listening to presentations on the latest technologies in software development might make them beg, "just shoot me now, please". But to someone interested in keeping abreast of these sorts of things, for both company and personal reasons, it was a very nice way to do just that. Plus, it was hot as hell outside, the neighborhood pool is even hot, and the lake is just too far away.

The Lone Star Symposium was held this past weekend here in Austin, and it was a great show. The lack of vendor presence at these conferences allow software developers to focus on the technology itself. The people who put this conference together go out of their way to provide all the amenities to the attendees, such as good food, snacks, not to mention some of the best industry experts out there. With regard to the experts, I am always pleased to find not only those who write about the technologies at this show, but also those who have had a hand in developing them. A case in point, the presenter for the Spring Framework was Keith Donald, one of principals and founders.

It's always a shame that you can't make it to all the sessions in this type of conference, but you generally can't go wrong with any selection. Just to sort of sum up, the hottest topics this year were the ones concerning dynamic languages, such as Groovy, and it's related framework, Grails. Also, Spring continues to be THE overarching framework for J2EE development.

My favorite session, though, was one by Neil Ford, titled "Productive Programmer: Acceleration & Automation". I am a sucker for cool command line tools, and he talked about such great productivity enhancers such as Auto-Hot Key, which allows you to define (and redefine) hot keys in Windows, and clcl, which allows you to maintain multiple clipboards. I am very keyboard-oriented, and these tools will allow me to stay away from my carpal-inducing mouse.

Next time one of these conferences makes its way near you, check it out. Especially if its a hot summer weekend!

In Spring FrameworkGroovy
Comment (0) Read More...


Posted by: Wesley Willard on

The Spring Framework has become the most popular open source application framework in the Java space in recent years. One of its most powerful features is its ability to allow developers to create Spring Beans, which can be configured together to create an application's object graph, or data structure. The framework provides a consistent interface to accessing these beans which avoids unnecessary dependencies between components.

JMX (Java Management Extensions) is a technology that enables the configuration, instrumentation, and monitoring of Java applications of all sorts, both J2SE and J2EE. It has gained wide-spread acceptance in the Java community as the standard API for these tasks. JMX provides access to MBeans (JMX's version of Spring's Beans), which compose its management interface. This is handled through a software layer known as the MBeanServer.

One useful piece of the Spring Framework is its direct support for JMX. Spring provides the ability to register its Beans in an MBeanServer, which can then be interrogated and modified by management applications by Spring Bean interface methods. The interface to Spring Beans is more intuitive and easier to use than the MBean interface, and abstracts many complicated details.

The follow example shows how Spring JMX can be used to provide remote management capability of its Beans. It will illustrate both server and client configuration and code. It will assume some Spring and JMX knowledge.

First, I create the Spring server-side application context configuration:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 
 
<beans>
    <bean id="registry" class=
"org.springframework.remoting.rmi.RmiRegistryFactoryBean">
        <property name="port" value="1090"/>
    </bean>
    
    <bean id="exporter" 
class="org.springframework.jmx.export.MBeanExporter" 
lazy-init="false"
         <property name="beans">
             <map>
                 <entry key="spring:name=jmxBean">
                     <ref local="jmxBean"/>
                 </entry>
             </map>
         </property>
         <property name="assembler" ref="assembler" />
         <property name="server">
             <ref local="mbeanServer"/>
         </property>
    </bean>
 
    <bean id="mbeanServer" 
        class="org.springframework.jmx.support.
MBeanServerFactoryBean"/> <bean id="jmxBean" class="com.phurnace.JmxBeanImpl"> <property name="name"> <value>Daffy Duck</value> </property> <property name="rating"> <value>5</value> </property> </bean> <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.
AnnotationJmxAttributeSource"/> <bean id="assembler" class="org.springframework.jmx.
export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxAttributeSource"/> </bean> <bean id="serverConnector" class="org.springframework.jmx.support.
ConnectorServerFactoryBean"> <property name="objectName" value="connector:name=rmi"/> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:
1090/myconnector"/> </bean> </beans>

The MBeanExporter class is used to specify the Spring Beans that are to be exposed via JMX by the MBeanServer. The MBeanServer is implemented by the Spring MBeanServerFactoryBean class. In this example, it will expose the specifed Beans via RMI. If there is an existing MBeanServer, such as in a web container like Tomcat or JBoss, Spring JMX will use that one. Spring also allows for the specification of an RMI registry for the MBeanServer. It will be started when the application context file is loaded.

The AnnotationJmxAttributeSource and MetadataMBeanInfoAssembler classes are used allow Java 5 Annotations to indicate which classes and methods which will be exposed in the MBeanServer.

The final bean in the configuration file configures a ConnectorServerFactoryBean to provide remote access to the Spring Beans. This connector will be running over RMI, on port 1090.

Now, I configure the Spring Bean (jmxBean), which looks a whole lot like a standard Java Bean:


//
// Interface class
//
package com.phurnace;

public interface JmxBean {
    public String getName();
    public void setName(String name);
    public int getRating();
    public void setRating(int rating);
}



//
// Implementation of JmxBean interface
//
package com.phurnace;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;

@ManagedResource(objectName=
"spring:name=jmxBean", description="Managed Bean")
public class JmxBeanImpl implements JmxBean {
    private String name;
    private int rating;

	
    @ManagedAttribute(defaultValue="animal")
	public String getName() {
		return name;
	}
     
    @ManagedAttribute
       (description="Name Attribute",
        defaultValue="animal")
	public void setName(String name) {
		this.name = name;
		System.out.println("Setting name to " + this.name);
	}

	@ManagedAttribute
	    (description="Rating Attribute")
	public int getRating() {
		return rating;
	}

	public void setRating(int rating) {
		this.rating = rating;
	}
}

As I indicated before, Spring allows usage of Java 5 Annotations to specify which classes and methods will be loaded into the MBeanServer, as well as metadata about them. Annotations are straight-forward to use, and provide great visibility to the developer as to which methods are exposed.

Finally, here is an example server, which loads up the Spring application context file.


package com.phurnace;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
ClassPathXmlApplicationContext; public class SpringJmxServer { private static Logger logger =
Logger.getLogger(SpringJmxServer.class); /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); ApplicationContext ctx = new
ClassPathXmlApplicationContext("/com/phurnace/server-jsr160.xml"); if (ctx != null) { logger.info
("Successfully loaded ApplicationContext"); } JmxBean jmxBean = (JmxBean) ctx.getBean("jmxBean"); String name = jmxBean.getName(); logger.info("Name is " + name); while ( !name.toUpperCase().equals("EXIT") ) { try { Thread.sleep(5000); name = jmxBean.getName(); } catch (Exception e) { logger.error("Trapped error " +
e.getMessage()); System.exit(1); } } System.exit(0); } }

Now, on to the client-side of things. First, I will show how to access the Spring Bean as a standard JMX client:


package com.phurnace;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.log4j.Logger;

public class TestJmxClient {
	private static Logger logger = Logger.getLogger(
TestJmxClient.class); private final String objectNameStr = "spring:name=jmxBean"; private final String jmxRmiStr = "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/
myconnector"; private ObjectName objectName; private JMXServiceURL jmxUrl; private JMXConnector jmxConnector; private MBeanServerConnection mbsc; /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); if (args.length == 0) { logger.info("Usage: java com.phurnace.
TestJmxClient "); System.exit(0); } TestJmxClient jmxClient = new TestJmxClient(); jmxClient.init(); jmxClient.accessBean(args[0]); System.exit(0); } public void init() { try { objectName = new ObjectName(objectNameStr); jmxUrl = new JMXServiceURL(jmxRmiStr); jmxConnector = JMXConnectorFactory.connect
(jmxUrl); mbsc = jmxConnector.getMBeanServerConnection(); } catch (Exception e) { logger.error("Error initializing
connection"); } } public void accessBean(String newName) { String name = getName(); if (name == null) { return; } logger.info("Original name is " + name); logger.info("Setting new name to " + newName); setName(newName); // // Access the name again to check it's value // name = getName(); if (name == null) { return; } logger.info("New name is " + name); } private void setName(final String name) { final String operationName = "setName"; try { Object[] params = new Object[1]; params[0] = name; String[] signature = new String[1]; signature[0] = new String("java.lang.String"); mbsc.invoke(objectName, operationName, params, // no parameter signature ); } catch (Exception e) { logger.info( "Error setting name value in bean "
+ e.getMessage()); } } private String getName() { final String operationName = "getName"; try { final String status = (String) mbsc.invoke(objectName, operationName, null, // no parameter null ); return status; } catch (Exception e) { logger.info("Error getting name value from
bean " + e.getMessage()); } return null; } }

This example does not need any Spring classes to access the MBean, even though it is created on the server as a Spring Bean. The test client accesses the MBeanServer via the RMI protocol.

You may notice that in order to make a connection to the MBeanServer, several intermediate objects must be created, such as a JMXServiceURL, a JMXConnector, and a MBeanServerConnection. In the process of creating these objects, checked exceptions must be handled.

This leads me to my final piece of code, which illustrates the same functionality, but is implemented using Spring.

First, here is a client-side Spring configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">
 
<beans>
 
<bean id="clientConnector" class=
"org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
  <property name="serviceUrl" value=
"service:jmx:rmi://localhost/jndi/rmi://localhost:1090/myconnector"/>
</bean>
 
<bean id="proxy" class=  
"org.springframework.jmx.access.MBeanProxyFactoryBean">
  <property name="objectName" value="spring:name=jmxBean"/>
  <property name="proxyInterface" value="com.phurnace.JmxBean"/>
  <property name="server" ref="clientConnector"/>
</bean>
 
</beans>
This configuration file configures an MBeanServerConnectionFactoryBean to provide the client with a connection to the server, via the RMI protocol. Then, an MBeanProxyFactoryBean is configured to create a proxy for the MBean registered under the specified ObjectName. Finally, the client connection bean is referenced, to allow remote access. Finally, here is the the Spring client:

package com.phurnace;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
ClassPathXmlApplicationContext; public class TestSpringJmxClient { private static Logger logger = Logger.getLogger
(TestSpringJmxClient.class); private ApplicationContext ctx; private JmxBean jmxBean = null; /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); if (args.length == 0) { logger.info("Usage: java com.phurnace.
TestSpringJmxClient "); System.exit(0); } TestSpringJmxClient jmxClient = new TestSpringJmxClient(); jmxClient.init(); jmxClient.accessBean(args[0]); System.exit(0); } public void init() { ctx = new ClassPathXmlApplicationContext
("/com/phurnace/client-jsr160.xml"); if (ctx != null) { logger.info("Successfully loaded
ApplicationContext"); } jmxBean = (JmxBean)ctx.getBean("proxy"); } public void accessBean(String newName) { String name = getName(); if (name == null) { return; } logger.info("Original name is " + name); setName(newName); name = getName(); if (name == null) { return; } logger.info("New name is " + name); logger.info("Rating is " + jmxBean.getRating()); try { jmxBean.setRating(10); } catch (Exception e) { logger.warn("Unable to set rating -
attribute is read-only"); } logger.info("Rating is still " +
jmxBean.getRating()); } private String getName() { return jmxBean.getName(); } private void setName(String name) { jmxBean.setName(name); } }

You might notice that the code is much more concise and clean. Except for the loading of the application context file, and the Bean access, there are no references to Spring code needed.

A try-catch block wraps the call JmxBean.setRating(10), as this method was specifically not exported by the server-side. This essentially makes this property read-only.

Hopefully, this code might encourage you to investigate Spring JMX as a technology worth incorporating in your next application. Providing external access to applications can pay off in valuable, unforseen ways after the it has been deployed.

In Untagged 
Comment (4) Read More...


Posted by: Wesley Willard on

In the last 10 years, Open Source software has provided an incredible benefit to the software development process. Most open source software projects present quality, well-tested APIs and libraries that can be quickly integrated into a product, providing much-needed functionality that does not have to be developed in-house. While there are too many projects to even begin to mention, the software produced by the Apache Project, and SpringSource provide frameworks and utilities that would take companies man man-years to develop on their own.

There are, however, a few issues that every organization should consider before choosing to include open source software in their commercial products. While these issues are usually not show-stoppers in the decision process, but should be viewed as risk factors. Failure to consider these issues can leave a company with problems that cause development and maintenance nightmares.

First, I would take the time to consider the involvement of the project's community of users and developers. Is work on the project ongoing, or does it seem to be stagnant? Are there discussion forums for the project, and do the developers post to the forum? An active Open Source project community enables you to resolve usage issues, obtain patches, and generally integrate the project more quickly into your product. A less active community can be an indicator that the project has not been well-received, perhaps because of stability, or even issues with its usefulness.

Licensing is a potential Pandora's Box of issues for anyone wishing to include Open Source software in their product. In general, software which fall under BSD or Apache licenses are the safest to use. For example, the Apache License allows free use, modification, and distribution of their software, provided that the appropriate notice is included. A great source of information concerning Open Source licensing issues is the Open Source Initiative. This group maintains the definition of open source software, and vets licenses in order to certify that the license adheres to it. In this litigative age that we live in, no one needs the hassle of a potential lawsuit involving their product.

In my opinion, while there are issues involved in the choice to include open source software in a commercial software product, the benefits far outweigh the drawbacks.

In Open Source
Comment (0) Read More...


Posted by: Wesley Willard on

Beginning in the 90’s, American software companies began farming out development work to companies overseas, or "off-shoring". These efforts mirrored what had been taking place for quite some time in other industries, such as textile manufacturing, and sent tremors through the software community. The heady days of the dot-com boom gave way to fear and gnashing of teeth in the early part of this decade. CEO’s were pictured riding astride elephants in India, and executives were predicting that soon all non-design development work would take place off-shore. Would there be any jobs left for American software developers?

Now entering the latter part of this first decade of the 21st century, the software development community state-side finds itself in what appears to be a better situation, jobs-wise. What happened? Why did the gloom-and-doom scenarios not play out?

A couple of realities have become apparent as the decade has played itself out. First, globalization of software development has actually worked against itself, as the cost of doing business in countries like India has increased to the point where the cost savings benefit is in question. Software developers are able to demand more money there, as the need for them has increased.

But secondly, and I believe just as importantly, companies seeking to off-shore their development made critical mistakes in choosing the products that they would send overseas. The products they chose were mostly mainstream, legacy products, which tend to be, by their sheer longevity, much more complex and intricate. From my experience in this business, I have found that "old" does not equal "simple". In fact, just the opposite is true. This software has generally been developed over the years by hundreds of developers, all with different programming styles, and do not always follow textbook patterns. Asking primarily inexperienced developers to maintain or enhance these products without day-to-day guidance from at least a few senior developers is tough. Couple this fact with the risk of losing market share for these products (oh yeah, they’re probably still profitable, why else would development continue?), and you have a recipe for disaster.

What seems like such a great idea when discussed at cocktail parties 8 years ago, should now be one that should be considered with at least some trepidation.

In Untagged 
Comment (0) Read More...


<< Start < Prev 1 2 Next > End >>