Main | Next page »
20100121 Thursday January 21, 2010

Mark your calendars! My upcoming speaking engagements

Now that we're a few weeks into 2010, my speaking calendar is starting to take shape. Already in just the first quarter I think I have more dates set than I did in all of 2009.

If you follow this blog, you know me and you know that I like to yammer on about Spring and OSGi. So it should be no surprise that it is those topics that I'll be talking most about again this year. But I'll be throwing in some other stuff as well.

In case you're interested in attending one of the places I'll be speaking, here's a list of the places I've got on my calendar right now:

Feb 10th: JavaMUG - Dallas, TX
I'll be talking about Spring MVC and the new REST features in Spring 3.
Feb 23rd: SOA User Group - Dallas, TX
Here I'll be talking about OSGi and how it provides an "SOA in a JVM".
Feb 27-28: Greater Wisconsin Software Symposium (NFJS) - Milwaukee, WI
Jay Zimmerman has me scheduled to talk about what's new in Spring 3, OSGi, Spring Roo, and testing beyond JUnit.
Mar 14th: Twin Cities Software Symposium (NFJS) - Minneapolis, MN
As in Wisconsin, I'll be talking about Spring 3, OSGi, Spring Roo, and the Spring Expression Language (SpEL).
Mar 17th: Spring Dallas User Group - Dallas, TX
We haven't ironed out a specific topic for this event, but I'm sure it will be something about Spring. Any requests?

One way you can keep up with where I'll be speaking is to subscribe to my speaking engagements feed (served via FeedBurner). I will do my best to keep that feed updated.

In addition to all of these fun events, I'm also scheduled to teach a Spring course for my company, Improving Enterprises. The dates are April 6-8 and it will be at the Improving Enterprises offices in Dallas, TX. Do me a favor and tell your friends and tweet about this...it's the first time I've taught a class through Improving and I'd like to see a good turn out.

Put these events on your calendar. I hope to see you at one of them.

(2010-01-21 10:00:00.0) Permalink Comments [0]

20091023 Friday October 23, 2009

SpringOne/2GX: A Retrospective

SpringOne/2GX is now over and most everyone has made their way back to the real world. Rather than write a long-winded review of the conference, I decided to summarize my thoughts in the form of a retrospective. That is, what went well, what didn't go so well, and what I'd improve upon next time around.

Feel free to contribute to this retrospective with your own comments.

What went well

The Day 1 Keynote
The keynote on Monday night was quite interesting with SpringSource tcServer Developer Edition stealing the show. But also hearing about all of the different facets of the Spring ecosystem and seeing how they are evolving was great.
Adrian Colyer's comedic bit to start the Day 2 Keynote
Funny stuff. Adrian's quite the story teller. Wish I could find this on YouTube.
My talk on SpEL went well
I had given this talk twice before with less-than-desirable results. This time it worked out. It may have been the best talk I've ever given.
The people
It was great meeting and chatting with so many people who are also interested in Spring and Groovy/Grails. Also fun to catch up with my friends in SpringSource who I only get to see once per year.
Rod Johnson's duet
Rod played piano while another attendee played clarinet. Very entertaining.
Roo and tcServer Dev Edition
The darlings of the show. Almost everyone was talking about them. Both are awesome and you should check them out.
The Roosevelt New Orleans
This was hands-down one of the nicest hotels that I've ever stayed in. Very comfortable and luxurious. Highly recommended.
The food
The food served at lunch and dinner during the conference was outstanding.

When didn't go so well

The Day 2 Keynote
Don't get me wrong...I think the VMWare stuff is cool and interesting. But this is a developer conference and the parade of VMWare products would have better suited an IT crowd. It was interesting, but not valuable to me. I did find Chris Richardson's demo of CloudFoundry very interesting, though.
The constant pinging sound in Salon 5
What the heck was that?
My failure to schedule appropriately
I think that my strategy for choosing which sessions to attend was flawed. All of the sessions were great, but I think I could've learned more by attending a different mix of sessions. I'm especially regretful that I didn't attend more Groovy-oriented sessions.
The size of the desserts
Last year's desserts were much bigger...slices of cake the size of your head. This year they were more petite. But, if you smash several of them together...

Things to improve upon next year

Personal session selection
I should try to attend more sessions on topics that I don't know as well.
More audience interaction
The best part of my talk was where the audience chimed in with things to try in SpEL. I should purposefully set aside time to "take requests" from the crowd in my talks.
Get more sleep
I missed out on a few things because I was exhausted. Should plan my sleep better so that I can attend and see more stuff.
Bigger desserts
'Nuff said.
(2009-10-23 18:30:00.0) Permalink

20091022 Thursday October 22, 2009

Curing ADD with Roo, Blueprints, and Karaf

Yesterday was a big day for me at SpringOne/2GX. It was the day that I gave my talk on the Spring Expression Language (SpEL). I've been excited about giving that talk, but also excited about attending so many of the great sessions by other speakers. So, I started the day by attending a session presented by Stefan Schmidt on web productivity with Roo.

Unfortunately, due to lack of sleep and anxiety for my own presentation, I was unable to focus well on Stefan's talk. He was doing a great job presenting Roo, but my brain just couldn't focus. So to entertain my brain with something that at least was close to the topic at hand, I decided to tinker a bit with Roo's support for SpringSource's Bundlor to generate OSGi manifests for Roo artifacts.

The first thing I did was to start up the Roo shell and issue the project command:

roobundle% roo
    ____  ____  ____  
   / __ \/ __ \/ __ \ 
  / /_/ / / / / / / / 
 / _, _/ /_/ / /_/ /  
/_/ |_|\____/\____/    1.0.0.RC2 [rev 321]


Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo> project --topLevelPackage com.habuma.numbers
Created /Users/wallsc/Projects/roofun/roobundle/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
Created SRC_TEST_JAVA
Created SRC_TEST_RESOURCES
Created SRC_MAIN_WEBAPP
Created SRC_MAIN_RESOURCES/META-INF/spring
Created SRC_MAIN_RESOURCES/META-INF/spring/applicationContext.xml
roo> 

From here it looks like Roo has created the basic project structure. Nothing special so far. But what I want to do with Roo is build a simple OSGi bundle that publishes a service to the OSGi service registry. So, let's start by creating the service's interface. There's lots of ways I could do this, but as long as I'm in Roo...

roo> interface --name NumberToEnglishService
Created SRC_MAIN_JAVA/com/habuma/numbers
Created SRC_MAIN_JAVA/com/habuma/numbers/NumberToEnglishService.java
roo> 

Notice that Roo's interface command creates the interface in the base directory without me having to explicitly specify that package. If we dig around in the project directory, you'll see that Roo has created NumberToEnglishService.java in src/main/com/habuma/numbers. But it's empty, so let's give it something to do. I could find no way to do this directly in Roo (and I can't imagine how that'd work anyway), so I hopped out of Roo and opened up NumberToEnglishService.java in my text editor and made it look like this:

package com.habuma.numbers;

public interface NumberToEnglishService {
    String translate(int number);
}

The idea behind NumberToEnglishService is to take a number as an int and to return a String that spells it out in English. For example, given 6, the translate() method should return "six". Simple enough. Now we need an implementation. So, trying to do as much work in Roo as possible, I issue the class command in the Roo shell:

