Frameworks and Build Scripts and POMs, Oh My!

Posted 887 days ago

It's been a while since I've started a new J2EE project from scratch, and a lot has changed since the last time I did. I've been working in the J2EE arena for quite a few years now, but with the exception of jETIA, which I started in 2002, I've only been involved in existing projects. jETIA's build system was Ant, revision control was Subversion, and project management and dependencies were managed by hand.

I learned about Maven about a year ago when I responsibilities at my previous job suddenly included maintenance and development of a large, complicated ant based build system. I had hoped that Maven would be the golden solution to my dependency maintenance nightmares, and complicated Ant scripts integrating our source control mechanisms - however I quickly learned (the hard way) that Maven was not flexible enough to adapt to your project structure; I'd have to make my project structure meet their idea of a good layout. Not that I objected to their layout, but the discombobulated state of the project I was working on took years to screw up so badly; fixing it would only further confuse the developers who held deep understanding of how the project ran.

Which brings us today, with my new Maven book (Maven : A Developer's Notebook) and the need to start a project from scratch. Sadly, the book I bought not 4 weeks ago is officially out of date, as Maven 2 is now the standard release, and my book only briefly mentions that while the concepts are the same in version 2, that it's a complete rewrite of the system. Many commands are the same, but the one thing I wanted to do - create a new project - has changed :-\.

Additionally, I discovered today that my MVC framework of choice, Struts, has drastically changed as well! Struts is now broken into two core projects: Structs Action framework - the "original" struts, so to speak, and Shale, a Java Server Faces based MVC framework being billed as "what Struts would have been if we'd known then what we know now".

How fast things change. I feel like, from a technology standpoint, I'm starting all over again... While initially discouraging for me, this should be exciting for you, because this means that I'll be posting many many how tos on getting started with these exciting new versions of technologies designed to make you life in J2EE easier!

So my question to you, then, is aside from Maven for project management, Struts and/or Shale for a strong MVC framework, and Spring for a solid IoC driven dependency injection mechanism - what should I be reading up on during my "technology review" stages, and what are your opinions on them?

Creating New Workspaces in WSAD 5.1

Posted 889 days ago

When you launch WSAD for the first time, it prompts you to create a workspace. The dialog has a checkbox that asks if you want to be prompted each time. If you uncheck it, so as to not be prompted each time, it will never ask you again. This is great, until you actually need to create a new workspace! There's no File->New Workspace or anything like it, and the solution is quite elusive.

Elusive, yet simple.

Open up your handy dandy command line window, CD into your WSAD installation folder, and do the following:

cd C:\Program Files\IBM\WebSphere Studio\Application Developer\v5.1.1
wsappdev -setworkspace

This will launch WSAD and cause it to prompt you to create a new workspace, again with that tricky little checkbox.

I created a ShortCut to run this that I added to my WebSphere Studio folder in the start menu. You can download the shortcut here. You may need to repoint the target if you're using a different version (than 5.1.1) or have installed it to a non-standard location.

Prevayler Persistence

Posted 908 days ago

A colleague of mine at Zedak recently sent out an email directing our attention to Prevayler - a rediculously fast persistence layer for Plain Old Java Objects.

Boasting speeds 9000 times faster than Oracle and 3000 times faster than MySQL (when queried via JDBC), and licensed under the LGPL, one might ask why everyone hasn't already switched. The answer is simple, scary, and potentially complex: it stores the whole of your data model in RAM, so it's readily accessible at lightening speed. The concerns are obvious, and the answers simple.

Prevayler persists snapshots of the memory image to disk regularly (you can configure the schedule) to ensure long term persistence, and keeps a persistent log of issued commands in the event of a crash - similar to a journaling file system. The idea is that's its faster to write down what you asked for than to read the information you need; if you already know the answer, why go to the book, right?

The driving motivation behind Prevayler is that RAM is dirt cheap - much more so than physical storage. Of course it's not without its limitations; today's 64 bit processors can only handle 8 gigs of memory, and the vast majority of us are still on 32 bit hardware handling at most 4 gigs. Whereas one can store countless terrabytes of data on other mediums such as hard disks and DVDs - and lets face it, sometimes you just have more than 8 gigabytes of data; although for me and my friends Tom, Dick and Harry Web Developer, 8 gigs is a relatively unrealistic amount of information.

It's limitations and unrealistic applications are pretty well documented by Prevayler's authors though; they're even good enough sports as to post emails from uninterested traditional RDMBSers accusing them of being zealots.

Personally, I think it's a great idea. I saw mention of cross-language support on their site; perhaps I'll look into it for Blosxonomy caching. It'd be great if I could keep the Blosxom like file-system entries and use an in-memory DB like cache - my performance would sky rocket! It would also be a great segway into developing a full-on SQL based Blosxonomy entry locator.

Best of 2003

Posted 927 days ago

Thanks to the Web Archive, I was able to retrieve a bunch of old posts that I had lost a couple years ago when the server I hosted on at the time crashed. I restored the posts that had interesting content with their original publish dates, and thought I'd post a "Best of '03" to those stories. So here they are, in chronological order:

IoC Design Pattern

Posted 1027 days ago

I had read something a while ago about a design pattern called Inversion of Control (IoC), which came back to me this morning as I was working. I looked it up on Google and found a decent overview of the pattern, and wanted to share it: IoC Article

The basic jist of IoC is that if your class needs an object that is outside of its primary responsibilities, it should not instantiate it itself, but rather should accept that object either in a constructor or with a setter method. This writeup uses a database object manager for it's example, however a more common example is logging. I'd be willing to bet that at the top of most Java Code with logging, you'd see a line that looks like this:

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

And then the rest of the methods in that class use the LOG instance. IoC says that it is NOT your class' responsibility to instantiate a logger, and therefor should be passed one instead.

Some benefits to doing this:

  1. It ties in well with Test-First programming, as it helps to minimize the amount of setup needed in your testcases. In the case of logging, it means that you can pass in a "dummy" Log implementation rather than configuring a Log4J runtime.
  2. It allows us to log based on "use-cases" rather than at a functional level. Take for instance the core/Reports framework. Every class in core/Reports right now has it's own logger, but in general, I only use 2 or 3 of the classes in the package (t he classes which expose the high-level functionality of the framework). If I implemented IoC with respect to Logging in core/Reports, I'd probably only have 2 distinct Log instances in the entire package, making it a) easy to configure logging for core/re ports and b) easy to identify flow-of-control in the logging output.
  3. It minimizes the amount of work we need to do when we all of a sudden decide we want to, say, drop in commons-logging rather than use Log4J directly :).

