ModeShape

An open-source, federated content repository

Free JBoss Developers Studio 2 Beta

Download the JBoss Developers Studio 2 Beta for free. Max has all the details here. Did I mention that it’s free?

Filed under: news, tools

Internationalization in JBoss DNA

It’s pretty important to be able to create applications that support multiple languages, and most libraries should provide some kind of support for this. The first step is making your code support internationalization, but then you need to localize the application for each language (or locale). We’ve included internationalization (or “i18n”) in JBoss DNA from the beginning, but we haven’t done much with localization (or “L10n”), and have only one (default) localization in English.

Java really does a crappy job at supporting internationalization. Sure, it has great Unicode support, and it does provide a standard mechanism for identifying locales and looking up bundles given a locale. But where is the standard approach for representing an internationalized message ready for localization into any locale? ResourceBundle.getString()? Seriously?

What I want is something analogous to an internationalized String capable of holding onto the replacement parameters. Each internationalized string should be associated with the key used in the resource bundles. I want to localize an internationalized string into the default locale, or into whatever locale you supply, and even into multiple locales (after all, web applications don’t support just one locale). And I should be able to use my IDE to find where each internationalized string is used. I should be able to test that my localization files contain localized messages for each of the internationalized strings used in the code, and that there are no duplicate or obsolete entries in the files. I also don’t want that many resource files (one per package – like Eclipse used to do – sucks); one per Maven project is just about right.

I’m not asking for much.

Meet the players

There are quite a few existing internationalization (aka, “i18n”) open source libraries, including JI18n, J18n, Apache Commons I18n, just to name a few. Too many of these try to be too smart and do too much. (Like automatically localizing a message identified by a Java annotation into the current locale, or using aspects to do things automatically.) This stuff just tends to confuse IDE dependency, search, and/or debuggers. We found nothing we liked, and lots of things we didn’t like. Internationalization shouldn’t be this hard.

Sweet and to the point
So we did what we don’t like to do: we invented our own very simple framework. And by simple, I mean there’s only one I18n class that represents an internationalized string with some static utility methods (and an abstract JUnit test class; see below). To use, simply create an “internationalization class” that contains a static I18n instances for the messages in a bundle, and then create a resource bundle properties file for each of these classes. That’s it!

So, let’s assume that we have a Maven project and we want to create an internationalization class that represents the internationalized strings for that project. (We could create as many as we want, but one is the simplest.) Here’s the code:

public final class DnaSubprojectI18n {

// These are the internationalized strings ...
public static I18n propertyIsRequired;
public static I18n nodeDoesNotExistAtPath;
public static I18n errorRemovingNodeFromCache;

static {
// Initializes the I18n instances
try {
I18n.initialize(DnaSubprojectI18n.class);
} catch (final Exception err) {
System.err.println(err); // logging depends on I18n, so we can't log
}
}
}

Notice that we have a static I18n instance for each of our internationalized strings. The name of each I18n variable corresponds to the key in the corresponding property file. Pretty simple boilerplate code.

The actual localized messages are kept same package as this class, but since we’re using Maven the file goes in src/main/resources):

  propertyIsRequired = The {0} property is required but has no value
nodeDoesNotExistAtPath = No node exists at {0} (or below {1})
errorRemovingNodeFromCache = Error while removing {0} from cache

Again, pretty simple and nothing new.

Using in your code
At this point, all we’ve done is defined a bunch of internationalized strings. Now all we need to do to use an internationalized string is to reference the I18n instance you want (e.g., DnaSubprojectI18n.propertyIsRequired). Pass it (and any parameter values) around. And when you’re ready, localize the message by calling I18n.text(Object...params) or I18n.text(Locale locale, Object...params). The beauty of this approach is that IDE’s love it. Want to know where an internationalized message is used? Go to the static I18n member and find where it’s used.

The logging framework used in JBoss DNA has methods that take an I18n instance and zero or more parameters. (Debug and trace methods just take String, since in order to understand these messages you really have to have access to the code, so English messages are sufficient.) This static typing helps make sure that all the developers internationalize where they’re supposed to.

With exceptions, we’ve chosen to have our exceptions use Strings (just like JDK exceptions), so we simply call the I18n.text(Object...params) method:

  throw new RepositoryException(DnaSubprojectI18n.propertyIsRequired.text(path));

We’ll probably make this even easier by adding constructors that take the I18n instance and the parameters, saving a little bit of typing and delaying localization until it’s actually needed.

Testing localizations
Testing your internationalization classes is equally simple. Create a JUnit test class and subclass the AbstractI18nTest class, passing to its constructor your DnaSubprojectI18n class reference:

public class DnaSubprojectI18nTest extends AbstractI18nTest {
public DnaSubprojectI18nTest() {
super(DnaSubprojectI18n.class);
}
}

That’s it. The test class inherits test methods that compare the messages in the properties file with the I18n instances in the class, ensuring there aren’t any extra or missing messages in any of the localization files. That’s a huge benefit!

One more thing …
Remember when I said there was only one class to our framework? Okay, I stretched the truth a bit. We also abstracted how the framework loads the localized messages, so there’s an interface and an implementation class that loads from standard resource bundle property files. So if you want to use a different loading mechanism for your localized messages, feel free.

Props to John Verhaeg and Dan Florian for the design of this simple but really powerful framework.

Filed under: techniques, testing, tools

Mockito 1.5

Mockito 1.5 has been released with several nice enhancements. Perhaps one of the most useful is the ability to spy on non-mock objects. In other words, you can verify that methods are called on the non-mock object. So, for example (from the release notes):

   List list = new LinkedList();
   List spy = spy(list);

   //wow, I can stub it!
   stub(spy.size()).toReturn(100);

   //wow, I can use it and add real elements to the list!
   spy.add("one");

   //wow, I can verify it!
   verify(spy).add("one);

I haven’t wanted to do this too often, but there was an occasion or two.

Another improvement is supposed to result in more readable code. Instead of

   stub(obj.someMethod()).toReturn(result);

it is now possible to write:

   doReturn(result).when(obj).someMethod();

Notice that the code is exactly the same length, so it’s clearly up to you whether you think it’s more or less readable. In addition to doReturn(), there’s also doThrow(), doAnswer(), and doNothing().

Check out the Mockito documentation for examples and details on how to use.

Filed under: techniques, testing, tools

JBoss.org upgrades JIRA

Last night, the good folks at JBoss.org upgraded JIRA to version 3.12.3. This latest version has some very nice new features and bug fixes. I especially like the Subversion Commits report and the other new tabs on the Browse Project page.

Nicely done, JBoss.org!

Filed under: tools

Testing behaviors

I mentioned in my last post how learning Ruby has made me a better Java developer. In particular, learning RSpec opened my eyes to a new way of unit testing.

RSpec is a library for Ruby that is built around Behavior Driven Development (BDD). In BDD and with RSpec, you focus on specifying the behaviors of a class and write code (tests) that verify that behavior. Whether you do this before you write the class is up to you, but I’ve found that outlining the class’ behaviors before (or while) I write the class helps me figure out what exactly the implementation should do.

You may be thinking that BDD sounds awfully similar to Test Driven Development (TDD). In some ways they are similar: they both encourage writing tests first and for fully testing the code you write. However, TDD doesn’t really guide you into the kinds of tests you should be writing, and I think a lot of people struggle with what they should be testing. BDD attempts to give you this guidance by getting the words right so that you focus on what the behaviors are supposed to be.

Let’s look at an example of a class that represents a playlist. The first step will be to decide what the class should and should not do:

Playlist

  • should not allow a null name
  • should not allow a blank name
  • should always have a name
  • should allow the name to change
  • should maintain the order of the songs
  • should allow songs to be added
  • should allow songs to be removed
  • should allow songs to be reordered
  • should have a duration that is a summation of the durations of each song
  • should not allow a song to appear more than once

Really, these are just the requirements written as a list. With BDD and JUnit 4.4, we can capture each behavior specification as a single unit test method. Initially, we’ll just stub the methods, but later on we’ll implement the test methods to verify the class actually exhibits that behavior. And since JUnit 4.4 gives us the freedom to name our test methods anything we want, let’s take a play from the RSpec playbook and put these behavior specifications directly in our test method names. Pretty cool! Just start listing the expected behaviors, and the test methods simply fall out:

public class PlaylistTest {
 @Test public void shouldNotAllowANullName() {}
 @Test public void shouldNotAllowABlankName() {}
 @Test public void shouldAlwaysHaveAName() {}
 @Test public void shouldAllowTheNameToChange() {}
 @Test public void shouldMaintainTheOrderOfTheSongs() {}
 @Test public void shouldAllowSongsToBeAdded() {}
 @Test public void shouldAllowSongsToBeRemoved() {}
 @Test public void shouldAllowSongsToBeReordered() {}
 @Test public void shouldHaveADurationThatIsASummationOfTheDurationsOfEachSong() {}
 @Test public void shouldNotAllowASongToAppearMoreThanOnce() {}
}

By capturing the requirements/behaviors in the test class, we don’t need to document them elsewhere. We can even add JavaDoc if the name isn’t clear. And, with a little work, we could generate that list of requirements by processing (or sequencing!) our code, as long as we follow the convention that the method names form a camel-case but readable English description of the behavior. (In fact, the org.jboss.dna.common.text.Inflector has a method to “humanize” camel-case and underscore-delimited strings, making it a cinch to output human readable code.)

And our test class even compiles. Pretty cool, huh? Oh, and that last requirement that’s not very intuitive? We now have a specification (test method) that verifies the seemingly odd behavior, so if a developer later on changes this behavior, it’ll get caught. (Of course the developer might just blindly change the test, but that’s another problem, isn’t it?)

But back to our development process. At this point, we could implement the test methods using the non-existent Playlist class. It may not compile, but we could then use our IDE to help us create the Playlist class and the methods we actually want. Of course, if this is too weird, you can always stub out the class and then implement the test methods. Personally, I like to implement some of the test methods before going any further, and we’ll use Mockito to stub out a Song implementation.

public class PlaylistTest {
  private Playlist playlist;
  private String validName;
  private Song song1;
  private Song song2;

  @Before
  public void beforeEach() {
    validName = "Pool party songs";
    playlist = new Playlist();
    song1 = mock(Song.class);
    song2 = mock(Song.class);
  }

  @Test(expected = IllegalArgumentException.class)
  public void shouldNotAllowANullName() {
    playlist.setName(null);
  }

  @Test(expected = IllegalArgumentException.class)
  public void shouldNotAllowABlankName() {
    playlist.setName("   ");
  }

  @Test
  public void shouldAlwaysHaveAName() {
    assertThat(playlist.getName(), is("New Playlist"));
  }

  @Test
  public void shouldAllowTheNameToChange() {
    validName = "New valid playlist name";
    playlist.setName(validName);
    assertThat(playlist.getName(), is(validName));
  }

  ...

  @Test
  public void shouldHaveADurationThatIsASummationOfTheDurationsOfEachSong() {
    stub(song1).getDurationInSeconds().toReturn(134);
    stub(song2).getDurationInSeconds().toReturn(205);
    playlist.add(song1,song2);
    assertThat(playlist.getDurationInSeconds(), is(339));
    verify(song1, times(1)).getDurationInSeconds();
    verify(song2, times(1)).getDurationInSeconds();
  }

  @Test
  public void shouldNotAllowASongToAppearMoreThanOnce() {
    stub(song1).equals(song2).toReturn(true);
    stub(song2).equals(song1).toReturn(true);
    assertThat( playlist.add(song1), is(true));
    assertThat( playlist.add(song2), is(false));
  }
}

Now we can complete the Playlist class and round out more tests as we discover new requirements and behaviors. Rinse and repeat. And we’ve done it all with just a little convention and JUnit 4.4, meaning it works in our IDE and in our continuous integration system.

The real change that BDD brings is just thinking differently. So while there are some Java frameworks for BDD (e.g., JDave and JBehave), the real benefit comes from changing your testing behavior, not changing your tools.

I hope this long post has inspired you to rethink how you do testing and to give BDD a try. Let us know what you find!

Filed under: techniques, testing, tools

Java developers should learn Ruby

Okay, it doesn’t have to be Ruby. Pick some other language. Pick Erlang, or even JavaScript. It doesn’t matter really matter, as long as it’s different enough from Java that it actually requires some effort, and that you keep your mind open to new things.

Why bother? Because learning other languages will make you a better Java developer. Seriously.

Learning another language forces you to dive into a different community. You’ll find different ideas and different approaches to many of the same problems. They may not be better ideas and approaches, just different. Other communities often have a fresh perspective on similar problems. And sometimes it will even make you appreciate what we really do have in the Java community (like a huge number of really great libraries).

Learning another language can teach you new idioms. Some you may be able to use in Java, and others you won’t. Ruby blocks, for example, are Ruby’s form of closures and are widely used in most Ruby programs. They’re extremely useful for running predefined code that delegates (perhaps repeatedly) to the block for custom behavior. Here’s a simple example of iterating over an array and doing some custom behavior (printing the element):

animals = ['lion','tiger', 'bear']
animals.each {|animal| puts animal }

Unfortunately, Java doesn’t have closures. Not really. The closest thing in Java 6 is to pass an anonymous inner class in much the same way that listeners are often used in GUI applications. All we need is a predefined interface and a method on a class that accepts the implementation and that performs the iteration (like the “each” method in Ruby). So pretend that java.util.List has an “each” method that takes an implementation of an OnEach:

public interface OnEach<T> {
    void run(T obj);
}
public interface List<T> ... {
    void each( OnEach&lt;T&gt; action );
}

Then our example would look something like this:

List<String> animals = Arrays.asList( new String[]{"lion", "tiger", "bear"} );
animals.each( new OnEach<String>() {
  public void run( String animal ) {
    System.out.println(animal);
  }
});

Kinda gross, huh? But even though it’s not as easily done, it’s a pattern that you can use in your designs to allow custom behaviors without requiring subclasses. There are several closure proposals for Java 7, but none are as easy as in Ruby or JavaScript. By the way, Alex has the best resource for all things Java 7.

Learning another language also forces you to use different tools and processes. One example in Ruby is RSpec, which is a Behavior Driven Development framework focused on specifying and verifying behaviors. BDD is a rich topic that I’ll explore in another post.

Another example is autotest, a great little tool from ZenTest that takes continuous integration to a whole new level. It works on your local machine (rather than a remote continuous integration server), and it simply monitors your development environment’s file system for changes to source files and runs the unit tests corresponding to any changed file(s). If those tests pass, then it runs all of the tests. It’s simple, elegant, and allows you to focus on changing the code, yet still get feedback from your tests. It’s like JUnit or TestNG Eclipse plugins that automatically run your unit tests as you work on the code.

The bottom line is that the Java community doesn’t have the market cornered on good ideas. Java is great and will continue to be, but it does need to evolve. Java first appeared over 13 years ago, and some of us have been developing primarily in Java for most of that time. Go exploring, and I’ll bet you’ll become a better Java developer for it.

Have you changed how you develop Java after learning another language?

Filed under: techniques, tools

Staying informed (via our mailing lists)

One of the easiest ways to stay informed of what’s going on with many open source projects is through their mailing lists and blogs. You’ve obviously found the blog for the JBoss DNA project, but did you know about our mailing lists?

JBoss DNA has several mailing lists, and you can always find them (and how to subscribe) off our main project page or on the JBoss.org mailing lists. Here’s a summary:

  • dna-announce is, well, for announcements. This list won’t have much traffic, as we’ll really just be announcing releases and such.
  • dna-users is the list for anyone who wants to use JBoss DNA but doesn’t want all the nitty-gritty about the inner workings. You can use this list or the forum to
  • dna-dev is the list for those of us developing the project and those that wish to listen in.
  • dna-issues is the automated list of notifications made to JIRA issues.
  • dna-commits is the automated list of SVN commits.

My advice would be to start with dna-users and dna-announce, and then subscribe to the others as you see fit.

One important note: you must subscribe to a list before you can post to it. There’s no getting around that.

Filed under: news, open source, repository, tools

Speedy unit testing with Jackrabbit

We’re using Apache Jackrabbit for one of the JCR implementations in our unit tests. Configuring Jackrabbit isn’t intuitive at first (like many libraries, it’s highly configurable and thus non-trivial to configure), so the trick for us was figuring out how we wanted to use it in our unit tests.

One of the more important qualities of a unit test is that its fast. We do a lot of unit testing, and so we run unit tests very frequently. Change, compile, run tests. Repeat. Repeat again, and again. So the slower the tests take to run, the more they interrupt this process and your train of thought. (More on our testing philosophy and techniques in a future post.)

So we’ve found that the easiest way to speed up Jackrabbit is to use the in-memory persistence manager and the in-memory file system implementations. Here’s a snippet of the XML configuration showing the in-memory file system for the “/repository” branch:

<filesystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem">
  <param name="path" value="${rep.home}/repository"/>
</filesystem>

and here’s a snippet showing the XML configuration for the in-memory persistence manager:

<PersistenceManager class="org.apache.jackrabbit.core.persistence.mem.InMemPersistenceManager">
  <param name="persistent" value="false"/>
</PersistenceManager>

Remember, there are two persistence managers and three file system managers in the normal configuration, so make sure to change all of them.

Then in your test code, create an instance of the TransientRepository class by passing in the location of your configuration file and the location of the directory used for the repository data. We’re using Maven 2, so our configuration file goes in “./src/test/resources/” while we use “./target/testdata/jackrabbittest/repository” for the test data directory.

We’re also using JUnit (version 4.4), so one decision we had to make was whether to set up the repository in a @Before method and tear it down in an @After method. This makes all the tests easy to write, but it also means that the repository is set up and torn down for every test case. That means slower than necessary. And since I like to have a single test class for each class, my test cases often have a mixture of test methods that need a repository and test methods that don’t.

The pattern we’ve settled on is to create an abstract base class that sets up the repository in a “startRepository()” method, and in the @After method automatically tear it down if needed. That means in our unit test case classes that use Jackrabbit, simply extend the base class, and call “startRepository()” in those test methods that need the repository. Test methods that don’t need a repository don’t take the time to set it up. Plus, I personally like that this explicit call makes it more obvious which test needs the repository.

There’s one final twist. The TransientRepository cleans itself up when the last session is closed (not when the instance is garbage collected). Since some tests try saving saving changes in a session, closing the session and opening a new one can make all this data go away. To fix this, our “startRepository()” method creates a “keep alive” session, and our @After tear down method closes the session if it’s there.

Here’s the basics of our abstract base class:

private static Repository repository;private Session keepAliveSession;
    @BeforeClass
    public static void beforeAll() throws Exception {
        // Clean up the test data ...
        FileUtil.delete(JACKRABBIT_DIRECTORY_PATH);

       // Set up the transient repository (this shouldn't do anything yet)...
       repository = new TransientRepository(REPOSITORY_CONFIG_PATH,REPOSITORY_DIRECTORY_PATH);
}

@AfterClass
public static void afterAll() throws Exception {
    try {
        JackrabbitRepository jackrabbit = (JackrabbitRepository)repository;
        jackrabbit.shutdown();
    } finally {
        // Clean up the test data ...
        FileUtil.delete(JACKRABBIT_DATA_PATH);
    }
}

public void startRepository() throws Exception {
    if (keepAliveSession == null) {
        keepAliveSession = repository.login();
    }
}

@After
public void shutdownRepository() throws Exception {
    if (keepAliveSession != null) {
        try {
            keepAliveSession.logout();
        } finally {
            keepAliveSession = null;
        }
    }
}

So setting up unit tests is a piece of cake, and they run very quickly. Now we’re getting somewhere.

Filed under: techniques, testing, tools

Using JIRA and Eclipse

The JBoss DNA project is using JIRA for its issue and task management system. I’ve not used JIRA before working on JBoss DNA, but I definitely like what I’ve seen so far. And, like many other Java developers, I’m using Eclipse as my development environment. In fact, I’ve used it for years and have even developed quite a few plug-ins during my earlier days at MetaMatrix and Revelytix. Needless to say that Eclipse works for me.

So it was only recently that I’ve had the opportunity to really try out the Mylyn task-oriented tools that are included in the 3.3 (Europa) release of Eclipse. After just a few days, I have to admit that I’m impressed.

If you’re already working with some task management system, then right off the bat Mylyn does the obvious: it allows you to view, edit and create new JIRA, Trac, or Bugzilla tasks directly from within Eclipse. The Mylyn forms are all customized to your particular task repository, making them very usable. You can also create lists of tasks (e.g., “My open tasks” or “All open issues”) that are kept in sync with the repository. Sure there are some things that Mylyn doesn’t do that the web-based JIRA interface does much better. But some things are just as easily done in Eclipse – like reviewing an issue, adding a comment, or even resolving an issue.

But the real gem of Mylyn is that you can focus your environment on the task at hand. Just activate the task you want to work on, and Mylyn tracks what source files you read, change, and create. Mylyn uses this information (what it calls the task’s “context”) to do useful things that make your life much easier.

First of all, Mylyn adds a mode to the “Package Explorer” view that shows only those resources that are part of the current task’s context. As you add or edit or create files, they are automatically added to this context. When you switch to a different task, Mylyn switches the view to show that task’s context. I find myself switching tasks frequently, so this feature has been invaluable.

Second, Mylyn integrates with your team plugin to automatically track the changes you’ve made as a change set. The name of the change set is based upon the task name, so it’s easy to keep track of uncommitted changes. Also, when you commit the change set, the comment is prepopulated with the task information so that you’re changes in the SCM system can be linked back to the JIRA, Trac or Bugzilla task.

In short, Mylyn make me feel a little more productive, and that I have a better handle on the things I have to get done. Gotta like that.

Filed under: tools

ModeShape is

a lightweight, fast, pluggable, open-source JCR repository that federates and unifies content from multiple systems, including files systems, databases, data grids, other repositories, etc.

Use the JCR API to access the information you already have, or use it like a conventional JCR system (just with more ways to persist your content).

ModeShape used to be 'JBoss DNA'. It's the same project, same community, same license, and same software.

ModeShape

Topics

Follow

Get every new post delivered to your Inbox.