WebObjects Java Client, the 3rd way

Last revised on March 28th, 2008.

In this document I try to illustrate the possibilities of the using Java Client capabilities built into WebObjects, without using any of it's provided user interface functionalities, just the data handling. There is some general information in it, suitable for people who have not encountered WebObjects before, and might be just looking for a solution to their software design problem. There are also practical starting points for developers who want to give it a go, but simply do not know where to begin. I hope that this will help them out. It also might come in handy to developers that are (or were) using "Direct To Java Client" and the "Non-direct Java Client" approaches of WO, if they decided to switch to making custom GUI Java Client applications. It would be impossible to write anything comprehensive that would cover it all, this document just tries to get you started on the way.

1. Introduction

IDEs, APIs, etc.

This guide, document, even in parts where specific ways to code things are described does NOT require it to be within a specific Integrated Development Environment (IDE), nor does it talk about specific Application Programing Interfaces (API) that one might or might not use for the development of their WebObjects Java Client application. It is all written in an as independent way as possible. There are of course things you simply will need to know already: you need to have a grasp on Java programming, you need to understand some networking concepts etc.

What is WebObjects

WebObjects (or simply WO) is a development environment that is the property of Apple Inc., and currently distributed with their operating system, the Mac OS X. In short in consists of everything needed for developers to make dynamic and database driven web applications, Java Client applications (more on that below), and to deploy them on the internet, or intranet. For more information go to Apple's homepage, or visit a number of web pages, blogs, wikis and tutorials made by WO users to help newcomers orient themselves.

Why do we like it

For this you might want to refer to some other sources out there. I do not want to rewrite things that other people expressed better in the first place. Since there is at the moment little information provided by Apple itself regarding WO, the best way to find this out would be to google for information, or visit the WebObjects mailing lists and talk to the (very supportive and forthcoming) community.

What about Java Client

Java Client is a kind of an umbrella expression that implies connecting Java programs running on user computers (the "clients") to some kind of service providers ("servers"), by using Sun's Java technology. For more info on Java visit the Java homepage. In practical terms this means that any computer running Java based software can connect to a server somewhere out there that is also running Java based software, and they can exchange information. There is very little limitation to what you can accomplish in this manner, as there is no definition of what this "information" might be. This is in principle not very different from many other IT solutions; what makes Java Client specific and handy is the fact that you do your programming for both the client and the server in Java, and you don't have to worry about the in-between communication. The whole Java Client idea is not the holy solution to every problem, but it provides an excellent base for solving a certain kind of problems.

Mentioned technologies, programs etc.

There is mentioning of a number of technologies throughout this tutorial that you might not be familiar with. WO and Java Client have been explained to some degree, a few other ones are:

Eclipse An open-source integrated development environment, that is a kind of a platform on it's own. Java based and pretty cool. Currently the IDE supporting WebObjects development.
WOLips A plugin for Eclipse that enables you to edit standard WebObjects files (.wod, .eomodeld, etc), provides project templates and makes building good WO apps easier and faster.
Swing A standard part of the Java platform, used for making cross platform user interfaces.
SWT Another Java based user interface system, a part of the Eclipse project.
EOGenerator A free tool that generates Java classes from EOModels based on the templates YOU provide, invaluable. An older approach to WO class generation.
Velocity EOGenerator Apache based class generator, the prefered tool for new WO projects. Even though the template syntax is different, wherever in this document you see EOGenerator mentioned, the Velocity EOGenerator can be used for the same purpose.
JBND An EOF + Swing databinding library I've made.

Disclaimer

The content of this "guide" is not exhaustive, and in places probably not precise enough. I am writing it based on the knowledge gained from practical experience, that knowledge being most of the time limited to things that were of direct or associated interest to me, for working on my projects. WebObjects is a wealth of nice ingredients, and I most likely don't do justice to many of them, by simply skipping them or not even being aware of them. For more in-depth information on specific issues refer to google, the API documentation of WebObjects, Apple's technical documentation, WO user mailing lists etc.

2. Java Client with WebObjects, in general

Basics

WebObjects has a large code base, a part of which is dedicated to distributing data in a Java Client scenario. So, there is a set of libraries made to run on the client computer. The client computer then interacts through those libraries with a WO server to retrieve data. The client side libraries are necessary for the client machine to be able to understand the data formats that WO uses. Then there are also the server side libraries which take care of data distribution, connecting to databases, keeping track of users, etc. One of the capabilities of WO which I do not get into in this document is the dynamic web page generation. If that is what you are interested in, WO might be the ideal thing for you, but this document is not. For that, go to one of the few but precious WO tutorials out there.

Architecture of WebObjects, scope of this doc

WebObjects has a very object oriented design, which is entirely out of the scope of this document. It takes a while to get to know it, even with some good documentation at hand, which is nowadays difficult to find. The reason I mention this layered architecture is to point out that there are parts of the WO suite dealing with data distribution, parts with making dynamic web pages, parts with making Java Client applications. All these different parts fit very well together, and sometimes you will not even be aware that you are using them. Some of them you might not even use. Apple has more then half a dozen books about WO, and even that barely scratches the surface. This document focuses on only one super-specialized aspect of WO, nothing more.

Different Java Client approaches WO provides out of the box

WO documentation describes (or at least used to describe, we are on the brink at the moment of this whole feature set being depreciated) two approaches for making Java Client based web applications. They call it the "Direct To Java Client" and "Non-direct Java Client" techniques. Much can be said about both of them, but if you are interested in those, you should check out Apple's documentation. This document focuses on the third approach, which used to be mentioned by Apple, but only across a few pages, as a possibility.

Licensing

Be sure to take a look at the WO license agreement, to see what you can and what you can not do with their libraries. This is quite important as you need their libraries (the client side libraries of WO) running on your client machines for them to be able to connect to a WO server.

3. Custom Java Client applications with WebObjects, introduction