roo> class --name ~.internal.NumberToEnglishServiceImpl
Created SRC_MAIN_JAVA/com/habuma/numbers/internal
Created SRC_MAIN_JAVA/com/habuma/numbers/internal/NumberToEnglishServiceImpl.java
roo> 

Since I'm ultimately going to export com.habuma.numbers in the OSGi manifest, I want to put the implementation of NumberToEnglishService in a different package. This keeps it private to this bundle so that no other bundle will try to use it directly. In Roo, the tilde (~) is a shortcut for the project's base directory, so "~.internal" will be expanded into "com.habuma.numbers.internal"...and that's where NumberToEnglishServiceImpl.java was created.

We're almost ready to create our bundle, but we need to flesh out the contents of NumberToEnglishServiceImpl.java. Again I turn to my text editor to have it implement the NumberToEnglishService interface as follows:

package com.habuma.numbers.internal;
import com.habuma.numbers.NumberToEnglishService;

public class NumberToEnglishServiceImpl implements NumberToEnglishService {
    public String translate(int number) {
        if(number == 6) {
            return "six";
        }

        return "unknown";
    }
}

So this implementation of NumberToEnglishService is a bit short-sighted, but it does satisfy the aforementioned requirement of translating 6 to "six", so it's a good start.

Now we have all of the code in place for our service, so let's build it. Roo produces a Maven project, so all we need to do is run Maven with the package goal:

roobundle% mvn package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building numbers
[INFO]    task-segment: [package]
[INFO] ------------------------------------------------------------------------
...
[INFO] Building jar: /Users/wallsc/Projects/roofun/roobundle/target/numbers-0.1.0-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 16 seconds
[INFO] Finished at: Wed Oct 21 22:09:43 CDT 2009
[INFO] Final Memory: 19M/34M
[INFO] ------------------------------------------------------------------------
roobundle% 

So far, so good. Let's crack open the JAR artifact to see what its manifest looks like. Unfortunately, it looks like this:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: wallsc
Build-Jdk: 1.5.0_20

There's no Bundle-SymbolicName, Bundle-Version, Export-Package or any other header that would indicate that this is an OSGi bundle. This is just a plain old JAR file. We need it to be an OSGi bundle.

We could edit our own manifest file, but that's no fun. Fortunately, Roo has support for the Bundlor tool to automatically generate a proper OSGi manifest. All we need to do is tell Roo that we want it to use Bundlor. To do that, issue bundlor setup in the Roo shell:

roo> bundlor setup 
Managed ROOT/pom.xml
Created ROOT/template.mf
roo> 

Now our Roo project is setup with Bundlor, so let's build it again and the review the manifest to see if it looks any better. This time the manifest looks like this:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: wallsc
Created-By: Apache Maven
Import-Package: javax.sql;version="0.0.0",org.springframework.stereoty
 pe;version="[3.0.0,3.1.0)"
Export-Package: com.habuma.numbers;version="0.1.0.BUILD-SNAPSHOT"
Bundle-Version: 0.1.0.BUILD-SNAPSHOT
Bundle-Name: numbers
Bundle-Classpath: .
Build-Jdk: 1.5.0_20
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.habuma.numbers
Tool: Bundlor 1.0.0.M5

Now that looks like an OSGi manifest. We have a Bundle-SymbolicName and a Bundle-Version, among other things. And notice that the Export-Package header exports our base package. It all looks good...except...

The Import-Package header imports javax.sql and org.springframework.stereotype. We're not really going to use those in our bundle, so I'm not sure that we need them. So we need to tell Bundlor to not import them. If you paid close attention when doing the Bundlor setup, you saw that Roo added a file called template.mf to the project. This file contains instructions to guide Bundlor in producing a manifest. We'll need to edit this file to remove the Import-Package instructions for javax.sql and org.springframework.stereotype. If you open up template.mf, you'll see a line that looks like this:

Import-Package: org.springframework.stereotype;version="[3.0.0,3.1.0)",
  javax.sql;version="0.0.0"

Just remove it and then run the build again. Then have another look at the produced bundle's manifest. It should look a little like this:

Manifest-Version: 1.0
Bundle-Name: numbers
Bundle-Classpath: .
Archiver-Version: Plexus Archiver
Build-Jdk: 1.5.0_20
Built-By: wallsc
Created-By: Apache Maven
Bundle-ManifestVersion: 2
Bundle-SymbolicName: com.habuma.numbers
Tool: Bundlor 1.0.0.M5
Export-Package: com.habuma.numbers;version="0.1.0.BUILD-SNAPSHOT"
Bundle-Version: 0.1.0.BUILD-SNAPSHOT

Much better. Now the manifest doesn't import anything we don't need. But we're not quite ready to deploy our bundle yet. Even though we have a service interface and implementation and our bundle's manifest is in shape, there's nothing that actually publishes the service to the OSGi service registry.

There are a lot of ways to publish services to the OSGi service registry. In Modular Java I wrote about using both the core OSGi API and Spring-DM to publish and consume OSGi services. But recently, the OSGi R4.2 specification was released including the OSGi Blueprint Services specification and I've been wanting to try it out. OSGi Blueprint Services is a formalization of the service model from Spring-DM. It's slightly different than Spring-DM, but if you've already used Spring-DM, then it should be quite easy to figure out. Even if you've not used Spring-DM before, I think that the Blueprint model is quite intuitive.

All we need to do to publish our service in the OSGi service registry using OSGi Blueprint Services is to add an XML file containing the blueprint specifications to the bundles OSGI-INF/blueprint folder. Since our Roo-created project is a Maven project, that means creating the blueprint XML file in src/main/resources/OSGI-INF/blueprint. This one ought to do fine:

<?xml version="1.0" encoding="UTF-8"?>

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:ext="http://geronimo.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
    default-activation="lazy">

   <bean id="numberService" 
       class="com.habuma.numbers.internal.NumberToEnglishServiceImpl" />

   <service ref="numberService" 
       interface="com.habuma.numbers.NumberToEnglishService" />

</blueprint>

I named the file numbers.xml, but the name really isn't important. Any filename with a ".xml" extension will work.

The root of the blueprint specification XML is <blueprint>. Within that the <bean> element declares the NumberToEnglishServiceImpl class as a bean in the blueprint context (just like Spring). Finally, the <service> element refers to that bean and publishes it in the OSGi service registry under the com.habuma.numbers.NumberToEnglishService package (just like Spring-DM).

There's only one more bit of bookkeeping to be done before we're ready to build and deploy our bundle. When Roo first created the project, it assumed that we'd be doing some Spring stuff, so it created a Spring configuration XML file at src/main/resources/META-INF/spring/applicationContext.xml. Since we're using OSGi Blueprint Services and no plain-old Spring, we'll not need that file anymore. And, if our bundle is deployed in an OSGi framework with the Spring-DM extender installed, this file will actually keep our bundle from starting successfully because it refers to stuff in org.springframework.stereotype, which we no longer import in our manifest. The simple solution to this problem is to simply remove applicationContext.xml.

Now after we build the project one last time, we'll have an OSGi bundle with a service that is published to the OSGi service registry using OSGi Blueprint Services. All we need now is an OSGi runtime that supports Blueprint Services.