IoC happens to be very easy to re-factor in, here's an example of how that would be done without breaking compatibility:

Existing Class:

public Class Foo { private final static Logger LOG = Logger.getLogger( Foo.class ); public Foo() { // Initialize the class here. } ... }

Refactored class:

public Class Foo {
    private Logger LOG = null;

    public Foo() {
	// Default constructor creates a logger so 
	// as to not break any existing code.
        this( Logger.getLogger( Foo.class ) );    
    }

    /**
     * New usages of Foo should use this class 
     * instead, passing in a Logger instance.
     */
    public Foo( Logger log ) {        
        // Initialize the class here.
        this.LOG = log;
    }

    public void setLogger( Logger log ) {
        this.LOG = log;
    }
}

You should really take the time at this point to find usages of the "old" constructor, update them to usages of the new constructor, and remove the old constructor. This may not be very easy to accomplish, especially when you're refactoring libraries.. . The refactoring shown above guarantees that no current usages of your code will break. New code, however, should implement IoC and NOT give users the option of using a Default logger, as follows:

New Class:

public Class NewFoo {
    private Logger LOG = null;

    // Explicitly remove the ability of constructing 
    // this class w/o a logger. This prevents outside 
    // instantiations, and subclasses of this class 
    // from doing this.
    private NewFoo() {
    }

    public NewFoo( Logger log ) {
        this.LOG = log;
    }
}
Tomcat Configuration Trickery

Posted 1108 days ago

Say you're working on a handful of different web application projects using one installation of Tomcat; it's very likely that you need different resources, settings, and runtime parameters per project - and as a consequence of such it's very likely that your tomcat configuration is a mess! Well no more, I say! What if you could have a distinct set of configurations for each project you're working on?

Fortunately Tomcat makes this extremely easy. There are two primary locations that Tomcat works with, identified by and . is the location you installed Tomcat into -- in my setup, that's /opt/tomcat. is where it will look for configuration files and other "dynamic portions" (according to tomcat's documentation) of the server.

What we're going to do is create one per project (or one for just the projects you think require their own, anyway), and then configure tomcat to use the new TOMCAT_BASE.

The first thing to do is create a local tomcat directory structure in your project directory -- my project looks something like this:

  MyProject/
    docs/
    etc/
    src/
      java/
      test/
    tomcat/
      conf/
      logs/
      tmp/
      webapps/
      work/
MyProject/tomcat is going to be your .

You need to copy two files from /conf to /conf:

  • web.xml - Contains the default settings for all web apps deployed into .
  • server.xml - Contains the server configuration. For my web projects, i usually use server-minimal.xml file instead of the default server.xml, as it only loads the minimum amount of services needed to run a web application (which is usually sufficient for my hobby projects).

Once you have that done, your is ready for use. If you're launching Tomcat from the command line, you'll want to set the environment variable CATALINA_BASE to point to your TOMCAT_BASE directory (MyProject/tomcat). If you're launching Tomcat from XCode, you'll want to open your custom executable's properties, and add the following argument:

  -Dcatalina.base=../tomcat
Note: XCode appends arguments in order, so you'll want to put it somewhere before the argument that specifies the Bootstrap class to launch.

All that's left to do is start deploying your project's webapp to /webapps rather than /webapps, and you're good to go. Your project's instance of Tomcat will log to MyProject/tomcat/logs, use MyProject/tomcat/work for its working directory, and MyProject/tomcat/tmp for tmp space.

Why would you want to do this, you ask? Well first and foremost, cuz it's cool. Second, perhaps you have projects that really should be tested and run in isolation. Third, maybe you don't have the luxury of having multiple machines that you can run webservers on, and you need to test a multi-server setup - or test communications between applications on separate app-servers. For me, it's a configuration-location thing - it lets you keep project-specific server configurations in your project, where they belong.

Debugging Servlets in XCode

Posted 1108 days ago

So I've been struggling for a while with finding a way to debug web applications in XCode. The answer wasn't immediately obvious. I'm sure it would have been if I happened to have Apple's WebObjects, but I don't; just XCode. Well today I figured out how to do it -- you run Tomcat directly from within XCode!

Now before we get started, I want to point out that I realize there are pros and cons to doing this -- I'm going to save those for the end.

My setup

Here's the software I have installed to work with:

  • OS X 10.4 Tiger
  • XCode 2
  • Java 1.5.0 (also "Tiger")
  • Tomcat 5.5.9 (installed in /opt/tomcat)
I'm 99% certain this procedure will work using OS X 10.3, XCode 1.5, Java 1.4.2, and Tomcat 5.0.x as well, but I haven't tried it. If you try it, and it works, please let me know -- if your mileage varies and you want me to post instructions for that as well, please email me :).

Step 1: Creating a new project

If you already have a project you want to try this with - just skip to step 2.