Why stick to WebObjects to make Java Client apps

There are many systems you could use to build Java Client applications. The reasons you might want to use WebObjects are:

  • WebObjects is really good when it comes to mapping database rows to programming (in this case Java) objects
  • it provides a lot of excellent data handling capabilities (validation, mapping rows to class inheritances, qualified querying and a lot more)
  • it is highly scalable, so you can tune your servers to handle hundreds of users
  • in case of Java Client apps it takes care of all the lower level networking for you
  • it can be used to make both Java Clients and Web (browser) based apps tapping into the same data source
  • it is simply *that* good
  • many other reasons you might be able to get an impression of from other sites, blogs, postings etc.

Why take this "custom" approach

If you are reading this, then I assume you need or want to make database driven client applications, and don't mind doing it in Java (there is a whole world of other technologies out there that you might use). Most likely you need a rich user interface application that users need to interact with data that is stored remotely, manipulate that data etc. You might need a powerful, enterprise level system for your or another company. If this is more or less the case, continue reading, this might be the solution for you.

There are situations in which the development with Java Client possibilities provided out of the WO box are not appropriate. Their user interfaces (either generated, or accomplished by translating Apple's .nib files to Swing components) are as a rule sloppier then what can be done with Java centric GUI systems (Swing, SWT), and most possibilities of fine tuning them are out of the question. Then there is the issue that if one wants to have anything remotely complex, then what is advertised as easy becomes a lot more complicated. In my opinion, and opinions of a few other people as well, it is a much better solution (if one wants to make rich user interfaces for their Java Client app) to use WebObjects just for data management, and use Swing or SWT for making user interfaces. Yes, that means that one has to know those systems as well, but it will not take much more time then learning all the ins and outs of standard WO Java Client approaches, and you will have much better tools under your belt.

Another situation where this approach can come in handy is if you need to make Java Client applications that need to be something else as typical user interfaces to a database. For example, you might want to create or adapt a scripting language to abstract from database operations. You might want to build that on top of WebObjects' data handling capabilities, or even over an already existing system. Maybe you need a database driven visualization system, something that needs to represent data in other forms as lists and tables. Some of this (not all) you could even do with taking one of the out-of-the-box approaches, but then you would need to know three systems (WO's data handling, WO's Java Client handling and your custom stuff) instead of just two (WO's data handling, and your custom stuff). This increases the possibilities of bugs, potential problems, dependencies, and in short degrades the quality of your product.

Why NOT take this approach

It is not exactly easy. If you need very basic things, then the automated user generation possibilities built into WebObjects (assuming they do not get depreciated and die) might do the trick for you. In that case it would be foolish to learn for example Swing (if you are not already proficient with it) to build your simple app.

Even if you need a complicated client app, WO might be an overkill, depending of what kind of data handling capabilities you need. Simple socket communication might do just fine.

There is no possibility (at least to my knowledge) for making Java Client applications that use combined storage (both remote and local) with WebObjects. Your apps will use remote storage, period. Sure, you can always upload and download files, make some local caches and so on, but that will all have to be your custom handling. WebObjects will not help you out there, and depending what you try to do, it might crash.

What is necessary

To deploy WebObjects applications (both the ones that server Java Clients and those that generate Web pages) you need the Mac OS X Server software. A WebObjects license is included in it.

To develop WebObjects applications you can use either Mac OS X Server or standard Mac OS X software. Both of them include Developer tools and all the necessary WebObjects libraries you will need.

There was also some talk about the possibility of deploying (not developing, DEPLOYING) WO applications on the non-server version of Mac OS X, but I am not sure exactly how that works regarding the WO license. I know that technically speaking it is possible.

You will also need some kind of a Java development environment. That can be command line compilation with javac, combined with a text editor, it can be a fully blown IDE like Eclipse, Netbeans or whatever. This is for the development of the client side application.

For the server side application development will need Eclipse and WOLips.

4. Custom Java Client applications with WebObjects, how-to

Intro

This chapter should get you going, point out what needs to be done to get your Java Client construction working, and also immediately point out to some problems you will face, and offer solutions. While writing it I've tried to say both what needs to be done and underline why. The idea was to share some experience I have had with these things in a rounded way. Hopefully it will save you some headaches I have had when first trying to do this. This point is also my guideline in choosing what to write and how, I am trying to remember where I was banging my head against the wall the most, and write about those issues.

Prepare your server application for a client scenario

To get a basic idea of WebObjects server side applications (.woa), take a look at one of the WO getting started tutorials out there. To deploy apps that serve data to Java Clients you will in general not need complicated server side software. So, you do not need to get bogged down in details of it, just learn how to make basic server apps and deploy them ("deploy" not implying full blown production deployment, "development mode" deployment works just fine as a back end for developing Java Clients).

Now, to start with what is different when developing a WO app made to serve Java Clients...