Even though OSGi R4.2 is rather new, there are already a few options available for using Blueprint Services. Spring-DM 2.0.0.M1, for instance, includes support for Blueprint Services and is, in fact, the reference implementation. But I've been tinkering with Karaf lately, which includes Blueprint out of the box. And just to prove that this will work even without Spring, let's deploy it to Karaf.

Assuming that Karaf is running, all I need to do is to copy numbers-0.1.0-SNAPSHOT.jar from our Roo project's target directory into Karaf's deploy directory. Upon arrival in Karaf's deploy directory, Karaf will install and start the bundle. Then Karaf's Blueprint deployer will pick it up and publish the service to the OSGi service registry.

Once it's deployed, you can verify that the service is being deployed by using the ls command in the Karaf shell:

karaf@root> ls

...

numbers (46) provides:
----------------------
com.habuma.numbers.NumberToEnglishService
org.osgi.service.blueprint.container.BlueprintContainer
karaf@root> 

The ls command lists all of the bundles installed in the OSGi framework along with any services that they provide or consume. In the case of the number service bundle, we can see that it's deployed with the ID of 46 (this will vary depending on what else you've installed before) and provides two services: The NumberToEnglishService and the bundle's blueprint container.

Karaf's list command tells a similar story:

karaf@root> list
START LEVEL 100
   ID   State         Blueprint      Level  Name
...
[  46] [Active     ] [Created     ] [   60] numbers (0.1.0.BUILD-SNAPSHOT)
karaf@root>        

From here I can see that bundle 46 has been started and that a blueprint has been created for it.

Clearly the Blueprint Services have published our service for us. But if you want one more bit of evidence, then we can also look in the web console. If you've not already done so, we'll need to install the web console in Karaf:

karaf@root> features:install webconsole

Simple enough. Now point your browser at http://localhost:8181/system/console. When prompted for a username and password, use "karaf" for both. Once in, find our bundle and drill into its details. Click here to see what I saw in Karaf. I could see (among other things) that my service was published with service ID 118 and the Blueprint container was published as a service with ID 119.

That wraps up my excursion into Roo, Blueprints, and Karaf for today. Note that from start to finish I did all of this in just under 30 minutes, including time to stop and take notes of what I had done. It was simple work putting together this bundle. Part of the simplicity is owed to Blueprint Services--to me the Blueprint model is quite natural and straight-forward. And Roo helped out a ton at the beginning by generating the project structure and (along with Bundlor) generating the manifest.

In hindsight, it was fun to say that I developed an OSGi bundle using Roo. However, I'm not sure that Roo brought a lot to the table aside from the initial project creation. I still prefer Pax Construct for rapidly creating bundle projects. Don't get me wrong, I like Roo...I like it a lot. But in this case I'm not sure that Roo offered a lot once the project was created.

Perhaps in a more interesting example where I'm developing a data access service, Roo would be helpful in setting up the persistence with Hibernate or EclipseLink. Or maybe if I were creating a web bundle, Roo would help out with the controllers.

Nevertheless, the exercise was well worth it. It helped me get comfortable with Roo (albeit in an off-beat kinda way). I got to tinker with Blueprint Services. I had fun fiddling around with Karaf. And ultimately, it gave my unfocused brain something to do that was at least somewhat related to the topic of the session I was sitting in.

By the way, the anxiety I was feeling for my own presentation was unnecessary. From my perspective, it was one of the best presentations that I've ever given. And I've had a few of the attendees tell me that they enjoyed it. It was a great presentation because everyone in the room learned something new. That includes me and even Andy Clement (the creator of SpEL). The crowd suggested several tricks to try with SpEL and we were all uncertain that any of them would work. As it turns out, SpEL's even more capable than any of us knew. Keep an eye on this blog, as I hope to soon post my SpEL presentation in the form of an article.

(2009-10-22 09:00:00.0) Permalink

20091021 Wednesday October 21, 2009

SpringOne/2GX Day 2 Keynote

It's almost 24 hours after the fact, but here's my writeup on the SpringOne/2GX Day 2 Keynote that was given by Adrian Colyer, Karl Rumelhart, and Chris Richardson. I won't go over it in detail as I did with Rod Johnson's keynote...instead I'll just summarize it as best as I can.

The keynote started with Adrian telling a rather humorous story about his luggage. He then went on to try to make sense of what has gone on in the past year with SpringSource, specifically with regard to the various acquisitions (G2One, Hyperic, CloudFoundry, and ultimately the VMWare acquisition of SpringSource).

To help make his point, he called Chris Richardson (founder of CloudFoundry) to the stage to provide a quick demonstration of CloudFoundry. Chris' demo involved deploying a Roo application to the cloud using CloudFoundry.

Adrian resumed the keynote by discussing the notion of deployment blueprints. Deployment blueprints describe the pieces that come together to make up the virtual deployment in the cloud.

Chris then returned to the stage to provide a demo of the new CloudFoundry plugin in SpringSource ToolSuite.

Finally, Kyle Rumelhart takes the stage to describe some of VMWare's products and technologies geared toward the private cloud.

I realize that this summary has been quite brief. To be honest, I was having a hard time following along during the keynote because (1) I was tired, (2) I was too consumed thinking about my talk that I'd be giving today, and (3) while all of it is very interesting, much of what was being shown is less development-oriented and more IT-oriented...especially the private cloud stuff.

(2009-10-21 18:58:40.0) Permalink Comments [2]

20091020 Tuesday October 20, 2009

SpringOne/2GX Day 2 session wrap-up

The second day of sessions at SpringOne/2GX is almost over. Soon, we'll be having dinner and then listening to Adrian Colyer give a keynote address (which I'll summarize in a later post). So I thought I'd go ahead and take a moment to report on my day and the sessions I've attended.

I spent the better part of the day in the "Rich Web Application Development" track, as it had a lot of topics that I find interesting. I started by hearing Keith Donald give an overview of the entire Spring Web stack, focusing on Spring 3.0 MVC. I'm already familiar with the topic, but I wanted to make sure I wasn't missing something in Spring MVC and for lack of another talk to catch my attention I decided to go for Keith's talk. It was a very informative talk. The one thing that I walked away with was a deeper understanding of how to apply Spring 3.0-style REST to my Spring MVC applications.

With REST fresh in my mind, I decided to spend the 2nd session of the day sitting in on Arjen Poutsma's talk that focused on using REST in Spring. Although I've been familiar with Spring 3.0's new REST support for awhile, I still learned something that I didn't already know. Specifically, I wasn't aware that @RequestMapping can take URL patterns with Ant-style wildcards and regular expressions. I also got a better feel for how to divide up my RESTful resources among Spring MVC controllers.

After lunch, I attended Jeremy Grelle's talk on Spring Faces. I'm not a big JSF fanatic, but I decided to make myself go to this talk because I really should be more comfortable with the topic than I am. I'm glad that I went because I learned that Spring Faces offers a Spring-centric approach to JSF where JSF is really just a view technology for Spring MVC (as opposed to a JSF-centric approach where Spring is nothing but a managed bean provider). As a fan of Spring MVC, I like the Spring-centric JSF integration that Spring Faces offers. Couple that with Facelets (I hated the JSP-oriented JSF) and I think I could end up liking (or at least tolerating) JSF.

