Entries Tagged 'general' ↓

Frame2 and MacOS X

Currently, Frame2 does not work on Macs. This, of course, is due to the fact that there is no (easily) available Java 6 implementation for MacOS. I’ve been trying to decide if this is an issue or not.

Reasons why it might be an issue:

  • I use a Mac for most of development, and I hate having to drop into an emulator to work on Frame2
  • I really would like Frame2 to run on the Mac, if just for completeness.

Reasons why it probably doesn’t matter:

  • Who really runs Java webapps on Macs? Tomcat on Windows or Linux is OK, but it just feels dirty to me on the Mac.

Hopefully, there will be a version of Java 6 available for the Mac soon. At that point, I’ll probably make the necessary updates to make everything work. Until then, if you’re writing a web app and using a Mac - go with Rails.

Frame2 Gets a Point Release

Frame2 1.3.1 is now available. The full source package is not updated yet, but it should be in the next day or so. This is a pretty minor release - only two changes, but I think they’re important changes.

  1. Enums are now supported in Events. This relies on the Enum.valueOf() behavior, so the values passed in to the event must be legal values that enum values can be built from. This means that things like case are important.
  2. Input views can now be events. I don’t know why this feature was missing. Frame2 already supported using an event for a cancel view (although the unit test didn’t actually test for that). What does it mean to be able to specify events in addition to forwards for input and cancel views? There may be cases where some data needs to be loaded or verified prior to displaying a JSP page. Sometimes this information can be lost when simply redirecting back to a JSP page. By specifying an event, the developer can be sure that the required data has been loaded before the JSP has been displayed.

The Eclipse plugins and sample web applications have been updated with the latest Frame2 jars. Follow the download links in the sidebar, or go to http://sourceforge.net/projects/frame2 if you don’t see the sidebar.

Using Pipes to Squash a Bug

There’s been a bug in the Frame2 Eclipse plugin from day 1 that I believe I have finally squashed. The reading and writing of the frame2-config file happened outside of the Eclipse API, and when the file was updated using a wizard the resource got out of sync with the workspace. It hasn’t really been a big issue, but it’s annoying to always be asked by Eclipse if you’d like to reload the file since it has changed.

My original stab at fixing the problem was to change the file as it’s always been changed, but call refreshLocal() on the Eclipse IFile representation. The call never threw an exception, but it also never seemed to do anything. I finally refactored the model reading and writing code to use Eclipse APIs and platform objects. This worked fine until I got to the point where I needed to write the modified configuration to file. The existing API required an OutputStream, while the Eclipse API wanted an InputStream.

Luckily, Google turned up some suggestions, most notably using piped streams. My first attempt looked like this:

PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
config.write(out);
modelFile.setContents(in, true, true, monitor);

Config is the Frame2 model object that knows how to write itself to an OutputStream, and modelFile is the IFile object representing the config file in Eclipse. Anybody who’s ever used piped streams in Java should be able to tell what happened when I ran the code - it hung. It always pays to read the JavaDoc in addition to copying somebody’s snippet of code from the web. What the JavaDoc says is this: “Attempting to use both objects from a single thread is not recommended as it may deadlock the thread.” In this case, I think may is a bit soft. It deadlocked every single time I ran it.

Based on another online snippet, I modified the code to this:

PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(in);
new Thread(new Runnable() {
  public void run() {
    try {
      config.write(out);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}).start();
modelFile.setContents(in, true, true, monitor);

This is the variant that I ran across most often online. It uses two threads to avoid deadlocking, but it still has a fatal flaw. The setContents() method always throws an IOException with this code. The IOException’s message is always “Pipe Broken”. I found a *lot* of entries online from people asking how best to ignore this exception. There were lots of helpful explanations as to the cause of the error, but I didn’t see a single solution. Luckily, the answer was easy to find in this case.

The “Pipe Broken” message is happening because the the thread doing the writing to the OutputStream has terminated and nothing more is being added to it. The solution is to simply close the OutputStream after writing the configuration to it. The OutputStream is correctly marked as being finished and the exception is not thrown. An examination of the read() method in PipedInputStream shows why the OutputStream must be closed:

if (closedByWriter) {
  /* closed by writer, return EOF */
  return -1;
}if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
  throw new IOException("Pipe broken");
}

If the writing side of the pipe simply exits, writeSide.isAlive() returns false and the exception is thrown. If the OutputStream is closed, however, the reading side of the pipe sees it as EOF and terminates gracefully.

To sum up, the correct example for using piped streams in Java should look like this:

PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
new Thread(new Runnable() {
  public void run() {
    try {
      doSomethingWithOut(out);
      out.close(); // Critical!
    } catch (IOException e) {
      e.printStackTrace(); // Do more than just this, OK?
    }
  }
}).start();
doSomethingWithIn(in);

Build Web Services with the Plugin

The Eclipse plugin has just been updated, and a new plugin has been added to the mix. The new plugin allows users to create Frame2 projects with web services support by adding all of the required libraries and initial configuration. Also in the new plugin are two wizards: one for creating new Responders and one for creating Schema mappings. The Getting Started guide has also been expanded to explain how to add web services support to the example application.

Again, the Update Manager site is the preferred method for downloading the plugins, since it will gracefully handle version and dependency conflicts.

Update Site for Eclipse:
http://frame2.megatome.com/eclipse

Sourceforge Downloads:
Main Eclipse Plugin
Web Services Eclipse Plugin (requires at least version 1.3.3 of the regular plugin)

The Plugin, It Is Done (For Now)

The Eclipse plugin for Frame2 is done, and has been released. Grab the file over at Sourceforge, or point your Eclipse Update Manager to http://frame2.megatome.com/eclipse. Using the Update Manager is the preferred method for installing the plugin.

Sourceforge Download:
Eclipse Plugin

Update Site for Eclipse:
http://frame2.megatome.com/eclipse

Eclipse Plugin Nearly Ready

As the title says, the Eclipse plugin for Frame2 is almost done. Of course, “done” is a relative term. In this case, it means that the plugin has been updated to work with the latest version of the framework, including the updated DTD. Unfortunately, it also means that it still has the same limitations that previous versions have had. Specifically, the plugin still does not support creating a Frame2 project with web services support. This can be added by hand and the Frame2 plugin won’t stomp on it, but neither are there any nice wizards for the web services tasks. This limitation is the next item on my list - I’m pretty sure that I can create an optional plugin that can be downloaded that will add the web services functionality for anyone that wants it. This will also help keep the download size of the “core” plugin as small as possible.

One other feature that the plugin is missing is a contextual editor for the Frame2 configuration file. It would nice to be able to get contextual help and hints when editing the config by hand, but I don’t think I have the time in the forseeable future to research how this works in Eclipse.

The plugin will be available for download from Sourceforge and I will be creating an update site here at frame2.megatome.com that will be the preferred way of getting the plugin.

Version 1.3 is Released

Version 1.3 of Frame2 is officially available. The framework can be downloaded here, and the sample applications are available here.

Work on the Eclipse plugin continues, with a (hopeful) release date in the next week or two.

Documentation is Always the Hardest Part

I’ve pretty much wrapped up the coding for the next version of Frame2, and decided to give the documentation a once-over. All in all, it’s not too bad, but it’s not great either. There’s some real improvements that can be made, but I don’t see it happening any time soon.

Don’t get me wrong - I don’t mind writing doc. One of the most annoying things is to download some open source project and not have any idea how to use it. The issue I have with writing doc is that the feedback loop is entirely different than for code. When writing code with automated tests, there’s immediate feedback if you’ve done the right thing or not. With doc, I have to wait for someone to actually read the doc and give me feedback. This is frustrating because: 1) I don’t know if anybody even uses Frame2, 2) of the people that do use it, I don’t know if they read the doc, and 3) if the doc sucks, does anybody care enough to tell me?