If you don't already have an XCode project, now's the time to make it. I used the "Java: Ant Based Application Jar" project template in XCode. This creates a new project with an ant build script, and src and lib directories. Making yourself a nifty servlet that looks something like this:

import java.io.*;

import javax.servlet.http.*;
import javax.servlet.*;

public class javaplay extends HttpServlet {
  public void doGet ( HttpServletRequest req, 
                      HttpServletResponse res )
    throws ServletException, IOException
  {
    PrintWriter out = res.getWriter();
	
    out.println("Hello, world!");
    out.close();
  }
}

is a great beginning. You'll also want to make yourself a WEB-INF/web.xml file, like so:

<web-app>
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>javaplay</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

And then modify your build script a little bit a make the WAR. Mine is embarrasing, so I'm not going to show it to you. There's two steps though:

  1. Make a new target that creates a WAR and depends on "compile"
  2. Change the default target of your build script to call your new target.

Ok great, one last final step, grab your servlet-api and jsp-api jars and copy them into your projects "lib" directory. The build script needs these in lib to resolve against at compile time. Now go ahead and build your project to make sure it goes smoothly and generates the WAR as expected.

Had a problem, did you? That's okay... I'll wait till your done.

( ... jeopardy theme ... )

Step 2: Tying in Tomcat

This part's also very easy -- you're going to create a new executable target that starts Tomcat. My setup has Tomcat 5.5.9 installed into /opt/tomcat.

Right-click (ctrl-click) "Executables" under Groups & Files and select "New Custom Executable". Name it something meaningful, such as "Tomcat", and set the executable path to: /usr/bin/java. When you press "Finish" you'll get the "Executable Tomcat Info" dialog up. Go to the Arguments tab, and add the following set of arguments, in order:

  -classpath /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/commons-logging-api.jar
  -Dcatalina.home=/opt/tomcat
  -Xmx128m
  -Xms64m
  -Xincgc
  -Djava.awt.headless=true
  org.apache.catalina.startup.Bootstrap -debug start

Set your new target to be the active target, and run your project. You'll notice that your console output is Jakarta Tomcat starting up! Not too shabby, eh?

Step 3: There is no step 3

That's it. Just deploy your webapp to tomcat, start it up under XCode, and you're good to go. Give it a try, set a break point in your servlet code and hit the page through a web browser.

Conclusion

One thing I did to make my life easier in this setup is to make my default ant target automatically deploy the WAR file to my tomcat directory. That way when I hit "Build & Debug", it builds, deploys, and launches tomcat in my debugger.

Well I hope you found this helpful. I know I keep having to go back to using IntelliJ IDEA for my servlet based projects up until now I haven't been able to figure this out. I'm still looking into getting the XCode debugger to hook up to a remote Tomcat session, and I'll be posting info about that soon (I hope). If anyone out there has info on doing that, please get in touch with me.

Tiger on Tiger

Posted 1117 days ago

Well as you all know the Tiger is out. You can download Java 1.5 here and the Java 1.5 developer documentation here. The Java 1.5 installer does not make itself your default java though, so you should do two things:

  1. In /Applications/Utilities/Java/JS2E 5.0, run the Java Preferences, and set your default Java version to be J2SE 5.0.
  2. Open a terminal window and execute the following:
    cd /System/Library/Frameworks/JavaVM.framework/
    sudo rm Versions/CurrentJDK
    sudo ln -sf Versions/1.5 Versions/CurrentJDK
    

Now everyone's defaulting to Java 5.0 - huzzah!

Funny try/catch/finally

Posted 1286 days ago

So I ran across an article not too long ago, can't remember where, it was one of those things that just gets passed around, about the importance of try/catch/finally... and how the finally block is executed no matter how the controlling block is terminated. So I put together a toy example to test something out, and thought it was a little cool. Consider the following java method:


public boolean trytest( final int x ) {
switch( x ) {
case 0:
try { return true; }
finally { break; }
default:
return true;
}

return false;
}


Now if you were to call this method and pass it 0, what would happen is the try block would return true. Since the controlling block exited, the finally block is hit and the break statement executes, dropping control out of the switch statement so that the return false line statement is executed. The method returns false.


So there ya go. Be careful what you do in your finally's; you can easily override the behavios of your try if you're not paying attention.


Anonymous Abstract Factory pattern revisited

Posted 1310 days ago

A while ago I had posted an article about the Anonymous Abstract Factory Pattern - an adaptation of the Abstract Factory Pattern that takes advantage of anonymous class loading in Java. Well I've finally got around to pulling the framework for that pattern out of the jETIA source tree, so I CPL'd it and am making it available here: AnonymousAbstractFactory-1.0.0.tar.bz2.

Please let me know if you're interested in working on the project. I'd love to get a couple developers working on it, adding features such as support for factory constructors, configurable factories, and a few other features. If I get a couple people who are interested, I'll set up an SVN repository for the project and we'll start making plans. Sorry for the minimal documentation, I'll work on that as well.

Abstract Anonymous Factory Pattern

Posted 1508 days ago

A factory is an object that creates instances or related types of objects. An abstract factory provides the interface that factory objects implement, as well as a method return a concrete factory implementation. For example, jETIA contains an Abstract DAO Factory that defines abstract methods to get different types of data access objects, and a static method to obtain a concrete instance of a DAO Factory.

In the abstract factory pattern as described in "Design Patterns", the Abstract Factory's static method to obtain a concrete factory instance would take a parameter identifying the type of concrete factory to return, and instantiate the appropriate sub-class of itself to satisfy the request. This hard coded knowledge of the available types of concrete factories makes it difficult to supply new types of factories later.