You will need a JavaClient web component (by now you should be more or less familiar with WO's component concept: the group of .wo, .java and .api resources). Good old XCode used to generate this one for you through it's standard "WO Java Client" project templates, but let us not assume that you have access to those... The following few steps describe your Java Client component.

You might be wondering why you will need this component in the first place, as you are not trying to build a web app, and WO's components normally are meant to help doing exactly that. You need this component for your server to be able to accept an incoming connection request. It breaks down like this (most of it will be described in greater detail below):

  1. You deploy your server app.
  2. A client starts up his client side app.
  3. The client app tries to connect to a WO server at the given URL.
  4. The server receives the request and passes is on to the JavaClient component, which processes it depending on its configuration.
  5. A response is returned to the client: communication is established.
  6. The client app resumes execution.

That is why you need to have a JavaClient component in your deployed WebObjects application.

So, to the practical side of things. The .wo part of the component contains the html for the component, the bindings (".wod"), and the ".woo" file which I never really understood the purpose of (although there must be one). The html file only requires one part, and that is:

<WEBOBJECT NAME=JavaClientComponent></WEBOBJECT>

The .wod file requires the WO bindings for the element in the html file. It should look more or less like this:

JavaClientComponent: WOJavaClientComponent {
    applicationName = "My Cool App";
    applicationClassName = "com.company.client.App";
    applicationDescription = "The World Changer.";
    vendor = "My company.";
}

Some of these are not necessary, some are. For a full list of bindings you should check the API documentation for the com.webobjects.eodistribution.WOJavaClientComponent class (please note that this WO element is of that class). If you are familiar with standard WO approaches to Java Client, some things might be missing in your eyes, like for example the interfaceControllerClassName binding. That's right, it is NOT necessary in this case, since your client application is handling the interface in any way it chooses. Other bindings were partly used to automatically generate JNLP files for WO's WebStart capabilities, something that might be useful to you, but that is outside the scope of this doc. Another point you should remember at this point is the applicationClassName binding. This IS important and necessary. This binding tells to WO which class on the client side is the EOApplication subclass. More on this in the "Establishing communication..." section.

And in the end there is the .woo class, which says something like this:

{
    "WebObjects Release" = "WebObjects 5.2"; 
}

Next, the .java part of the JavaClient component. It does not really require anything, except for the default content:

import com.webobjects.appserver.*;

public class JavaClient extends WOComponent {

    public JavaClient(WOContext context) {
        super(context);
    }
}

Same applies to the .api part of the component:

<?xml version="1.0" standalone="yes"?>
<wodefinitions>
        <wo wocomponentcontent="NO">

        </wo>
</wodefinitions>

This covers the JavaClient component content, at least to get you started. There is nothing preventing you from expanding on this on your own, for example, you could use your JavaClient WO component's .html file to actually display something, like a hyperlink that triggers a WebStart based client application, some explanatory content, or whatever else. Experiment according to your own needs!

OK, back to your WebObjects application in general. It now contains the crucial JavaClient component. What else do you need? Nothing really, your Session and Application classes can be as barren as they come by default. Your .eomodeld file is presumably in your application already. You do not need to generate your EO Java Classes, unlike in standard WO web apps, most of your data manipulation and work will be done on the client, so that is where you will probably want to have your EO generated classes. That's it, you should be ready to roll.

Note that this is only what you *need* to have to get a server for your client apps running. There is a whole lot more you *can* have and most likely will want to have. More on this in the "Additional things..." part.

Deploy your server application

Deploying your server app does not differ from deploying any other WebObjects application. There are certain differences in how it will be used, which start to matter with issues like load balancing etc. So, the fact that you are deploying it only to serve Java Clients does have consequences, but does not change the process.

You also might want to make an app that is a combination of a Java Client serving app, and a standard web app. There is no reason why you should not, except that in complicated scenarios it might make debugging and keeping your apps up and running more complicated. Personally, I prefer to make only one WO component for a Java Client serving app (the "Main" component), and on it say it is a reserved URL, provide a hyperlink to somewhere else, or something like that. User friendly, but not providing much functionality.

Client application libraries

There is a set of .jar files that are distributed with WebObjects frameworks (found in the /System/Library/Frameworks/ folder), meant to be included in client side applications. They are typically stored in the WebServerResources folder of different WO frameworks. Here is a list, which is as far as I know complete (some other frameworks have a WebServerResources folder which contains nothing):

  • JavaEOApplication.framework/WebServerResources/JavaEOApplication.jar
  • JavaEOControl.framework/WebServerResources/JavaEOControl.jar
  • JavaEODistribution.framework/WebServerResources/JavaEODistribution.jar
  • JavaFoundation.framework/WebServerResources/JavaFoundation.jar
  • JavaEOGeneration.framework/WebServerResources/JavaEOGeneration.jar
  • JavaEOInterface.framework/WebServerResources/JavaEOInterface.jar
  • JavaEOInterfaceSwing.framework/WebServerResources/JavaEOInterfaceSwing.jar
  • JavaEORuleSystem.framework/WebServerResources/JavaEORuleSystem.jar

Establishing a communication between the client and the server

The juicy part.

WebObjects generally likes to do things for you. Which is great, most of the time, but not really at other times. There is a lot of code in the client side of WO that you do not need, and most likely do not want. A lot of it is half wired to the user interface generation capabilities, which only gets in the way if you want to skip that approach. In that sense you should be careful in relying upon the API, as it often automatically assumes what you want to do.

Still, to establish a communication between the client and the server there are a few central points.

The first one is the static main(String[]) method of the com.webobjects.eoapplication.client.EOClientApplicationSupport class. This method provides an entry point for client side applications, essentially taking care of connecting to the server. You supply it with an array of Strings, I'm not aware of the the full list usable arguments. I only use the following String[]:

{"-applicationURL", "http://domainName/cgi-bin/WebObjects/AppName.woa/"}

This will tell to the stated method where to try to find the server application. The call should be within a try / catch block, as it is possible it will throw an exception for any number of reasons. In my experience it never locks the app down, so there is no need for you to provide your own timing out system around it.

The second thing you need to implement is your com.webobjects.eoapplication.EOApplication subclass. This is a fine example where WO will want to do more for you then you want it to. There is a set of methods in the EOApplication class, most of which I do not use. For example the startApplication(NSDictionary, EOComponentController, EOApplication.ApplicationSupport) sounds good, but requires an EOComponentController object, which is a kind of a bridge between the Cocoa concept of controllers and Swing components. Which I do not want to use. Still, subclassing EOApplication comes in handy because you can override the finishInitialization() method.

finishInitialization() will be called once the connection to the server has been established. This is where you get the control of your program back into your hands. From here you can start doing whatever you like. EOF has been initialized and connected, you can bring up your custom GUI, fetch the data using EOF, populate your GUI with it, etc. Be aware however that finishInitialization() will be called from AWT's event dispatch thread. For those unfamiliar with it, that is the thread responsible for managing the windowing system, and receiving events in AWT and Swing. If you are not working with Swing, you probably want to switch to another thread.

Now is the time to recall setting up the JavaClient component on the server side of this story. I was pointing out one of the bindings in the component, the "applicationClassName". Now you can see why it is important, this is meant to be the com.webobjects.eoapplication.EOApplication subclass mentioned above, which is a part of your client application. WebObjects needs to be aware which class that is, so it can connect to it.

Is there another way? Most likely yes. I've avoided anything remotely resembling WO's user interface controller and generation classes, when trying to make this work. I've done some digging through them however, hoping to find something useful, but did not. This was however done with the idea of leaving Swing to do the interface work, I was actually looking for handy data binding classes that would bridge the gap between EOF and Swing. What I have found was a lot of Cocoa concepts implemented on top of Swing in obscure and, for my purposes, dirty ways.

Another thing to consider is that you can encapsulate all of the above in a part of your application. The time or place for connecting to the server are not in any way enforced. Your program can run for hours, doing whatever it should, and only then connect to the server, do some data transfer, and disconnect. I think this point is another place where the "custom" approach can come in really handy, you can relatively easily build Java Client capabilities into an already existing application. Something I believe would be quite difficult using standard WO approaches to Java Client.

Client application how-to, basics

The client application. It can be just about any kind of a Java application, applet, command line tool etc. As long as it is written in Java (SE), and can connect to your WO server over a network, you can make a WO JavaClient app from it. And since WO is pretty good and translating relational database information to objects, a world of possibility just opened up for you and YourGreatApp(tm).

Assuming you have empowered your app with the appropriate WO libraries, you get a set of really fine options, which are:

Data manipulation: Enterprise Objects Frameworks, aka EOF is the data handling layer part of WebObjects. A subset of it's functionality is extracted to be used in client applications, along with some extras that are necessary in the specific situation that a client application is. If you are familiar with html oriented WO programming, you will know 95 % of all you need to know. The object graph is managed in the same way as on the server, the objects are an implementation of the EOEnterpriseObject class etc. If you are not familiar with it, think of it as one of the more appreciated row to object mapping and manipulation systems being delivered to your hands. It is way beyond this document to go into all EOF has to offer.

So, it is quite easy. You need to fetch all the Person records stored in your database? Just execute something like this (assuming the connection between the client and the server is established):

//	create a new editing context
//	it's parent object store will be the distributed object store,
// EOF's connection to the outside world
EOEditingContext ec = new EOEditingContext();
NSArray persons = ec.objectsWithFetchSpecification(
	new EOFetchSpecification("Person", null, null);

//	want to make a Swing JList containing those items?
JList myList = new JList(persons.objects());
//	BEWARE:	Swing uses toString() to display objects in a list
//	so override in client side EO classes

Of course, most of the time you will be doing more complicated things then this, just an example.

Data changing is just as straightforward, assuming you have a fetched array of "Person" table rows as displayed above:

EOEnterpriseObject p = (EOEnterpriseObject)person.objectAtIndex(index);
p.takeStoredValueForKey(nameTextField.getText(), "name");
//	or
Person p = (Person) person.objectAtIndex(index);
p.setName(nameTextField.getText());

//	done with changing data, save changes
p.editingContext().saveChanges();
//	the call gets propagated to the distributed object store,
//	which in turn transfers the changes to the server and asks it
//	to save them to the database

Multithreading... Client side EOF is not bound to any single thread, so at some point or another you might want to offload fetching and / or data processing to other threads then your user interface handling etc. Not a problem, as long as you avoid all the standard pitfalls of multithreaded code.

Then there is the quite handy Remote Method Invocation (RMI). Another Java(tm) implementation that goes hand in hand with the Java Client concept (which actually relies on it to some degree). The possibility to trigger a method on a remote machine and retrieve the results. There of course is more to it, both in capability and complications, but that is what it comes down to. In a WO Java Client situation it means that you can call specifically prepared methods on the server from the client side. To trigger a server side action, obtain some result, etc. It can also be used for security purposes, to isolate certain logic (a piece of code) on the server, if you are afraid of de-compilation of your client side application.

There are two types of RMI in WebObjects, the stateless invocations, and "state-full" ones, for lack of a better term. "Stateless" implies that you can invoke methods WITHOUT automatically causing the state of the object graph of the client (meaning: all the changes you made to the data) to be uploaded to the server. Then there is the "state-full" version, which pretty much does the same thing, except that it allows you to invoke methods remotely on a specific EO, and it makes sure that the client and server object graphs are in the same state before the remote invocation is made.

IMPORTANT: Do not confuse the "stateless" and "state-full" concepts of Java Client RMI with those of standard WO components. On the server side, "stateless" implies that no track is kept of the current user of the application; there is no session. As far as I know, a Java Client connection to the server always causes a session to be created, and there is no way around it. If you want something more "stateless", you could try making an app that consumes WebServices, also a nice approach in it's way, but not related to Java Client in the sense we talk about it here.

Personally I do not use RMI except in the stateless mode. It is a handy way to for example retrieve file data that is stored on the server. Example of client side code for stateless RMI:

//	stateless RMI is invoked on the EODistributedObjectStore
//	which is the first hop from the server, in EOF's eyes
EODistributedObjectStore dos = 
	(EODistributedObjectStore)EOEditingContext.defaultParentObjectStore();

//	what we are trying to get from the server
NSData fileData;

//	invoking a method in the server side session
try{
	fileData = dos. invokeStatelessRemoteMethodWithKeyPath(
		"session",			//	where the method is
		"clientSideRequestGetFile",	//	method name
		new Class[]{Integer.class},	//	argument types
		new Integer[]{anInteger}	//	argument values
	);
}catch(Exception ex){
	/* invocation failed for whatever reason, act accordingly.
	a nice thing here is that Exception differentiation
	works remotely as well, so you can try to catch an
	IOException, for example, to know if the reading
	of your file failed, as opposed to some other 
	exception if the file was not present
	*/
}

This will call the NSData clientSideRequestGetFile(Integer) method in the relevant session on the server. Naturally, for this to work, the method has to be present there. Another thing to remember is the naming convention for methods that can be invoked remotely. For security reasons, the only RMI requests that will work are those that call a method whose name starts with "clientSideRequest...". If working with RMI more you will most likely want to isolate the above code in some kind of a class that keeps a reference to the EODistributedObjectStore object, provide methods for specific invocations you use, etc.

This pretty much covers the basics of using client side EOF. There is a whole lot more to it of course, as you have most of EOF's capabilities that are present on the server: validation (against the model and custom, per-key validation), key-path evaluation, qualifying, faulting, pre-fetching, etc... What is great about Java Client is that most of the work is now actually performed on the client, so you can have reasonably complicated and time consuming processes going on without being afraid that your server will not be able to handle it once many users are connected. Your server will in this situation work primarily as a data conversion (database rows to EOs) and distribution center.

Customizing the communication between client and server

By default the communication between the two is a done through straightforward HTTP. If you would like to change that, use SSL for example or another protocol, you need to work with the com.webobjects.eodistribution.client.EODistributionChannel class. For more details on how to use it, check it's API.

Client side EOF peculiarities

There are some slight differences and a few bugs (that I have detected, there of course might be more) in the client side distribution of EnterpriseObjectFrameworks. I will try to give a brief enumeration of them.

Validation bug. Most of client side validation works as expected, and as it is illustrated in the documentation. For more on EOF validation system (which is quite powerful) consult Apple's documentation. However, there is one bug that is quite serious. In the EO model file it is possible to define "deletion rules" which indicate how a record's relationships should be evaluated when an attempt to delete the record occurs. For example, it is possible to say that if an "Author" object (row in the database) has related "Book" objects, then it should not be possible to delete that "Author" row from the database. EOF enforces this by throwing an instance of com.webobjects.foundation.NSValidation.ValidationException when validateForDelete() is called upon the "Author" object in question (which can be done manually, and is also automatically performed before EOF tries to delete that row in the database). EOF will know that this is not an allowed operation because it says so in the EO model. On the client side, however, calling validateForDelete() will never throw the said exception. Which might lead one to believe that the object graph is in a state where it can be saved to the database, at which point the unexpected exception will be thrown.

Besides reporting this to Apple and hoping for the best, there are two workarounds for this issue. The first one is to override validateForDelete() in relevant places in your generated EO classes, doing manual comparison, instead of using deletion rules defined in the model. This is a bad solution, as you will constantly have to maintain them to be in sync with the EO model. The second one is to override the method generically in an EOEnterpriseObject subclass that you use as a superclass to your EO classes. This technique goes well when using EOGenerator (see the "Additional things..." part). The code you need is below (it is a part of the org.jbnd.eof.EOFDataObject class, which is a part of the JBND library (more on that later).

There is also an issue with constructing EOs. The problem is that for some reason EOF fails to obtain the EOClassDescription object for the object in question. This was a weird behavior to observe since everything goes well if you have fetched for objects of the same Entity before trying to construct new ones. Since EOGenericRecord provides a constructor that takes an EOClassDescription argument, my workaround has been to generate my EO classes (EOGenerator again) that look something like this:

/** Entity name of the EO. */
public static final String ENTITY_NAME = "PunchItem";

/**
*	Constructor. Creates an EO with the <tt>EOClassDescription</tt> of the
*	relevant entity, to ensure a proper client side behavior.
*/
public ClassName() {
	super(EOClassDescription.classDescriptionForEntityName(ENTITY_NAME));
}

As you programatically request for an EOClassDescription object, it is retrieved from the server succesfully, and no exception is thrown. I believe that this bug is caused by the was EOClassDescription objects are requested and produced by EOF, a system that described in the part of WO documentation called "EOClassDescription concepts" for which a link is provided in com.webobjects.eocontrol.EOClassDescription API.

And the last thing of interest to point out is that the client side lacks some of the server side functionality and classes, and uses some extra ones. For the stuff that lacks it is to some degree possible to tap into it through RMI, basically executing the code on the server and returning the results to the client. This of course works only in some cases.

What is NOT there is the eoaccess package. This includes nice things such as EOUtilities, the adaptor layer, the classes used in the programatic representation of an EO model file, etc. Most commonly used class (by the programmer) of these, EOUtilities, often provides functionalities that are just "shortcuts" for what you can do with eocontrol classes, so you can live without it. Sometimes you can use RMI to trigger EOUtilities on the server to do something, for example call a stored procedure. And sometimes you just will miss it.

What is added is the com.webobjects.eodistribution.client package. It provides some client side functionality for stuff that is in the eoaccess package on the server, and some client specific stuff. Cool stuff there are the EOAttribute and EORelationship classes, which can provide you with detailed information on the attributes and relationships defined in your model. Handy for example if you want to limit the number of maximum characters in a text field based on the allowed character width of the attribute that will be edited in it. Of the things found in the com.webobjects.eoapplication.client package I've only ever used the EOClientApplicationSupport.main(String[]) method, as desribed in "Establishing a communication..." part. There are a few more classes that I have never really found a practical use for.

Additional things and techniques that can help

EOGenerator is a really fine tool to customize the way your Java classes are generated from the EOModel. If you have not tried using it already, you should try. I remember I heard about it a lot before I actually went and tried it out, I simply did not feel the need. It seemed that my EO classes did all they should. Nowadays I would not give it away for the world. Among other things, it enables you to do the following:

  • generate classes that inherit an arbitrary class, and implement arbitrary interfaces
  • generate custom constructors (for example the mentioned constructor that uses EOClassDescription objects)
  • generate static String declarations for the keys of all the attributes, which is great for code completion, and better compile time checking
  • generate your own arbitrary methods from individual keys, or generate customized getter and setter methods. I use this to fire change events from my EOs (more on this just below)
  • and last but surely not the least, EOGenerator is made with the capability to generate two classes for each entity. One class that has all the getter and setter methods, key declarations etc, and inherits from your common EO superclass. You never manually edit this class. Then another class is generated that inherits from the first generated class, thereby having all of it's functionality to start with. You put all your custom logic in here, thereby separating the generated code from your own, which makes it easier to maintain and read. Invaluable.

You should be convinced by now. Just go get it, if you are not using it already.

Event firing when EOs change. This is not something EOs do by default. I suppose the reason why they do not is twofold, for one they were originally made in Objective-C, which as far as I know does not rely on the event firing mechanism as extensively as Java does, and two, it is not so necessary on the server side, what WO is most often used for. In a typical WO web based application, the user sees data in a browser, and a request has to be made from the browser to the server for the display to be refreshed. It is easy in such a case to simply feed the requests with latest values. However, in a Java Client situation the story is different. Editing is real time, so you would want that the changes the user makes are immediately reflected everywhere where the changed value is displayed in the interface. Anything else will confuse the user, and reduce their productivity. Thus reducing the quality of your application. In short, you need event firing.

My way to solve this was EOGenerator. I've decided on this approach after getting deep into the way EOF sets values, and it was my impression that trying to solve this problem on a more generic level (for example overriding the takeStoredValue... and similar methods) would not give the desired results. So, I've made my EOGenerator templates so that they generate EO classes which fire appropriate events from setter methods. Actually, they do so only after checking if the old value is the same as the new value being set, otherwise there is no change, so no reason to fire an event. This functionality is made public (and open source) in the JBND library.

Another thing to consider when making Java Client apps is where you want certain resources to reside. This is always an issue you have to deal with, even if you are using WO for web apps, and much has been said about different approaches. In the end, it is your decision, as only you know what kind of data you are talking about, and how it is meant to be used. Still, it is worth mentioning how making Java Client apps influences this problem. In standard WO apps you can choose between:

  • the database
  • the server file system
  • the WO application bundle
  • the web server

When making JC solutions you have somewhat different possibilities:

  • the database
  • the server file system
  • the WO application bundle
  • the client side application bundle
  • the client side file system

I use pretty much all of the above. The database, well, we all know what goes there. The server file system is great for dynamic data that you do not want to store in the database, for whatever reason. Remote Method Invocation makes it really easy to retrieve that file data from the client side. The WO application bundle is a great repository for data that is not dynamic, but can change with time so you prefer to have it centralized, instead of distributing it with the client application (if such an application permanently resides on the client computer). This gives you less worry about as you don't have to update the client apps every time your data changes. Just update the server, and the clients are happy. The client side application bundle is the place to store resources that are entirely client-centric, and seldom change. For example user interface images and icons that are not related to the data. And then there is the client side file system, which is by far the most volatile of all, as you have (being a system programmer and / or admin) the least control over it. I use it for example to temporarily store files that are downloaded from the server. A cache. So, if the users want to look at a photo ten times, the client app still has to download it only once.

Still, I've faced some difficult decisions regarding this, as things are rarely as straightforward as we would like them to be, especially once you start making more intricate functionalities for your system. But, the decision is finally in your hands. If, however, for some issue you continuously fall "in between" of one of the approaches, maybe the best way is to rethink what you are trying to achieve, and try another road. Mixing data storage approaches (for one single issue that is) is regularly a pain, and will probably make you unhappy in the future. Sometimes unavoidable though.

EOGenerator issues

The already mentioned JBND library provides some EOGenerator templates that I use in combination with the EOFDataObject class to fire events after EOs have changed. Be sure to check the docs out for a description of the exact functionalities.


For general info about EOGenerator, how to use it etc., check out the author's website.

5. Java Client applications with Swing

Why Swing

Swing is a part of the Java platform, Standard Edition. Which means that it is present on every desktop machine that has Java installed. It sprouted from AWT (abstract windowing toolkit), which was Sun's first attempt at making a windowing toolkit that follows the Java promise to abstract as much as possible from the underlying hardware of the computer, thus ensuring that the code you write and compile can execute on any Java enabled platform. In an ideal world this would work perfect, but in reality of course it does not. So, to cut the long story short, Swing is never as pretty as the native windowing system, but it is still a powerful GUI system, and most importantly: cross-platform.

The good side of the story. However imperfect, Swing has come a long, long way since AWT. It has introduced a large set of features that are capable of doing a whole lot in making user interfaces. It has also abstracted the graphical painting from the windowing system, thus enabling entirely arbitrary "looks" of user interfaces, of course still in the typical paradigm that we know as Graphical User Interfaces. It comes packed with many nice data binding capabilities (more on that below), and scales very well with your familiarity with it. What I want to say by that, it is not that very difficult to get started, but the whole API is quite open thus enabling you to work at the lowest levels of user input handling and computer graphics generation to make whatever your heart desires. And last, but definitely not the least, it enables you to code and compile your user interface once, and run it anywhere. Thus becoming a very productive tool for multi-platform application development.

The bad side of the story. It is a pain, plainly put. Designing a good user interface is more difficult then with native windowing systems. This all has a good reason, it being that Swing will need to render your interface on different platforms, and thereby it never really knows which is the standard font for that platform, the standard button size, the standard keyboard shortcuts and so on. So, it abstracts all that into a non-intuitive approach of user interface defaults, minimum, maximum and preferred sizes, user interface painting delegates and so on. It takes a while before you really stomach it all, and before you can make high quality complicated interfaces. It also requires from the programmer to think on an abstract level, because what you see during development might exhibit an entirely different behavior on another platform, if you didn't have "the way Swing does it" in mind. Next to that all this cross-platformness also introduces maintenance issues, as sometimes things don't get really implemented as they should, so one platform is not rendering an element correctly, while another might, or one version does and the next does not. If you take it on, be ready for a moody ride. And then even if you know it inside out, you never have the latest native platform's GUI features, craze and smoothness. It's just the way it is.

Current state of things. It is getting better, and better. Bugs are getting fixed, new functionalities getting built in. I have even noticed that with new releases the API documentation for classes that have been around since forever have been revised, and updated to address some common concepts and misconceptions. Java is open sourced, in it's way, Swing included. Java 6 added some really cool things to Swing which will make our apps look and feel even better to end users. The amount of open source solutions (from graphing and animation to extending the functionality of standard GUI elements) is enormous, and continuously grows. Sun even directly supports some of these projects and sometimes includes them into the platform, if they are worth it. Simply put, there are more and more things we like, and less and less of those we don't.

Conclusion. I always found it rather simple. I need to make a cross platform product. I do not have the resources to invest into native development for each platform. I want to make desktop apps, and not an AJAX interface, or Flash or whatever. Which pretty much leaves me with Swing and SWT (the Eclipse project's cross platform GUI toolkit). In my eyes Swing is a better horse to bet on, however cool some SWT's features are. Next to that, we are talking about databases (at the moment). Their interfaces are relatively simple most of the time, and users typically less critical of visual appeal. They want the work done in a handy fashion, and that Swing can take care of.

Swing's data architecture, in short

OK, this here has been an issue of debate. Is Swing MVC, why yes, why not, what is proper, what is not. Let's try to skip that and focus on how it actually works, and how to use it.

Starting with general ways to handle "data". java.util package provides Java with a lot of data handling capabilities. Meaning, ways to push and pull java Objects around into containers, sorted lists, sets (Java way of naming a container that contains only one of every item), maps (dictionaries, a way of relating an object to some name) and more. It provides a lot out of the box, and is very extendable. Meaning, there are standard interfaces, and ideally places that use data containers of specific types only require that you provide objects that conform to an interface, so you are free to implement your own specific stuff. In reality, most of the time you will not need to. So, this would be the raw Object organization layer of Java.

How does that work with Swing? The short answer would be: indirectly. Swing components (user interface classes that inherit javax.swing.JComponent) manage their "state" through an underlying "model". By state I mean any data that influences how the component looks and behaves and which information it displays. By model I mean an Object that is made for this purpose, typically also having "model" in it's name (ListModel, TableModel...). Does that mean that once you have created your user interface elements, you leave them alone and just work with their models? In principle yes, you could. In reality, Swing components often provide methods that allow you to get and set their state directly through them, so you do not have to fuss with the model. This is made for convenience, beneath the surface you are still dealing with the component's model.

So, we have the model and we have the component, what now? Well, the whole principle is event driven. A large set of different "event" classes are defined, and they all have appropriate "listener" interfaces defined. Event is an indication that something happened, and a listener is the one who is interested. All the classes that can generate events allow for appropriate listeners to register themselves to be triggered when an event occurs. For example there is a ListModel, and a JList (user interface component). The JList always registers itself as a listener (it implements the ListDataListener interface) for all the events (of the ListDataEvent type) it's current model "fires". ListModel being an interface and not an implementation, you can make your own implementing classes that will take care of preserving state and firing events. And then tell a JList to use an instance of your custom made model. So, for example, you can add a new item to your ListModel implementation, an event gets fired, which will make the JList update how it looks according to the current state. Swing provides a plethora of interfaces, abstract classes that provide partial functionality, and fully implemented classes for general usage. You will most likely get to know them all pretty well. This part of Swing really is intuitive (OK, with *some* exceptions), certain principles and conventions are consistently followed, and once you get the hang of it you will easily use it to your advantage.

There of course is a whole lot more to this. There is a different kinds of events, like those that originate from the user interface components, but the principle is the same. As an example, a JList fires events when the user changes the current selection. If you want to do something as a reaction to that, you need to register an appropriate listener class with the JList, and then write code that will execute once the selection changes.

Multithreading. There is one simple rule, NEVER break it. It says: "Swing components are only allowed to be modified through the Event Dispatch Thread". This also includes models, as they will fire their events on the same thread that modified them, something that seems a bit ridiculous to me as it is quite easy to make models that fire events on the Event Dispatch Thread (EDT) regardless of the thread that modified them. Anyway, this is nothing to really worry about, just make sure you are familiar with Swing's threading concepts and conventions if you start to offload work to other threads then the EDT. The typical situation in which you will need to do this is for lengthy processes during which you want to display a progress bar or some other type of real time user feedback.

Actual component painting is an issue for itself, and not relevant here.

Nowadays much of the GUI code can be generated by Swing WYSIWYG designers. My favorite tool for the job, that I would be desperate without, is the JFormDesigner app by Karl Tauber. Very handy, very intuitive, made in Swing to handle Swing. Top notch work. Still, if you really want to make your data driven apps perform, you need to know how Swing does it.

EOF and Swing

Binding data of a Swing app is a reasonably complex issue that I don't want to go into in here. If you are interested in it, besides knowing how Swing works, you may want to check out Karsten Lentzsch's binding libraray and breakdown, a part of his JGoodies project.

That aside, I've developed an open-source Swing and EOF databinding library, JBND. This project has been a direct result of my work with WO and Swing, has been made specifically to bind Swing and EOF (even though it is extendable to support other user interface and data persistence systems), and is currently actively used and developed. For more information on it, check out library's website.

Things to make a data-driven Swing app better

Custom cell renderers. One of *the* ways of making a boring data management application into something is to get into Swing's cell rendering capabilities. I've seen many applications that might have had excellent business logic, data structures and / or summarizing capabilities, but sucked at representing those good values to the end user. They made intuitive things into a complicated bunch of inter-dependencies and confusion. They often shared the basic GUI principle, the "table and edit form" approach. This will not do.

What is the point of making "rich" user interfaces if you only stick to unimaginative approaches? Well, one of the easy but powerful ways to avoid this is to use custom cell renderers. Swing lists, combo boxes and tables all by default use the toString() method of individual Objects (or values, in case of tables) visually represent them through the default cell renderers. But they are capable of much more. Each of them can take an arbitrary cell renderer (which can be any visual component) as long as it implements the appropriate cell renderer interface. Those interfaces come down to a single method, and are quite easy to implement and plug into the user interface element you want them to be used by. And there you go, instead of having a list of Author records displaying only their toString() values and taking only a single line of text per record, you now have a nice little ID like item with a photo, name, number of books, top five books and I don't know what not, organized as you please. And yes, it still is a list, meaning you can select items, drag them around and so forth. Your app just became much more user friendly, and it took a total 30 minutes of work.

Open source solutions. There is just so much open sourced libraries out there made for Swing, that you can find virtually everything you need. Yes, many of them are of average quality, many of them are released under non open source licenses, and so on. Still, without investing much at all, you can probably take care of all of your needs.

Custom components. Finally, you might want to start making your own components, typically to perform some custom drawing procedures based on the underlying data model. This is not so difficult, you will need to get familiar with Java2D most likely, but the API is quite straightforward and there is plenty of documentation out there to get you going.

6. Where to go from here

With WebObjects

If you like what you hear and want to pursue this line of software development, you will most likely need to dig in deeper into WebObjects. Below is a small list of resources that will probably interest you.

The API documentation for WebObjects. You will work most often with classes such as:

From the eocontrol package:
EOEditingContextthe data managment object that you fetch data through
EOEnterpriseObjectthe Java interface defining an EO
EOCustomObjectthe main implementation of EOEnterpriseObject
EOGenericRecorda subclass of EOCustomObject, most often used as a starting point for your EOs
EOFetchSpecificationdoes what it says, specifies what data you are fetching and how (qualifying, sorting, pre-fetching...)
EOClassDescriptionrarely used directly, but it is healthy to be architecturally familiar with it

Knowing the foundation package also comes in handy, but that one is easy to pick up as you go along. It is NextStep's version of java.util, translated from Objective-C into Java.

Next there are a number of concepts, which are fairly well described in the WebObjects API itself, but if you are just starting with WO learning from JavaDocs is not very handy, nor stimulating. There are a number of supporting documents on Apple's developer site, the WebObjects section.

  • EOF's layered architecture basics
  • Value setting and getting principles (*very* important as it is quite powerful, even though confusing at first)
  • Data validation and coercion process (the same applies here)
  • Object graph (EOEditingContext and co.) management
  • Fetching data (EOFetchSpecification) capabilities, including sorting (EOSortOrdering) and qualifying (EOQualifier)

Good luck, and I hope you will get to enjoy and love WO as much as we do!

WO learning resources:

  • Apple's documents on the WO part of their developer site
  • The API documentation
  • The WebObjects community, especially the Apple hosted WO development mailing list

With Swing

I suppose the most important resource in learning Swing properly is an open mind. I've heard many people say many bad things about Swing, about it's architecture, about it's convoluted layout mechanisms, about sloppy results and slowness... Most of these complaints had a base in the way people often approach Swing, as if it is another native user interface generation system. It is NOT. When working with it keep in mind *constantly* that Swing is made to run on many different platforms, which even though GUIs nowadays are all more or less based on the same principle, have quite different concrete implementations and standards. Give it some slack, don't expect it to be as good as native stuff, and you will undoubtedly end up with decent interfaces. And gee, they will even run on other platforms, and if YOU did YOUR job properly in following Swing's way of doing things, your interfaces will feel native enough on those other platforms as well. Personally, I've seen some very nice Swing applications, and some very crappy ones. It all depends on how you handle it.

Resources. There are a zillion articles and books and so on about Swing, it's capabilities, how to do it and so on. There are some fantastic articles on specific issues, general architecture, approaches etc. I suppose in the beginning the most invaluable resource will be Sun's website. Now, do not be afraid when you see it, I also hated it once upon a time. I still do not like the organization of it too much, nor the style. I most often feel confused when I am there, and am trying to find my way to something that I have not seen before. BUT, the information you can find there is excellent, and made to guide you step by step through Swing's concepts and basic elements, starting easy but also tapping some difficult subjects with time. And it covers just about everything about Swing. Get into it. Oh, one of the handier ways I've found to come to a specific tutorial or resource on Sun's website was to NOT go searching on their site, but google for it. For example if I want to learn about handling tables, I just google: "Java table tutorial Sun". And then search in results for a similarly titled article hosted on Sun's site. It is virtually always in the top five, most often the first.

Then there is google. There are so many articles out there, so many libraries and concepts and books that I can not really point to one specific location. Browse the web. It is easy to find. Sometimes it will be a tech article on some obscure tech site, sometimes it will be a post on Sun's forums. You never know, but if it's sane enough for it to cross your mind, somebody most likely wrote about it.

And last, but not the least, the API documentation. It will probably become your best friend and a godfather to your kids. All of Swing is pretty darn well documented, and accompanied by tutorials that will explain a lot of things conceptually, the API will tell you all you know. Also, Sun has started revising some documentation lately, providing links into articles on their website, giving more conceptual information within the JavaDoc itself, in short, investing an effort into making our lives easier.

With WO and Swing

If you are into WebObjects and Swing, and plan to get into it further, join the web objects developer mailing list at Apple. It is a very supportive and vibrant community of dedicated developers, with a small group of JavaClient focused within it. We'll asnwer all the questions you may have, and help you get started, if necessary.

Next to that some of us are continuously working on producing more documentation, keeping the extisting stuff up to date, and promoting the technology and this approach to it.

I hope this document has been helpful to you, feel free to comment on the mail address mentioned below.

♤ Authored by Florijan Stamenkovic, 2007. email: flor385•mac•com ♤