So, for now I’ve corrected obvious errors in the doc, but I haven’t added anything. I’ve started a list of things to cover, but I don’t know when I’ll get to them. Third party dependencies need to be explained better, and web services interaction needs a LOT of coverage.

I feel that the getting started guides and the example applications are sufficient to get somebody up and running with a basic Frame2 application. If I’m wrong, hopefully somebody will let me know!

Approaching the Finish Line

Frame2 is almost ready to be released as a new version. I may still make some changes, but it’s definitely in Release Candidate stage now. There are only a few things that I may add before testing the heck out of it:

  • Upgrade unit tests to JUnit 4. There are a lot of tests, especially the ones that mock a servlet container, that do a lot of repetitive work in setUp() . JUnit 4 has finally brought the ability to annotate methods to be run before and after all tests in the class with @BeforeClass and @AfterClass, respectively. Individual test setup activities can still be performed by annotating a method with @Before.
  • Fix outstanding bugs. There’s only one right now, and it’s SOAP specific, so I may or may not fix it. It may take me longer to figure out how to reproduce the problem with unit tests than it’s worth.
  • Add outstanding feature requests. Again, there’s only one, but it’s (in my opinion) a biggie - the ability to add parameters to the response when handling an event.
  • Doc updates. The web services doc needs to be written, and I’m sure all of the other doc needs a good examination.

I’ll be testing the latest build with a web application that I’ve been working on for years that I’ve come to think of as an unofficial reference implementation of Frame2. I haven’t decided yet if the web app should become part of the project on Sourceforge or not. We’ll see.

Once the testing is done and I’ve released a new version of Frame2, I plan on working on the Eclipse plugin. The poor plugin has pretty much been ignored for several years now, and it needs some attention.

A Consistent API is a Very Good Thing

I’ve been mucking around in the codebase, cleaning up pieces of the API that annoy me. Some bright person thought that it was a good idea to have a method that returns an Iterator to access a collection. I’ve been cleaning up all of these methods, changing them so that they return an actual collection - occasionally made unmodifiable through the Collections class.

Naturally, this has led to unit test failures. Almost all of the failures have been easy to fix, but once in a while one pops up that makes me scratch my head. Here’s an example:

public void testGetIfEmpty() {
assertTrue(this.errors.isEmpty());
assertNull(this.errors.get(FOO));
assertEquals(0, this.errors.get().length);
assertEquals(0, this.errors.get(FOO).length);
}

In this instance, errors is a class that aggregates individual Error objects. The get(String) method returns an array of Error objects that have the specified key, while get() retrieves all Errors. Pretty simple, right? After my changes, the test fails on the assertNull() statement, which isn’t surprising.

The failing statement read assertNull(this.errors.iterator(FOO)) before I removed the iterator() method, which tells us a bit about how the API was originally coded. The iterator(String) returned null if there were no matching entries. However, as the unit test clearly shows, get(String) returns an empty array when it doesn’t find any matching Errors. Quite the difference, and potentially confusing - the developer has to remember which method may return null.

The API has now been changed to return an empty collection instead of null when no matching errors are found. Now, a user of the API simply has to call the method and loop over the result (zero times if it’s empty) without having to make null checks.

Whoever wrote this unit test obviously knew that one method returned null while the other returned an empty array for the same input, since the test passed. I only wish that person would have looked at those lines and noticed the inconsistency, instead of leaving it for me to find.