The Abstract Anonymous Factory is an adaptation of the abstract factory pattern that takes advantage of the anonymous class loading abilities of the Java runtime environment. Instead of explicitly telling the Abstract Factory about each type of Factory, the Abstract Anonymous Factory reads information about the types of concrete factories from a configuration file. The anonymous abstract factory then asks the runtime environment to find the class by name, and instantiate it.

Using this method, to add support for a new type of factory, the developer must implement the objects that are created by the concrete factory, create a new concrete subclass of the abstract anonymous factory, and modify a configuration file that is read dynamically at runtime. There is no need to recompile any of the code to deploy a new factory.

To help illustrate this concept, consider the sequence diagram shown the figure below. It depicts the sequence of events that occur when an application needs to use a Widget. In order to support a wide variety of widgets, an abstract anonymous widget factory is used. As you can see, the client obtains a concrete widget factory from the abstract anonymous widget factory. The configuration file is read to determine what types of widget factories are available, and in this instance, since no particular type is specified, the name of the default widget factory to use.


This is why the factory is referred to as "anonymous." Neither the client application nor the abstract factory has any advanced knowledge of the type of factory to instantiate. Since the concrete widget factory implements a known interface, it can be instantiated as a generic Object instance, and then cast to the appropriate interface type.

Java Performance under OS X

Posted 1557 days ago

I recently had a request for my opinion about Java's performance under OS X. Unfortunately I don't have any valid method of comparison other than my own personal experience, and even that doesn't provide too much.

Some background first: I've been using Macs for about 2 years now, and I must say they are the best systems I've ever used. From an aesthetic point of view, the hardware is just plain sexy; from a practical standpoint, it's fast and reliable. (I also have many fast reliable x86 boxes... the point of this is not to start a flame war!). The operating system was the main selling point for me; in the x86 world I am a *NIX user (linux on some, darwin on others, and i'm thinking about getting my hands dirty with Hurd) -- but I keep my x86 world to server functions rather than using them as desktops now. This is because after discovering Apple's Aqua interface on OS X, and knowing that BSD and all my favorite and familiar tools are just under the covers, I could never go back.


So as an Enterprise Java developer -- this left me with the question: sure it looks great, is easy to use, and is a BSD, but what about Java?

"What about Java?" is a loaded question. There's many aspects to Java... most end users would particularly be interested in GUI performance, as Java has the notorious reputation for having bad interface performance. As developers, GUI performance is also important, not only in our development, but also in the tools we use... most Java IDE's are themselves written in Java, and if they don't work well, we don't work well. We also need to be concerned with the performance of our tools, such as the java compiler, the Ant build system, and anything else you happen to use. As Enterprise Developers we further have the headache of needing to run application servers, I myself use JBoss, many others perhaps use Apple's WebObjects, or maybe even just the Sun Reference Implementation.

Like I said above, I don't have any formal measurement for performance, just my own experience... but on all of the above noted points, I am thrilled with Java's performance on OS X.

Apple's has done an enormous amount of performance tuning in the Swing and JFC libararies in their JRE implementation; so much so, in fact, that I can rarely notice a difference between running Swing applications and Cocoa (apple's native UI) applications.