Next up, I listened to Ben Alex give an introduction to Roo. I've tinkered with Roo here and there before, but never have had a chance to really dig into it. I just gotta say that I think an alternate name for Spring Roo might be "Spring Wow!", because I was blown away by it. I learned some little details about Roo that I didn't realize. For instance, I've seen the .aj files in my toy Roo projects, but didn't know what purpose they served--and in fact, they made me uncomfortable thinking that my project depended on AspectJ without me understanding why. Now I know that Roo uses AspectJ at compile-time only as its magic sauce for automatically weaving in code that I don't want to write (like accessor methods). Roo has no runtime presence and thus no runtime overhead. And, I learned that if I decide to de-Roo my project, it's a very simple 3-step process. Oh, and Roo makes easy work of creating OSGi bundles with its Bundlor support.

Right now I'm listening (sorta...I'm also writing this) to Chris Beams and Mark Pollack talk about a variety of dependency injection styles. They've organized the styles into external DI and internal DI. Spring's XML-based configuration, for example, is external (that is, it doesn't invade your application code). But Spring's @Component and @Autowired-based DI is internal because it invades your Java source. A lot of this talk is old hat to me...I've presented a similar talk before. But I wanted to catch up on the latest options (JSR-330, for example) and get their take on the different DI styles.

As I have already mentioned, Adrian Colyer will be giving a keynote address after dinner tonight. I'll blog about that later tonight or tomorrow. Following that is a sponsor reception and then BOF sessions. Honestly, I'm a bit drained, so I may skip out on the BOF sessions so that I can do some last minute preparations for my SpEL talk tomorrow and get a good night's sleep.

(2009-10-20 18:06:36.0) Permalink Comments [1]

20091019 Monday October 19, 2009

SpringOne/2GX Keynote notes

Rod started out by giving a quick overview of the Spring timeline, starting with the publication of Expert One-on-One J2EE Design and Development, up through the formation of Interface21/SpringSource, and into the more recent acquisitions.

He then described Spring's core values:

With regard to community, Rod invited everyone to get involved. Ask and answer questions on the forums. Request issues and report bugs in JIRA. Participate in community events such as Spring and Java user groups and Groovy and Grails meet-ups. Join the conversation by following SpringSource developers on their blogs and on Twitter. Contribute code through Spring Extensions and by writing tests and patches to the other Spring projects.

[Editor's note: Spring Extensions is the new incarnation of what used to be known as Spring Modules. Spring Modules had a caching module that hasn't been moved to Spring Extensions because, as I understand it, lack of a project owner. If you're looking for an opportunity to get involved, that'd be a great place to start.]

Rod then went on to talk about what's new in Spring. He mentioned a few of the new features in Spring 3.0:

In addition to the new stuff in the Spring Framework, Rod also mentioned some recent and upcoming releases elsewhere in the Spring portfolio:

Rod then highlighted two Spring portfolio projects, Spring Integration and Spring BlazeDS. With regard to Spring Integration, he said that Spring Integration is an embedded message bus that runs within any Spring ApplicationContext--no need for an ESB. All components are Spring-managed objects and can take full advantage of the Spring component model. It also serves as an application integration framework, connecting to other systems via adapters such as File, JMS, HTTP, WS, Mail, UDB/TCP, Twitter, and others.

As for Spring BlazeDS, it bootstraps Adobe Blaze DS within a Spring environment, allowing Spring to manage Flex server-side components. It offers direct remoting from Flex clients to Spring beans and easy integration with Spring Security using regular Flex API. Spring BlazeDS gives Flex applications access to full power of Spring.

At this point, Rod invited Jereme Grelle and Mark Fisher to take the stage and give a demo of Spring BlazeDS and Spring Integration. The demo involved a Flex chat application that used Spring BlazeDS to communicate with server-side objects. On the server-side, Spring Integration was used as an embedded message bus to accept and deliver messages between Flex clients. It was a very impressive demo.

Rod then returned to the stage and told of having tried bacon ice cream (available on the menu at the hotel) and how it reminded him of pigs, which reminded him of Grails. That's because, from the story of the 3 little pigs, he knows that pigs build houses and the Grails house is built on the bricks of the JVM, Java Server infrastructure, and Spring. At this point, he invited Graeme Rocher to speak about Grails and to demo new Grails features coming in SpringSource ToolSuite.

Graeme reported that Grails continues to garner interest, with 150% growth in traffic to the Grails site in the last few months. Groovy 1.7 and Grails 1.2 releases are approaching. But what was most exciting to Graeme is the explosion in the Grails plugin community; over 25 million lines of user-contributed code in over 300 plugins. If you want to do something in Grails, then there's probably a plugin for that.

Graeme then spoke of the challenges in IDE support before demo'ing a Grails-capable version of SpringSource ToolSuite. Coming soon, STS 2.2 will include a much improved Groovy development experience and support for working with Grails in the IDE.

Rod returned to the podium again to speak briefly about SpringSource tcServer, which has been focused on operational concerns. He then announced SpringSource tcServer Developer Edition, which focuses on development-time concerns. It includes the Spring Insight Dashboard which provides real-time performance insights, drill-down transaction tracing, and a view into application health. It is tightly integrated with STS and will be available as a free download.

John Travis, lead tcServer Developer Edition, then demoed tcServer Developer Edition. He wowed the crowd with the ability to dive into a running application in real-time and see what was going on at an amazingly low-level.

Rod then returned to the podium one last time to discuss what's next. He spoke of their latest acquisition...VMWare (obviously joking). But with regard to VMWare's acquisition of SpringSource, he stated that both companies share the same core values. He says that VMWare cares about developer communities, is committed to open-source, and is serious about middleware.

He then went on to talk about moving into the cloud and their recent acquisition of CloudFoundry. Speaking of CloudFoundry, all SpringOne/2GX attendees will receive an invitation to try CloudFoundry for free for 48 hours of server processing time.

Rod wrapped up by saying that it's not just about SpringSource. For the next 3 days we'll have the opportunity to learn about technologies from the source and interact with the Spring team and fellow Spring developers. He also mentioned that we've packed the Roosevelt Hotel in New Orleans, so almost everyone here is a Spring or Grails person.

Finally, and best of all, Rod said that this is the first conference venue that offers the opportunity to try bacon ice cream.

(2009-10-19 19:14:07.0) Permalink Comments [1]

20091014 Wednesday October 14, 2009

Spring conference time is in the air

As of today, it's one week until I present That old Spring magic has me in its SpEL: DI Wizardy with the Spring Expression Language at SpringOne/2GX.

I'm really excited about giving this talk. I've already presented it twice at two different No-Fluff/Just-Stuff shows, but I've had some opportunity to refine it and get it in tip-top shape for SpringOne/2GX. Even if you've heard it when I presented it in Boston or Minneapolis before, this time's going to be a bit different (and hopefully better).

The other thing I'm excited about is that this is the first SpringOne (or The Spring Experience) conference where I only have on presentation and I'm totally prepared for it well in advance. So, instead of skipping sessions to fix my slides and examples, I'll be able to enjoy the conference as an attendee. With all of that free time on my hands, you can count on me to blog and tweet what I hear and see. Keep an eye on this blog to experience SpringOne/2GX from my point of view.

Also, if you're not following me on Twitter already, here's your chance to get on my followers list before the conference. In addition to blogging, I'll be tweeting random bits here and there from both my springinaction and my modularjava Twitter identities. For you lucky folks who are both following me and are at SpringOne/2GX next week, you'll be given a handful of opportunities to pick up a few goodies...I'm going to tweet directions during the conference, so keep watch on my Twitter identities for details.

While I'm advertising all of the ways to follow my online identities, I should mention that I have Facebook pages for both Spring in Action and Modular Java. Sign up as a fan on those pages and maybe I'll toss some goodies your way, too.

Finally, if you're at SpringOne/2GX, I look forward to getting a chance to say "Hi". Even though I'm talking about SpEL, I'll be happy to chat with you about most anything Spring or OSGi oriented. See ya there!

(2009-10-14 09:00:00.0) Permalink Comments [2]

20090826 Wednesday August 26, 2009

I don't really sound like that, do I?

Last week, I had the honor of participating in a podcast with Mike Abney and Leo Sakhvoruk, a few of my Improving colleagues. That podcast went live yesterday and you can listen to it at Improving Podcasts.

It was a good conversation, mostly focused on my favorite topics, Spring and OSGi. This is the first time I've participated in such an event and I'm usually not that great at answering questions off-the-cuff. But after listening to it, I don't think that I sounded too dumb. There are a few things I would've rephrased, but overall I think it was a good experience...I hope that you'll agree.

If after listening you really want to hear me talk some more, then here's just a quick reminder of where I'll be talking Spring and OSGi some more over the next few months:

Hope to see you there!

(2009-08-26 10:00:00.0) Permalink

20090824 Monday August 24, 2009

A bit of Modular Java errata

There has been more than one comment in the errata for Modular Java that mention a strange NoClassDefFoundError with regard to org.compass.core.util.reflection.ReflectionMethod.

I started to address these concerns on the errata page, but decided to talk about it here because (1) the comment button on the errata page seems to be missing right now and (2) I want to address it once instead of once for each errata item. Once I get the comment button back, I'll point the readers here for more info.

As it turns out, when I run my local instance of Dude, Where's My JAR?, I get that very same exception. I never really noticed it before, but sure enough it's there. Why didn't I notice it? Didn't I test this? Am I, as one reviewer incorrectly suggested, asking my readers to do my QA for my book?

Absolutely not! Believe me when I say that I walked through the instructions for Dude, Where's My JAR? no less than a half-dozen times before the book went to print. My editor will attest to the fact that I've put in far more testing time on this book's examples than for any of my previous books. I am confident that the examples in the book were working before they were published. Had they not been, I would've corrected them before they ended up in your hands. Furthermore, I know of several people who have also successfully worked through the examples.

Are they perfect? Probably not. I'd be shocked if I were ever able to, on my own, produce a flawless example. But I'm certain that I didn't just toss the example over the wall for the readers to sort through.

But the question still remains: How did I not notice the NoClassDefFoundError? Well, even though I witnessed that error when I ran my own instance of Dude, Where's My JAR?, the application still works. The spider crawls the repository, deposits its findings in the index, and the web lets me search for JAR files. The example works in spite of the error. The error itself happens very early in the startup of the application, so unless I'm paying very close attention, it scrolls off the screen unnoticed. Since the application works, I never felt compelled to review the log files for the error.

But this doesn't mean that the case is closed. I do not think such an exception should go unanswered. I will try to figure out why the error happens (I suspect it has something to do with the way OSGi class loaders work) and once I find a way to keep it from appearing, I'll let everyone know how to fix it. In the meantime, feel free to ignore that error--as far as I can tell it is innocuous.

(2009-08-24 21:49:41.0) Permalink Comments [4]

20090803 Monday August 03, 2009

Testing OSGi...Spring Style

Last week I showed you how to test OSGi bundles. We used Pax Exam to fire up an OSGi runtime of our choosing, install and start a selection of bundles, and to make assertions against the BundleContext and services registered in the OSGi service registry. This week, we're going to repeat that exercise, this time using Spring-DM's testing support.

Spring-DM's testing support works very much like Pax Exam. When a test is run, it will start an OSGi runtime, install a selection of bundles, create an on-the-fly bundle containing the test class, and then install the test bundle into the OSGi runtime so that it can perform its assertions from the inside.

At the center of Spring-DM's OSGi testing framework is AbstractConfigurableBundleCreatorTests, a JUnit 3 base class that all bundle tests will extend. It provides the basic functionality needed to access the OSGi BundleContext, consume services, and make assertions about your bundles.

I know what you're thinking...JUnit 3? Really? Yes, Spring-DM's testing support is currently based on JUnit 3. But there's plans to move it to JUnit 4 in Spring-DM 2.0.0. If you're interested in following the progress, then have a look at OSGI-410. In the meantime, we'll have to work with what we've got.

So let's get started writing a Spring-DM bundle test. We'll start with the basics and build it up as we go.

public class PigLatinTranslatorBundleTest 
      extends AbstractConfigurableBundleCreatorTests {

   @Override
   protected String[] getTestBundlesNames() {
      return new String[] {
          "com.habuma.translator, interface, 1.0.0",
          "com.habuma.translator, pig-latin, 1.0.0"
        };
   }   

   // test methods go here
}

Aside from extending AbstractConfigurableBundleCreatorTests, the first thing we're going to do is override the getTestBundlesNames. AbstractConfigurableBundleCreatorTests doesn't require us to override this method (or any method, for that matter), but if we don't override this method, the OSGi runtime will be started without much to test. So, I've overridden this method to identify the bundles we want installed in our test scenario.

Much like how we started our Pax Exam test last week, here we're specifying the bundles as Maven dependencies. But instead of using a fluent API, as with Pax Exam, we return an array of String where each member is a comma-separated list of group ID, artifact ID, and version number (and optionally type). Also unlike the Pax Exam version, we didn't have to explicitly ask for Spring-DM bundles to be installed. That's because Spring-DM is assumed and will be installed by default.

Now we can write the first test method. Just like we did with Pax Exam, we'll start by testing that the OSGi runtime starts okay by asserting that we have a BundleContext:

public void testOsgiPlatformStarts() {
   assertNotNull(bundleContext);
}

The bundleContext variable is a given for test classes that extend AbstractConfigurableBundleCreatorTests. If the OSGi runtime fails to start for any reason, bundleContext will be null. But if there aren't any problems, we'll have a reference to the BundleContext through which we can make some assertions.

Next up, we want to be sure that the Pig Latin bundle registers a Translator service in the OSGi service registry and that the service has its "translator.language" property set to indicate that it is a Pig Latin translator. There are a couple of ways to accomplish this using AbstractConfigurableBundleCreatorTests, but let's first try by mimicking the style of test we wrote last time with Pax Exam:

public void testServiceReferenceExists() {
   ServiceReference serviceReference = 
      bundleContext.getServiceReference(Translator.class.getName());
   assertNotNull(serviceReference);
   assertEquals("Pig Latin", 
         serviceReference.getProperty("translator.language"));
}

This method should be familiar, as it is almost identical to the serviceReferenceShouldExist() method from the Pax Exam example (the name has been changed to accommodate JUnit 3's conventions). Here, it goes directly to the BundleContext to get a ServiceReference for our service. From that ServiceReference, it makes the assertions necessary to satisfy the requirements.

The testServiceReferenceExists() method works using a more conventional programmatic approach to working with OSGi services. But this is a Spring-DM test--we can leverage Spring-DM to declaratively get a reference to the Translator service. To do that, we'll need to create a Spring context configuration that references the service:

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

<reference id="translator"
    interface="com.habuma.translator.Translator"
    filter="(translator.language=Pig Latin)" />

</beans:beans>

The <reference> element from Spring-DM's configuration namespace creates a bean in the Spring application context that is a proxy to the OSGi service. In this case, the service we're looking for is one that implements com.habuma.translator.Translator and whose "translator.language" property is set to "Pig Latin".

Next, we'll need to override AbstractConfigurableBundleCreatorTests's getConfigLocations() method to tell our test about the Spring configuration file:

@Override
protected String[] getConfigLocations() {
   return new String[] { "bundle-test-context.xml" };
}

The getConfigLocations() method identifies one or more Spring configuration files so that they can be included in the on-the-fly bundle. When a Spring-DM bundle test starts, it will load a Spring application context using the configuration files. In this case, that Spring context will include a reference to a Translator service.

Now we have a Spring context with a reference to a Translator service and our test class knows about the Spring context. The only setup work left to do is to create a property in the test class to hold the reference to the service:

public class PigLatinTranslatorBundleTest 
      extends AbstractConfigurableBundleCreatorTests {

   private Translator translator;
   public void setTranslator(Translator translator) {
      this.translator = translator;
   }

   // ...
}

When the Spring-DM test bundle starts and when its Spring application context is created, the translator property will automatically get set through the setTranslator method, wiring it with the service reference from bundle-test-context.xml. With the Translator service reference in hand, we're ready to test the service:

public void testTranslatorService() {     
   assertNotNull(translator);
   assertEquals("id-DAY is-thAY ork-wAY", 
         translator.translate("Did this work"));
}

The test method starts by asserting that we actually have a translator to work with. Then, we toss it some text to be sure that the translator can properly translate it into Pig Latin.

And that's it. We now have a Spring-DM bundle test that's roughly equivalent to what we wrote last week using Pax Exam. The finished test class, in its entirety, is as follows:

package com.habuma.translator.test;
import org.osgi.framework.ServiceReference;
import org.springframework.osgi.test.AbstractConfigurableBundleCreatorTests;
import com.habuma.translator.Translator;

public class PigLatinTranslatorBundleTest 
      extends AbstractConfigurableBundleCreatorTests {
   private Translator translator;

   public void setTranslator(Translator translator) {
      this.translator = translator;
   }
   
   @Override
   protected String[] getTestBundlesNames() {
      return new String[] {
          "com.habuma.translator, interface, 1.0.0",
          "com.habuma.translator, pig-latin, 1.0.0"
        };
   }   
    
   @Override
   protected String[] getConfigLocations() {
      return new String[] { "bundle-test-context.xml" };
   }
   
   public void testOsgiPlatformStarts() {
      assertNotNull(bundleContext);
   }
   
   public void testServiceReferenceExists() {
      ServiceReference serviceReference = 
         bundleContext.getServiceReference(Translator.class.getName());
      assertNotNull(serviceReference);
      assertEquals("Pig Latin", 
            serviceReference.getProperty("translator.language"));
   }
   
   public void testTranslatorService() {     
      assertNotNull(translator);
      assertEquals("id-DAY is-thAY ork-wAY", 
            translator.translate("Did this work"));
   }
}

Testing options

With Pax Exam, we were able to resolve test bundles using any means available to Pax Runner, including Maven, filesystem, and HTTP URLs. Unfortunately, Spring-DM's testing support is limited to resolving bundles as Maven artifacts. (Although you can opt to override getTestBundles() instead of getTestBundlesNames() to resolve bundles yourself using whatever means you'd like.)

But, we can tweak the OSGi runtime. By default, Spring-DM testing will use Equinox, but you can switch to Felix by overriding the getPlatformName() method:

protected String getPlatformName() {
   return Platforms.FELIX;
}

Or, if you're more of a Knopflerfish kind of person, then:

protected String getPlatformName() {
   return Platforms.KNOPFLERFISH;
}

Unlike Pax Exam, however, Spring-DM testing currently only supports a single version of these frameworks (specifically, Spring-DM 1.2.0 uses Equinox 3.2.2, Felix 1.4.1, or Knopflerfish 2.2.0). And, also unlike Pax Exam, you must choose a single runtime...you can't ask Spring-DM to run your tests on more than one OSGi runtime. (Although you could write separate tests that use different runtimes.)

Should I use Pax Exam or Spring-DM testing?

I'm not going to tell you which testing framework to use--I'll leave it up to you to pick which one suits you best. But I will share my opinions on the subject...maybe it will help you decide.

I like the way that Spring-DM's testing automatically wires in service references for my test to consume so that I don't have to look them up myself in my tests. But, given that Spring-DM's testing support is currently based on JUnit 3, I'm a little turned off from it. Furthermore, given the limitations in bundle resolution and platform selection, I find Spring-DM testing to be somewhat inferior to Pax Exam.

That said, I believe both sides could learn a bit from each other. Spring-DM's testing could obviously be bumped up to be based on JUnit 4 and to be more flexible with regard to bundle resolution and platform selection. Meanwhile, Pax Exam could learn a little from Spring-DM testing on how to wire test properties with OSGi services.

In any event, whether you use Pax Exam or Spring-DM testing, we can all agree that testing is a worthwhile practice. And regardless of which one you use, there's no reason to not extend that good practice into OSGi development.

That's it for this week. I'm still scheming on what I want to write about for next time--I won't tell you everything that I've got in mind, but I can say that I'm thinking of showing you a way to test OSGi-based applications in a way that is difficult (or perhaps even impossible) without OSGi's dynamic runtime. Keep an eye on this blog to get the details.

(2009-08-03 10:00:00.0) Permalink Comments [5]

20090728 Tuesday July 28, 2009

Putting OSGi to the test with Pax Exam

After a small delay, I finally bring you the next installment in my series of OSGi-oriented articles. This time we're going to have a look at writing tests around OSGi bundles.

It should go without saying that testing is an important part of software development. Developer-driven tests are often based on JUnit and usually focus on testing application units in isolation. But it's just as important to write integration tests to ensure that those units play well together. With regard to OSGi, it's important to write tests that put one or more bundles in an OSGi runtime to make sure that those bundles behave as expected.

I made the claim a few months ago that testing OSGi is quite easy. Today I'm going to show that to be true by showing you Pax Exam.

Pax Exam is a testing toolkit that addresses the need for bundle-level testing. What's particularly interesting about Pax Exam is how it works. When a Pax Exam test is run, it starts an OSGi framework, installs and starts a selection of bundles, and then makes an OSGi BundleContext available through which you can make assertions about your bundles, the services that they publish, and the effects that they have on each other.

Before we get started, you should know that I've reworked the previous article's Pig Latin translator project quite a bit. The new version is about translator services in general, of which Pig Latin is one implementation. Some package names have changed and it's now a Pax Construct-based project. I'm not going to go over the new code here, but it should be familiar enough that you should be able figure it out. Download the example code to follow along.

To get started with Pax Exam, we're going to create a separate project to house our bundle tests. There are a lot of ways to do this, but knowing that our bundle-test project is only going to contain a Maven pom.xml file and a single test class, I find it easy enough to take advantage of the Unix mkdir command and its -p option:

translators% mkdir -p bundle-tests-exam/src/test/java/com/habuma/translator/test

That sets up all of the directory structure we need. To fill it out, we're going to place a pom.xml file in the bundle-tests-exam directory and a test class in the bottom level test directory. (Sorry Windows users...I don't think your mkdir has an equivalent of the -p, so you'll have to create the directory structure manually.)

Okay, so let's create the pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.habuma.translator</groupId>
  <artifactId>bundle-tests-exam</artifactId>
  <version>1.0.0</version>

  <packaging>jar</packaging>

  <build>
      <plugins>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
        </plugin>
      </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>com.habuma.translator</groupId>
      <artifactId>interface</artifactId>
      <version>1.0.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.ops4j.pax.exam</groupId>
      <artifactId>pax-exam</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.ops4j.pax.exam</groupId>
      <artifactId>pax-exam-container-default</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.ops4j.pax.exam</groupId>
      <artifactId>pax-exam-junit</artifactId>
      <version>1.0.0</version>
      <scope>test</scope>
    </dependency>        

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.5</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

There are several things I'd like to highlight in this pom.xml:

With the Maven setup out of the way, we're now ready to write our test class. PigLatinTranslatorBundleTest uses Pax Exam's JUnit4TestRunner to run a series of OSGi bundle tests.

package com.habuma.translator.test;
import static org.junit.Assert.*;
import static org.ops4j.pax.exam.CoreOptions.*;
import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.*;
import java.util.List;
import java.util.Properties;
import org.junit.Test;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Inject;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;

import com.habuma.translator.Translator;

@RunWith(JUnit4TestRunner.class)
public class PigLatinTranslatorBundleTest {
   @Inject
   private BundleContext bundleContext;

   private Translator translator;

   @Before
   public void setup() throws Exception {
       translator = retrievePigLatinService();       
   }

   @Configuration
   public static Option[] configuration()
   {      
      return options(equinox(), profile("spring.dm"), provision(
        mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
        mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
      ));
   }  

   // ... Test methods go here ...

   private Translator retrievePigLatinService() throws InterruptedException {

      ServiceTracker tracker = new ServiceTracker(bundleContext, 
            Translator.class.getName(), null);
      tracker.open();
      Translator pigLatinService = (Translator) tracker.waitForService(5000);
      tracker.close();
      assertNotNull(pigLatinService);
      return pigLatinService;
   }
}

Probably the most interesting piece of PigLatinTranslatorBundleTests is the configuration() method. It is annotated with @Configuration to indicate that this method will return an array of Pax Exam options--effectively configuring the Pax Exam test case.

Within the configuration() method, I use a set of static methods provided by Pax Exam's CoreOptions and PaxRunnerOptions classes. Specifically, I ask Pax Exam to run the tests within the latest version of Equinox, using Pax Runner's Spring-DM profile. As for the bundles I want to test, I ask it to install the translator project's inteface and pig-latin bundles.

When the Pax Exam test starts up, the first thing it will do is start an OSGi framework (in this case, the latest version of Equinox), install the bundles specified by the Spring-DM profile, and then install our bundles that we want to test. At this point, the OSGi runtime is running, loaded, and ready to roll.

But before we can test our Pig Latin bundle, we're going to need a reference to the Pig Latin service and to the BundleContext. To accomodate that, Pax Exam offers an @Inject annotation to automatically provide the BundleContext to the test. With the BundleContext in hand, the setup() method calls retrievePigLatinService() to lookup the service.

Now we're ready to start testing our bundles. The first thing we should do is make sure that the BundleContext is available. If anything goes wrong while starting the OSGi runtime, we won't have a BundleContext to work with and there'd be no point in testing anything else. So, let's write a test that simply asserts that the bundleContext variable is not null:

@Test
public void bundleContextShouldNotBeNull() throws Exception {
   assertNotNull(bundleContext);
}

Great! Assuming that the BundleContext is available, we can now do something more interesting, such as testing that we get a service that implements the Translator interface that we expect:

@Test
public void serviceReferenceShouldExist() {
   ServiceReference serviceReference = 
      bundleContext.getServiceReference(Translator.class.getName());
   assertNotNull(serviceReference);
   assertEquals("Pig Latin", 
         serviceReference.getProperty("translator.language"));
}   

Here, I'm looking up a service reference for the Translator interface and asserting that the service has been registered with its translator.language property set to "Pig Latin".

If that test passes, then we know that the OSGi runtime is up and running and that there's a service that claims to implement the Translator interface. Finally, let's write one more test just to see that the service does what we think it should do:

@Test
public void shouldTranslateText() {     
   assertNotNull(translator);
   assertEquals("id-DAY is-thAY ork-wAY", 
         translator.translate("Did this work"));
}   

This test doesn't have to be a comprehensive test of the translator's abilities--there should be a unit-test that exercises every corner of the test. This test is just a simple smoke test to be sure that we get a service that meets our expectations.

Testing with different OSGi runtimes

One of the things that makes Pax Exam so powerful is that it's very flexible and can be configured to test bundles using virtually any OSGi frameworks. Under the covers, Pax Exam uses Pax Runner to start up the OSGi runtime, so a Pax Exam-based test can run within pretty much any setup that Pax Runner can provide.

Up until now, we've focused our test on running within the latest version of Equinox. That's what the equinox() option is for. But let's suppose that we want to test with the latest version of Felix instead. No problem, just change the configuration() method:

@Configuration
public static Option[] configuration()
{      
   return options(felix(), profile("spring.dm"), provision(
     mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
     mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}

Testing with either Equinox or Felix is nice, but it might be helpful to test in the latest version of both Felix and Equinox:

@Configuration
public static Option[] configuration()
{      
   return options(equinox(), felix(), profile("spring.dm"), provision(
     mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
     mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}

Given this arrangement of OSGi frameworks, the three test methods will be executed twice--once for Equinox and once again for Felix.

Maybe the latest version of the framework(s) isn't what you need to test. Maybe you want to hand select a specific version. How about Equinox 3.4.2 and Knopflerfish 2.3.1?

@Configuration
public static Option[] configuration()
{      
   return options(equinox().version("3.4.2"), knopflerfish().version("2.3.1"), 
     profile("spring.dm"), provision(
       mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
       mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}

Or maybe you don't want to choose. Maybe you need to know that your bundles work equally well regardless of the OSGi framework that they're installed into. In that case, we might as well test it against all versions of all OSGi frameworks:

@Configuration
public static Option[] configuration()
{      
   return options(allFrameworksVersions(), profile("spring.dm"), provision(
       mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
       mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}  

When I ran the test against all version of all frameworks, the tests were run against 29 varieties of OSGi runtimes in about four and a half minutes. Maybe that's overkill for your needs and all you need is to know that it works in the latest version of all of the popular OSGi runtimes. In that case, allFrameworks() is the way to go:

@Configuration
public static Option[] configuration()
{      
   return options(allFrameworks(), profile("spring.dm"), provision(
       mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
       mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}  

Or maybe you don't care about Knopflerfish or Felix...but you need to know for certain that it works for all versions of Equinox:

@Configuration
public static Option[] configuration()
{      
   return options(allEquinoxVersions(), profile("spring.dm"), provision(
       mavenBundle().groupId("com.habuma.translator").artifactId("interface"),
       mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}  

(Or, if you'd prefer, allFelixVersions() or allKnopflerfishVersions().)

As you can see, you can test your bundles within almost any OSGi runtime. But what about provisioning? Do you have to provision all of the bundles from Maven?

Provisioning options

Given that our bundles are built with Maven, provisioning them from the Maven repository is awful convenient. But it's not the only way to provision bundles for a test. If you'd rather configure a bundle from an HTTP URL, then no problem:

@Configuration
public static Option[] configuration()
{      
   return options(equinox(), profile("spring.dm"), provision(
       bundle("http://www.habuma.com/osgi/bundles/translator-interface.jar"),
       mavenBundle().groupId("com.habuma.translator").artifactId("pig-latin")
   ));
}  

Or perhaps you'd like to pull in a bundle from the filesystem:

@Configuration
public static Option[] configuration()
{      
   return options(equinox(), profile("spring.dm"), provision(
       bundle("http://www.habuma.com/osgi/bundles/translator-interface.jar"),
       bundle("file:/Users/wallsc/bundles/pig-latin-translator.jar")
   ));
}  

By now you should have a strong appreciation for what Pax Exam brings to the table. Using Pax Exam, you can test a selection of bundles within the OSGi framework(s) of your choice in a relatively tight JUnit test. We've seen how to create a test that asserts some basic expectations about our bundles and that acts as a service consumer to assert that the service works as we'd like.

Next time I plan to show you how Spring-DM supports bundle testing. We'll see how Spring-DM comes with testing support that resembles Pax Exam in many ways, but that has its own special Spring twist. And I promise not to let 2-3 months pass between now and that next blog entry.

(2009-07-28 10:00:00.0) Permalink

20090721 Tuesday July 21, 2009

Meanwhile, back at the ranch...

If anyone's looking for me this week, I'll be at the ranch...JavaRanch, that is.

This week, I'm the guest question-answerer in JavaRanch's Application Frameworks forum. I'm fielding questions on OSGi, Spring-DM, Pax, and other such things.

So, stop by, ask some questions, and get a chance to win a free copy of Modular Java.

(2009-07-21 01:27:01.0) Permalink

20090619 Friday June 19, 2009

The book is in the mail

For the benefit of those of you who don't follow me (@habuma and @modularjava) or Dave Thomas (@pragdave) on Twitter, I'm happy to announce that Modular Java has been printed and will be shipping very soon!!

For those of you who've already ordered your copies, thank you...they're on the way. For those of you who haven't, I understand. You're a patient person...I get it. You're the kind of person who kindly lets others ahead of you in line at the grocery store...we appreciate that. You let some kid take the last slice of pepperoni at the pizza buffet...because you know that a hot fresh slice is coming out soon. You don't shake it like a Polaroid picture, because you know that photograph will be ready soon enough. You like your books like you like your compiler...just in time.

Here's to you, Mr. Imperturbability Guy (or Gal). You're time has come. The wait is over. Pull out your wallet and have that 3-digit security code on ready as you point your browser toward PragProg.com. Upon placing your order, Dave will promptly print a shipping label and will send the book your way post haste.

Of course, you'll have to apply patience once more...the postal service can only move so fast.

(2009-06-19 14:06:17.0) Permalink

20090608 Monday June 08, 2009

NFJS Dallas 2009 Retrospective

The Dallas NFJS event for 2009 wrapped up yesterday evening. It had (unfortunately) been awhile since I had been to one of these shows and I gotta say that I really missed the boost that I get from hearing all of the good talk on software development.

First, what went well: I attended talks by Venkat Subramaniam, Stu Halloway, and Scott Davis on topics such as Scala, Git, Clojure, Groovy, and Grails. These guys are all good friends from NFJS events of years past and I always enjoy seeing and chatting with them. With the exception of Groovy and Grails (and to a much lesser degree, Scala), these were all somewhat new topics to me and it was great to learn something new that I believe I can start applying on my own projects today. Stu's Clojure talk in particular opened my eyes to how this deceptively cryptic LISP language could actually be easier to read than Java. In fact, that was a common theme among the language-oriented talks: How they remove the noise from Java. I also had my first chance to decypher Git and am considering using Git on a personal project.

I also think that my "Beyond JUnit" talk went much better than I had anticipated. It was the first time that I had presented that topic and I wasn't sure how well it would be received or how well it'd fit the time. It actually worked out very well and I think I'll try to present this one again someday.

What went not so well? Not much, really. My own talk on OSGi could've been organized better to fit the time allotted. I knew going into it that I probably wouldn't be able to cover it all, but I now see some opportunities to rearrange it to fit nicely in 90 minutes or less. As usual, my presence on the expert panel was somewhat lackluster--I often don't have strong thoughts or opinions on the questions being asked and when I do, one of the other panelists will have already stated what I was thinking and I hate to be a "me too" panelist.

The only other bad thing is that I arrived on Friday with a nasty headache and wasn't exactly the most social person in the conference--sorry if I was off-putting to anyone.

What could be improved? As I said, my OSGi talk needs a bit of reorganization to fit the time. For the most part, my live coding went well, but it was rushed a bit. My "Beyond JUnit" talk, while it went smoothly, could stand a bit of rework. There are other subtopics that I'd like to include in the talk and some subtopics that I might minimize or remove completely if I had to do it again.

I also think that as I select the topics to attend, I should mix it up better. NFJS is loaded with great speakers and topics, but I only stuck with 3 of the speakers and most of that was focused on language-oriented talks. I didn't realize that until the conference was almost over, but in hindsight, I should've mixed it up a bit more.

In summary, Jay and crew did an amazing job, as always and I am proud to have been a part of it. I am already looking forward to my next NFJS event, whenever/wherever that will be (Jay? Any thoughts on that? Hint hint hint).

Next up for me: Dallas TechFest 2009 in Frisco, TX. There I'll be talking about all that is new and exciting in Spring 3.0. See ya there.

(2009-06-08 08:32:24.0) Permalink

20090607 Sunday June 07, 2009

Spring-DM RefCard Available for Download

I'm happy to announce that my latest DZone RefCard, Getting Started with Spring-DM is now available for free download.

This RefCard covers all of the basics of working with Spring-DM (and a few advanced tips). In a succinct 6 pages, you'll learn how to...

I'm excited about this RefCard not only because it represents the blending of two of my favorite topics (Spring and OSGi), but also because it provides you with the essentials for working with the SpringSource dm Server and gives you a foundation for what's to come with Blueprint Services in OSGi R4.2.

After downloading the Spring-DM RefCard, if you find yourself wanting more, then I encourage you to check out Modular Java. As I write this, the book is at the printers and should start shipping from Pragmatic in the next few weeks (and will be in other bookstores shortly after that). Even then, if you can't wait, it's also currently available in beta form from Pragmatic or for pre-order from Amazon.com.

(2009-06-07 10:52:47.0) Permalink Comments [3]