The only real "tool" I use regularaly is Ant. For the sake of this article, I took my current project tree and compiled it on my Mac, and also on my IBM workstation (specs at the bottom of this post...). A clean build of my project tree on the Mac took a solid 1.2 seconds longer than on my IBM (and when you look at the specs, you'll see why); and with an average build time of 27 seconds, a 1.2 second discrepancy is perfectly acceptable.

How about my application server... I mentioned that I use JBoss. For those of you who have never started JBoss, it has the nice little feature of telling you how long it took to start the JBoss Microkernel after the server initialization is complete. Now here, I definitely have no valid comparison to my x86 server (again, specs below...). I can start JBoss on my Mac in just under 20 seconds. My colleagues at IBM who are helping to test my system tell me they're server starts JBoss in about 25, unfortunately the only specs I have on their system is that it's a mid-range P4 desktop running Windows XP. I don't know what they have to memory, processor speed, bus speed, or if they have a hyperthreading processor.

So -- what's all this tell you about performance of Java on OS X? -- unfortunately not much. Just my personal experience with it, and I'm thrilled. I've had no issues with it whatsoever, performance or functional.

A couple points worth mentioning:

  1. XCode, Apple's development suite, has fantastic support for developing Java projects, and it's entirely free... it comes with OS X infact. I use it frequently. (My primary IDE is IntelliJ's IDEA).
  2. The JRE on OS X is put out by Apple, not Sun. From what I understand the Sun people work very closely with Apple to ensure the JRE is 100% compatible with the actual Sun implementation; Apple prefers to put out their own JRE so that they can provide performance tuning specifically for their hardware and operating system.

System specs:

  1. My mac: A PowerBook G4 17" 1.0 Ghz w/ 768 Meg RAM
  2. IBM Desktop: Intellistation X Pro Pentium 4 2.8 Ghz w/ 2G RAM and Hyperthreading enabled
  3. IBM Server: Intellistation Z Pro: Dual Xeon 2.8 Ghz w/ 2.5G RAM and Hyperthreading enabled

As you can see, my x86 equipment far surpasses my laptop as far as performance goes... so my psuedo-runtime numbers on each platform should be compared with a grain of salt.

Double Buffer issue in JTabbedPane?

Posted 1562 days ago

So I tested my client tools for the first time on a Windows XP platform the other day. The system was a clean install running JDK 1.4.2_03 -- and to my horror, my JTabbedPane looked horrendous; here's how it went down... I have a class that extends JFrame, called MainFrame, and MainFrame's constructor looks something like this:


public class MainFrame
{
public MainFrame()
{
JPanel panel = new JTabbedPane( ... );
...

this.setContentPane( panel );
}
}


Now, on the Mac and Linux platforms, there is absolutely no issue with this. Everything works great. However, on the windows platform, everytime the panel had to be redrawn, the tabs would be shifted, skewed, missing, duplicated, and other strange sorts of things. It was very strange indeed.

Simple fix:


public class MainFrame
{
public MainFrame()
{
JPanel tabPanel = new JTabbedPane( ... );
...

JPanel panel = new JPanel( new BorderLayout(), true );
panel.add( tabPanel );
this.setContentPane( panel );
}
}


So it seems that the JDK1.4.2_03 on Windows isn't double buffering their JTabbedPane. Hopefully this will be resolved soon. Do any of you know where I could submit a bug report to sun? :).

JDBC Metadata and Column Types

Posted 1622 days ago

Today I've been testing my data caching module... it's pretty straight foward, the relevant part for today's ramblings is that it takes an SQL query, executes that query on some external database, and then creates a table in my database to mirror the resultset.

Making the database connection "some external database" was simple enough (I talk about that a little in my entry on class loaders...), and executing the query is easy. Once I've obtained the ResultSet, I simply get the ResultSetMetaData and iterate over the columns. The mistake I made was that I'd been calling metadata.getColumnTypeName( idx ) and getting the vendor-specific type name for that column. The fix was simple yet dissapointing, and I'm hoping one of you will have a more elegant solution --

The ResultSetMetaData class also provides a method called getColumnType() that takes the index of the column I want the information about. getColumnType, as opposed to getColumnTypeName(), returns the "JDBC Type" of the column, as an int as defined by the java.sql.Types class. The Types class contains fields that represent each of the generic SQL types (called JDBC Types in Java), however, as far as I could tell, there was no way to get string that represented that SQL Type... just the integer value of it's field in Types. What good is that?

So anyway, to get around this little annoyance, I made myself a little helper class that looks something like the following:

public class SQLTypeMap
{
    private final static Map typemap;

    static
    {
        typemap = Collections.synchronizedMap( new HashMap() );

        Field[] fields = Types.class.getFields();
        for ( int i = 0; i < fields.length; i++ )
        {
            String fieldname = fields[i].getName();

            try
            {
                int iValue = fields[i].getInt( null );
                Integer value = new Integer( iValue );

                typemap.put( value, fieldname );
                typemap.put( fieldname, value );
            }
            catch ( IllegalAccessException e )
            {

            }
        }
    }

    public final static String getTypeName( int type ) { ... }
    public final static int getType( String name ) { ... }
}

Java provides amazing support for introspection, so I took advantage of that to make a hash map that contained entries mapping the integer value, to the name of the JDBC Type. That way, to get the name of the SQL type of a column in my result set, I can do the following:

int type = rsmetadata.getColumnType( idx );
String typename = SQLTypeMap( type );

It's quick and easy, but feels to dirty to be the "right way". Anyone have any better ideas, or know something I obviously don't about where to find this information? If this is the best way, why??? It seems a little rediculous.

Loading arbitrary classes from arbitrary places....

Posted 1623 days ago

One of my very favorite things about the JDK is portability... and not just the "compile-once-run-anywhere" portability Java is so famous for, but also the portability across providers. JAAS, JCE, JDBC and JAXP are few among the handful of technologies that have been rolled into the Core SDK as sevice wrappers, for which you need an implementation provider. Specifically today I've been concerned with the JDBC, but todays lesson in class loaders applies across the board.

As part of my current development project, I am writing a simple SQL Query Builder tool. (I know, it's been done, but this is also my M.S. thesis and the work needs to be mine). This query tool needs to be able to connect to any JDBC database host, query meta data, and build SQL Queries based on it. Not too difficult or involved (a minor part of a larger client tool...), but I wanted to be as dynamic as possible in my implementation; which means having the ability to plug new JDBC Driver packages into the system at run-time....

My particular implementation scenario is a little more complicated than I'm making it here; jETIA is a J2EE solution and my Query Tool is a thin client on it, so in particular I need to be able plug in JDBC drivers without having to restart my J2EE server. Still, this doesn't sound too difficult yet, right? Anyone with JDBC experience has done the familiar routine of dynamically loading a JDBC driver:

Class.forName( "org.postgresql.Driver" ).newInstance();
con = DriverManager.getConnection( 
           "jdbc:postgresql://dummy.eskeeter.net/database" );

My problem today, however, was that the class org.postgresql.Driver may or may not be in my system CLASSPATH. Throurgh the miracle of XML configuration files, I happen to know exactly where the JAR that contains org.postgresql.Driver is located, the problem is loading the class out of it. Fortunately this is a whole lot easier than it sounds.

At first, I was concerned. I knew what I needed was a ClassLoader that would extract the Class from my Jar, but for the life of me I couldn't find anything resembling a "JARClassLoader" in the SDK Docs... I did, however, stumble across a URLClassLoader. The URLClassLoader takes as an argument to its constructor an array of java.net.URL objects, which, in my case, reference the JAR file(s) on my local file system that I need to open:

StringBuffer path = 
     new StringBuffer( 
          System.getProperty( "net.eskeeter.querytool.homedir" );
path.append( "lib" );
path.append( File.separatorChar );
path.append( "postresql.jar" );

URL url = new URL( "file://" + path.toString() );
URLClassLoader loader = 
     URLClassLoader.newInstance( new URL[]{ url } );

Class.forName( "org.postgresql.Driver", true, loader );

In this little example block I assume that I have a system property (set w/ -D on the java command line) named net.eskeeter.querytool.homedir that is the path to my applications directory. Off of that directory I have a subdirectory 'lib' that contains all the JAR files for all the JDBC drivers I want to support (and are not in my CLASSPATH). The StringBuffer builds the path to the particular JAR file I want, and then I use that path to instantiate a URL, and in turn a URLClassLoader. I can then use that class loader as an argument to Class.forName() -- the boolean value there indicates wether or not the new instance should be initialized. Class.forName uses the specified ClassLoader to attempt loading the class org.postgresql.Driver. The class loader looks in each of the URL's it knows about for the class, and loads the class object from the appropriate location.

It turned out to be much easier than I thought it would be, and it works great. I still wish there were some way I could just tell the Java VM that it should add "foo.jar" to the CLASSPATH and use the default class loader to open it, but I suppose that could potentially open the system up to all kinds of security risks, version control problems, and other nasty things.... Perhaps maybe in a future release it will be allowable with the use of the SecurityManager to ensure I have authorization to do that? Who knows... for now though, this worked great and wasn't very difficult at all.

Classpaths in Executable JAR Files

Posted 1626 days ago

I just had to suffer through packaging a Java application in a jar file and making it run. This doesn't sound like such a big deal, but it quickly turned into one. I've been working with JAR files for quite a while, but I've been dealing in the J2EE end of things, where you deploy your JAR into a server, not to a client as an application. It wasn't a big stretch to discover that all I had to do was add a Main-Class: tag to my manifest file, but the trouble came when I tried to run it.

Lets say I have a package, net.eskeeter.jartest that has a class in it called JarTest:

public class JarTest {
  public final static void main( String[] args )
    System.out.println( "Hello, Readers!" );
  }
}

JarTest is the entry point to my program, so I create a manifest that looks roughly like so:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.5.3
Created-By: 1.4.1_01-14 ("Apple Computer, Inc.")
Main-Class: net.eskeeter.jartest.JarTest

Name: net/eskeeter/jartest/
Sealed: true
Implementation-Vendor: eskeeter.net

Fantastic -- so I make my jar, named conveniently enough jartest.jar, and try to execute it:

java -jar jartest.jar

Fantastic! That worked great. So lets add the twist that gave me this headache; lets say JarTest.java looks like this:

import org.apache.log4j.*;

public class JarTest {
  private final static Logger logger = Logger.getLogger( JarTest.class );
  public final static void main( String[] args ) {
    logger.info( "Hello, Readers!" );
  }
}

Simple enough, all I've done is make this a toy example on how to use Apache's Log4J utility. For the sake of argument, lets say I have a file called log4j.jar (which I do) that contains the Log4J implementation (which it does...), so I want to execute my toy example, so I jar it up same as before and type the following:

java -cp .:log4j.jar -jar jartest.jar

An imaginary donut for the first reader who can tell me what will go wrong... That's right! Congrats to the young lady in the 2nd row, I get a ClassNotFoundException: org.apache.log4j.Logger! Why!? I included it in my class path... everything looks fine... but it's not.

The reason is that when you execute a jar file, the jar files Manifest must describe any external dependencies the application has; in this case log4j. So I have to update my manifest:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.5.3
Created-By: 1.4.1_01-14 ("Apple Computer, Inc.")
Main-Class: net.eskeeter.jartest.JarTest
Class-Path: log4j.jar

Name: net/eskeeter/jartest/
Sealed: true
Implementation-Vendor: eskeeter.net

Note the crucial addition of the Class-Path: attribute. If I had multiple entries on this line, they would be white-space separated; and the paths are relative to the location of the jar file. So I repackage my jartest and execute it -- note that since my jar file knows about it's external dependencies, there's no reason to be explicit about my classpath:

java -jar jartest.jar

And everything works great!

So it all seems simple and innocent enough, but I don't like the idea of having to be explicit about my external dependencies in such a fixed maner. For instance, when you download Log4J from apache, you get a jar with a name like log4j-1.2.8.jar, because by convention libraries include version numbers. I don't necessarily want to tie myself down to version 1.2.8, so I rename the library and strip it of its versioning information, log4j.jar, this is what I add to my classpath. Now, when a new version comes out, all I do is download it, strip it of it's version information, and replace my old log4j.jar with my new log4j.jar. The downside to this? I'll never know by looking in my lib/ directory which version of log4j I'm currently using.

The other downside? Lets say I want to distribute my JarTest application, to you for instance. You're a Java savvy user, and you already have Log4J installed in a location of your choice... but I don't know where that is and I can't tell my Manifest where that is. So I dictate that there will be a ./lib/ directory relative to the location of my jar (or, perhaps, bundled in my jar), and that directory will contain log4j.jar. My distribution bundle just increased in size by the size of Log4J, and has been complicated by Sun's distribution policy! That's awful! No, you being as savvy as you are, are pefectly able to delete my log4j file, and symlink to your own version of it, but lets say for instance that your less-than-savvy friend, Joe, wanted to try it out... see where I'm going with this?

It's limiting... I don't know how to fix it, but I'd like to see a solution. Perhaps Java needs a package management system similar to Perl... Perl knows what modules it has installed, and all I need to do is tell Perl I'd like to use it. It then knows where to find it, and how to load it. It would be fantastic if I could say "Java, I'd like to use Apache's Log4J... I don't care what version, but it should be greater than, say, 1.2.5", and Java would know where that library was located and go get it! Then I wouldn't have to hard code classpaths into my application's JAR bundle...

Then again, there are those who'd say limits are good -- I might NEED you to use Log4J-1.2.8 (bad example, but you know what I mean...). Still though, I find this to be too much.

Oh well, just a passing thought after hours of fighting with it. Has this been solved already? Any other ideas on how to make it better? Any better conventions for making JAR's less "fixed"? Comments welcome!

Writing Custom JAAS Login Modules

Posted 1635 days ago

This tutorial will show you in detail the steps required to implement a custom JAAS login module for a Java application.

When a client application needs to authenticate the user, the only thing it needs to do is obtain a LoginContext, and execute its login() method, as follows:

package net.eskeeter.jaasexample;

import javax.security.auth.login.LoginException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.callback.CallbackHandler;

public class JAASExample
{
    public static void main( String[] args )
    {
        String securityDomain = "exampleDomain";
	CallbackHandler callbackHandler = 
		new CustomCallbackHandler();

	try
	{
	    LoginContext lc = 
	    new LoginContext( securityDomain, 
			      callbackHandler );
	    lc.login();
	}
	catch ( LoginException e )
	{
	    System.exit( -1 );
	}
    }
}

The two relevant lines of code are in the try block. First, the application creates a LoginContext, then calls the login() method. Although this sounds simple enough, there is quite a bit going on here, so lets start from the top:

First, the securityDomain string. The security domain is used to determine what login modules should be used by the LoginContext instance. On the client, you will need to create a security domain configuration file that defines this security domain; I called mine auth.conf (the name is not importatant) and it simply contains the following:

exampleDomain {
     net.eskeeter.jaasexample.CustomLoginModule required;
};

The contents of the file are simple. The exampleDomain label identifies a security domain, and the modules it needs are enclosed in the curly braces. In this example, there is only one module, MyCustomLoginModule, and it is required. We will see the implementation of the MyCustomLoginModule class shortly.

Second is the instantiation of a CallbackHandler. The callback handler is used by the login modules to prompt the user for their username and password. This allows you to write Login Modules independent of how the client application interacts with the user, wether it be console based, Swing, network communications, or even a database lookup. We will come back to callback handlers later. For now, it is enough that you understand that the handler will get the username and password from the user, and then give that information back to the LoginModule.

The next thing we do is instantiate the LoginContext with these two pieces of information. When the LoginContext is created, it looks at your security domain configuration file and creates an instance of each login module specified. Before we can understand how the LoginContext interacts with each Login Module, perhaps we should take a look at what goes into the login module itself. Here is the MyCustomLoginModule implementation, details have been taken out for brevity, but we will come back to them in a bit:

public class CustomLoginModule 
  implements javax.security.auth.spi.LoginModule
{
    private Subject subject;
    private CallbackHandler handler;
    private Map sharedState;
    private Map options;

    private String username = null;

    // Saves the state of phase 1, login().
    private boolean loginOk = false;  

    private SimplePrincipal usernameprincipal;
    private Object password;

    public void initialize( Subject subject, 
			    CallbackHandler callbackHandler, 
			    Map sharedState, 
			    Map options)
    {
	this.subject = subject;
	this.handler = callbackHandler;
	this.sharedState = sharedState;
	this.options = options;
    }

    public boolean login() throws LoginException
    {
        ...
    }

    public boolean commit() throws LoginException
    {
        ...
    }

    public boolean abort() throws LoginException
    {
        ...
    }

    public boolean logout() throws LoginException
    {
        ...
    }
}

Each of these methods are defined in the LoginModule interface, so they must all be overridden. When the LoginContext creates an instance of the login module, it uses the default no-parameter constructor, and then calls the initialize() method. The only purpose that initialize() serves is to store away the parameters for the other methods to use later. The implementation shown here is exactly how you should expect to see it in any subclass of LoginModule. The Subject that is passed in represents the "thing" being authenticated (i.e., the user). The CallbackHandler is a reference to the handler you passed in to the LoginContext. The sharedState map lets you pass parameters between login modules, such as the username and password, so that the user does not need to be prompted for them with each module. The options map allows you to configure options at runtime; we do not use it in our sample implementation.

The next thing that happens in our JAASExample class is that we call the LoginContext's login() method. As you might have figured out by now, this will in turn call the login() method on each of the LoginModule instances it created. The login method looks like this:

public boolean login() throws LoginException
{
    NameCallback namecallback = 
	new NameCallback( "Enter username" );
    PasswordCallback passwordcallback = 
	new PasswordCallback( "Enter password", false );

    try
    {
        handler.handle( new Callback[]{ namecallback, 
					passwordcallback } );

	username = namecallback.getName();
	password = new String( passwordcallback.getPassword() );

	System.out.println( "TODO\t" + 
		            this.getClass().getName() + 
			    ": Call Authentication Code." );

	loginOk = true;
	return true;
    }
    catch ( UnsupportedCallbackException e )
    {
    }
    catch ( java.io.IOException e )
    {
    }
    finally
    {
    }

    return false;
}

The execution of the login method completes phase 1 of authentication. The login method creates a NameCallback and PasswordCallback and passes them to the CallbackHandler; we will look at this in more depth a little later. The only other thing that login does is to save the state of the callbacks by storing the username and password in its private instance variables. The SimplePrincipal class is defined as follows:

public class SimplePrincipal implements Principal
{
    private String name;
    private boolean destroyed = false;

    public SimplePrincipal( String name )
    {
	this.name = name;
    }

    public String getName()
    {
	return name;
    }
}

The implementation in the download is a little more complicated than this one because of some JBoss requirements. For more information on that, see my entry on creating custom JBoss login modules with JAAS. Note that nothing has been added to the Subject yet, this is done in commit().

public boolean commit() throws LoginException
{
    if ( ! loginOk )
	return false;

    usernameprincipal = new SimplePrincipal( username );
    password = new String( "idontusethis" );

    subject.getPrincipals().add( usernameprincipal );
    subject.getPublicCredentials().add( password );

    this.username = null;
    return true;
}

Commit stores the state saved in login in the subject being authenticated. Note that in the implementation I did for jETIA (http://www.jetia.com), I pass a phony password to the server. Since I do my authentication to the corporate user database on the client side, there is no reason to pass the actual password to the server. For JBoss though, it is important that you pass SOMETHING in the subject's credientials (we'll talk more about JBoss after we understand JAAS in general.).

The abort method should simply destroy all internal state saved in the LoginModule. The logout method should remove any principals or credentials from the subject that were added by that LoginModule.

The ONLY thing left to understand of the client side of things is the CallbackHandler. The CallbackHandler interface only defined one method, handle, that takes an array of Callback objects. For a description of the different types of callback objects, see the javax.security.auth.callback package in the J2SE API. Our CallbackHandle, CustomCallbackHandler, looks like this:

package net.eskeeter.jaasexample;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import java.io.IOException;

public class CustomCallbackHandler 
  implements javax.security.auth.callback.CallbackHandler
{
    private String username = null;
    private char[] password = null;

    public void handle(Callback[] callbacks) 
	throws IOException, UnsupportedCallbackException
    {
        prompt();

        for ( int i = 0; i < callbacks.length; i++ )
	{
	    Callback callback = callbacks[i];

	    if ( callback instanceof NameCallback )
	    {
	        NameCallback ncb = (NameCallback) callback;
		ncb.setName( username );
	    }
	    else if ( callback instanceof PasswordCallback )
	    {
	        PasswordCallback pcb = (PasswordCallback) callback;
                pcb.setPassword( password );
	    }
	    else
	    {
	        System.out.println( 
			"Unsupported callback: " + 
			callback.getClass().getName() );
	        throw new UnsupportedCallbackException( callback );
	    }
	}
    }

    /**
     * Prompts the user for username and password with the 
     * AuthenticationDialog dialog. This method may only be
     * called once per instance.
     */
    private void prompt()
    {
	AuthenticationDialog dlg = 
            new AuthenticationDialog( null );
	dlg.show();

	username = dlg.getUserName();
        password = dlg.getPassword();
    }
}

The only thing to do now is compile everything together, and run it. The one detail we did not cover above, is telling the LoginContext where exactly to find you security domain configuration file. Fortunately, this is as easy as passing a parameter to the JVM when you run it. To start this application, type the following:

java -Djava.security.auth.login.config=/auth.conf 
    net.eskeeter.JAASExample
Passing J2SE Collections in EJB Remote Methods

Posted 1646 days ago

The J2SE Collection interfaces and abstract classes do not implement the Serializable interface, making it difficult to pass Collections around using EJB Remote Interfaces.

The trick to this one is to be explicit about the type of Collection you want to use. I discovered this problem while implementing the Value List Hander pattern from Sun's J2EE Patterns Catalog. If you're unfamiliar with the pattern, it allows you to iterate over a list of remote entities in an efficient manner, by utilizing the Transfer Object pattern, also from the J2EE Patterns Catalog.

I wrote an Enterprise Java Bean to act as a facade to my VLH objects in the business tier, and found that it was throwing a NotSerializableException when I attempted to return a sublist of a java.util.List reference. The List variable referenced an instance of an ArrayList object, which does implement Serializable, but since I was referencing it as a java.util.List, which does not implement Serializable, the resulting sublist was not Serializable either.

I simply changed the VLH classes to contain a reference to an ArrayList internally instead of a List. This seems to have fixed that problem, hope it helps you with yours!

Serializing Static Instances over EJB Calls

Posted 1646 days ago

I've recently run across a problem serializing "enumeration" classes over RMI method calls... here's how I resolved it.

First note that "enumeration" is in quotes for a reason, I'm not talking about the java.util.Enumeration interface. Lets say that I wanted to represent user-states in an enum, I've come to use the following pattern to accomplish this in Java in place of C/C++'s enum type:

public class UserState
{
    public final static ONLINE = new UserState( "ONLINE" );
    public final static OFFLINE = new UserState( OFFLINE );
    public final static IDLE = new UserState( "IDLE" );
    public final static AWAY = new UserState( "AWAY" );
 
    private String name;

    private UserState( String name ) {
        this.name = name;
    }
}

This provides me with four final static instances of a UserState in the system. I can compare them using the == operators, because UserState references will point to one of these four.

In the J2EE world, this works great within each tier; however as soon as you try to pass an object like this into another tier using a remote EJB method call, problems arise. When you pass an object over an EJB method call, the object is serialized on the caller's side, and deserialized on the receiver's side. When that object is deserialized, however, it has the same logical values, but is itself a NEW INSTANCE of the UserState class. This will fail any comparison made using the == operator to one of the original four static instances.

To get around this, what you need to do on the receiving side is check the logical value of the object passed in, and set that reference to be one of the original four static instances. To help facilitate this, I've added toString() and getInstance( String str ) methods to my enumeration class pattern:

public class UserState
{
    ...

    public String toString() { return name; }

    public UserState getInstance( String str )
    {
        if ( str.equals( "ONLINE" ) ) return ONLINE;
        if ( str.equals( "OFFLINE" ) ) return OFFLINE;
        if ( str.equals( "AWAY" ) ) return AWAY;
        if ( str.equals( "IDLE" ) ) return IDLE;

        return null;
    }
}

So say I had a method in an EJB's Remote interface that looked like this:

public UserState getUsersState( String username ) throws RemoteException;

On the client side, what I would need to do is this:

UserState state = ejbremotereference.getUsersState( "timfanelli" );
state = UserState.getInstance( state.toString() );

This will get the user's state from the EJB instance, and then the second line reassigns the UserState reference to point to the appropriate static instance on the client. The same type of trick would be used in the Business Tier if I were to ever pass a UserState object into the EJB.