Monday, August 08, 2005

EJB3 EntityManager

Since my first post about Entity EJBs with Hibernate, the Hibernate team put out a new beta implementation of javax.persistence.EntityManager. So I wondered what exactly it would take to jettison all the hibernate imports from my class. Well it turned out to be pretty simple. First I substituted the hibernate.cfg.xml file for a META-INF/persistence.xml file that looks like this:

<entity-manager>
<name>manager1</name>
<properties>
<property
name="hibernate.connection.driver_class"
value="org.postgresql.Driver"/>
<property
name="hibernate.connection.url"
value="jdbc:postgresql://127.0.0.1:5432/myDatabase"/>
<property
name="hibernate.connection.username"
value="darcy"/>
<property
name="hibernate.connection.password"
value="darcy"/>
<property
name="hibernate.dialect"
value="org.hibernate.dialect.PostgreSQLDialect"/>
</properties>
</entity-manager>

The interesting thing about this is that it autodiscovers the annotated classes. No longer do I have to individually list each persistent class. Secondly, I changed my main method to look like this:

public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("manager1");

EntityManager em = emf.createEntityManager();
try{
Brand b = (Brand)em.createQuery("select b from Brand as b")
.setMaxResults(1)
.getSingleResult();
System.out.println(b.getName());
}finally{
em.close();
}
}

You can see that this code is very similar to the Hibernate code that I posted earlier. Obviously the class names and some of the methods are different (like getSingleResult() instead of uniqueResult()) but at first glance it looks like getting started is pretty easy. It'll be interesting to see some of the differences between Session and EntityManager.

Tiger Development

After installing Mac OS X Tiger, and restoring applications and user data, my next job was to install development tools.

Java

On the Java side: I'm a bit perplexed why Apple doesn't ship their Java 5 implementation with Tiger. As far back as I can remember they've always shipped the latest and greatest. But this time I had to download. No big deal, but it's hidden on their website. I expected to be able to go to connect.apple.com (their developer website) click on "Downloads>Java" and it would be there. But no, only the Java 5 docs are there. Instead I had to go to the general Mac OS X website and go to the downloads section in there and search for it.

Anyway, that was only a minor annoyance. I was able to download it and install it without any trouble. My next problem was that Java 5 wasn't made the default VM. So I had a little more googling to do before I discovered a couple symlink changes would make everything happy. In the end I have all my Java apps and IDEs (i.e., Eclipse) working with the new Java 5 VM and all is well a week later.

Cocoa

Next thing was a move to XCode 2.1. I downloaded it and installed it without any issues (there was a nice big link on the Apple's developer connect website). I was able to open all my Cocoa projects, recompile and run without issue. So then it was time to move onto seeing what's new in Cocoa in Mac OS X. There's quite a bit, but the one that instantly attracted me was the visualization tools in XCode.

I've always been a big fan of modelling tools and the diagrams they create. I always find it easier to express ideas in a picture and it's always easier to look at a diagram rather than gobs of source code to figure out what someone else was thinking. Well apparently Apple feels the same way. XCode now gives you the ability to generate class diagrams from your source code (Java, Objective-C or C++). And these diagrams aren't static either. As you change things in code the diagrams reflect those changes. Fortunately, they look and behave like UML class diagrams so the symbols are pretty familiar.

Apple also uses this new diagram facility in something they call CoreData. Essentially you create an entity relationship diagram that describes the data that your application maintains and then at runtime, the core data framework will use this metedata to store and retrieve user data in an XML file or a SQLite database. Couple this with the Cocoa Bindings framework, which allows you to bind object properties to UI widgets, and you have some great facilities for building data-centric applications. Now that the persistence and UI parts of the application are taken care of by the Cocoa frameworks you are left to concentrate on the business logic. The big limitation in CoreData right now is that it's XML and SQLLite only. That means if you want to create a multiuser application with an enterprise database server you're out of luck. Secondly, even if it did allow you to go against an Oracle or Sybase server I don't think the tools are really designed for fine grained control over the object relational mapping or the queries that are generated. But I don't want to diminish the productivity of this framework in addressing the the single user data persistence problem. If I was developing a desktop Mac OS X application, I'd be all over this. Here's a nice little tutorial that you may find interesting.

There is also a nifty little feature that allows you to drag and drop an entity from the diagram into a window in Interface Builder and generate a default UI. Apple says you can use this feature to quickly create a starting point for your application or to quickly generate an application to exercise your data model. I was impressed that I could create a fully functioning application that maintained data with no code in just a few minutes!

Monday, August 01, 2005

Tiger!

Well I took the leap and bought Mac OS X 10.4 Tiger today. I also followed the recommendations on the web (kinda of a herd mentality) and erased the hard drive and reinstalled "fresh". That second internal SATA hard drive definitely came in handy for backing up applications and the stuff in everyone's accounts. A few hours later I have everything back to normal (I think). My first impressions is that the Dashboard is pretty cute but I'm not sure how useful (although the calculator came in handy once already). Spotlight is definitely nice (and fast too). Searching for anything across the disk is pretty wicked! Well it's late, and time for bed. I'll post info about the ugly stuff once I come across it. ;-)

Friday, July 29, 2005

EJB3

With the use of Java 5's new metadata support and Hibernate 3's early annotation tools I decided to see what it would take to make an EJB3 Entity Bean. Well it's quite a bit simpler than Entity EJBs used to be and I don't need a big nasty EJB container either! It's just a plain old Java object (POJO). And as you can see in the main method's source code, I can still use the same Hibernate code that I'm familiar with.

@Entity(access=AccessType.FIELD)
@Table(name="my_brand", schema="ds")
public class Brand {
@Id(generate=GeneratorType.NONE)
@Column(name="brand_code")
private String id;

@Column(name="brand_name")
private String name;

/**
* @param args
*/
public static void main(String[] args) {
Configuration cfg = new AnnotationConfiguration()
.configure();
SessionFactory factory = cfg.buildSessionFactory();

Session session = factory.openSession();
try{
Brand b = (Brand)session.createQuery(
"select b from Brand as b")
.setMaxResults(1)
.uniqueResult();
System.out.println(b.getName());
}finally{
session.close();
}
}
//getters and setters
}

Tuesday, July 26, 2005

Discovery

I vividly remember watching the first space shuttle flight on April 12, 1981. I diligently cut out the newspaper story about Columbia's maiden voyage. It was an exciting time. Today over the internet, 24 years later, I was able to watch NASA's return to flight with the launch of Discovery. Call me nostalgic but it was inspiring today as it was then...

Halo

I remember watching the 1999 MacWorld keynote webcast where Steve Jobs introduced Bungie Studios. They demoed a new game called Halo on a G3 Mac. It was Bungie's followup first-person-shooter to their other Mac-only hits, Marathon and Myth. After Microsoft's purchase of Bungie (to make Halo an XBox exclusive), the enormous Halo 2 sequel, and six years, they finally came full circle and released a Mac demo that I can download and play. It may not be as revolutionary as it would have been in 1999 but it's still a good game.

Thursday, July 21, 2005

Bundles

Last night I upgraded my versions of Firefox and Thunderbird on Mac OS X. And then at work I did the same thing on Windows XP. The installation went pretty smoothly on both so maybe to most users the differences wouldn't be that significant but for someone like me who cares about little things like this, it showcased what I think is a pretty big features of Mac OS X, Bundles.

From Apple's developer documentation:
A feature integral to Mac OS X software distribution is the bundle mechanism. Bundles encapsulate related resources in a hierarchical file structure but present those resources to the user as a single entity. Programmatic interfaces make it easy to find resources inside a bundle. These same interfaces form a significant part of the Mac OS X internationalization strategy.

Basically it's a folder that looks like a file. It's a very simple but extremely effective method of hiding the details from the user. Most of the time, when you install an application in OS X you open a disk image and drag the application icon, the bundle, to some location on your hard drive. Then you double click it to run it. If you don't like where you put it then you drag it somewhere else. If you decide the app sucks you throw it (the one thing) in the trash. You don't use an installer or uninstaller.

On Windows on the other hand, it's never that simple. You almost always run an installer and then god knows what happens. While it's true that some Mac apps require an installer, especially if they need access to protected areas on the disk, it's the exception rather than the rule.

Like I said at the beginning, maybe most people wouldn't think this is a big deal but there is something quite satisfying about the installation/deinstallation process on a Mac. It's simple and obvious and you know what happened.

Tuesday, July 19, 2005

Dave Thomas on TSS

Dave Thomas is one of the two pragmatic programmers. The Server Side posted a transcripted video interview with him. Lots of great stuff discussing the differences between:
  • Test Driven Development and Test First Development
  • Agile and Extreme Programming
  • Strong Typing and Dynamic Typing
It's hard to argue with what he has to say. Definitely worth a listen/read.

Thursday, July 14, 2005

Cocoa

When I originally created this blog I named it after Apple's Frameworks for creating Mac applications, "Cocoa". At the time, I was working my way through Aaron Hillegass's book Cocoa Programming for Mac OS X. Since Apple gives away its development tools for free with their OS I had previously played around with it. But for one reason or another I found myself leaving OS X development and instead investigating technologies more closely related to Java (the language I use at work). I also recently spent a couple months looking at C# and .NET. But finally I'm back to looking at Cocoa and think I'm ready to compare Cocoa to Java and C#. Like my C# review so many months ago (February 2005) I'll try to comment on the things that make Cocoa different from Java.

But first of all, some history. Cocoa development is done in a language called Objective C (objc for short). It was invented in 1983 by Brad Cox at Stepstone. It is described as a thin layer on top of C so unsurprisingly, anything you can do in C you can do in Objective C. The so called "thin layer" adds Smalltalk-like syntax to add object-oriented features. Objective-C uses the open-source GCC (GNU Compiler Collection) and so people can program in Objective C on any platform. I've even written a small command line program on Windows just to prove that it can be done.

Secondly, Mac OS X's (and Cocoa's) heritage is NextStep. After Steve Jobs left Apple he founded NeXT computer in 1985 and in many ways created a computer that was ahead of its time. Part of that vision, often overshadowed by the media's attention to the hardware, was the object oriented application development environment called NextStep, based on Objective-C. This set of libraries (or frameworks) was ported to several platforms (Intel, PA-RISC, SPARC, etc.) during its lifetime and became known as OpenStep in a deal with Sun MicroSystems. When Apple eventually bought Next in 1996, the NextStep frameworks became known as Cocoa. To this day the classes in the framework all begin with the abbreviation NS. Interestingly, part of Next's work in the early 90's to make NextStep portable (specifically to Intel) is what is enabling Apple to switch the Macintosh's processor from PowerPC to Intel with such little trouble.

Namespaces and File structure
  • By convention, the interface is placed in a header file (*.h) and the implementation is placed in a file with the "m" extension (*.m). This violates the spirit of the DRY principle (Don't Repeat Yourself) because the method names are now in two places. But on the upside the class's logical public interface is easily communicated through the header file. It also gives you a way of protecting your source code while still allowing third parties to use your frameworks. Java and C# both suffer from being easily decompiled.
  • There are no namespaces in ObjC. Instead a naming convention suggests using an abbreviation at the beginning of each class name (e.g., all the Apple class names begin with "NS").
Misc
  • Like Java and all other C-based languages other than C#, Cocoa uses camelCase instead of PascalCase.
  • ObjC frequently uses the at-symbol (i.e., @) to differentiate ObjC functionality from standard C functionality.
  • Object references look like C pointers. (see next bullet point)
  • NSString is one of the most commonly used classes in Cocoa. Like Java, it stores immutable Unicode strings. Use the @-symbol in front of a C string to create an NSString instance. (e.g., NSString *name = @"Cocoa";)
  • C's printf String formatting functionality is included with NSString's factory method stringWithFormat:. The NSLog() function for printing to console also supports printf-type functionality. (BTW: Java finally got around to supporting this with Java SE 5.)
  • Like C#, ObjC uses a colon (:) for subclassing instead of Java's extends keyword
  • ObjC also uses the colon (:) for implementing an interface instead of Java's implements keyword.
  • Class methods are denoted with the plus-symbol (+) instead of Java's static keyword.
  • Instance methods are denoted with the minus-symbol (-).
  • Visibility identifiers are nearly the same as Java's except they use an @-symbol in front (i.e., @public, @protected, @private). And like Java, the default is @protected when it's not explicitly defined. The biggest difference is that methods are always public. Private-like methods are created by excluding them from the class's @interface.
  • Exception handling is the same in ObjC as in Java with the keywords @try, @catch, @finally, @throw except exceptions are not part of the method signature (like C#). Exceptions were new in Mac OS X 10.3 (Panther) so I doubt that they are utilized all that frequently.
  • Like Java, ObjC uses an #import keyword to include references to the classes that it uses.
  • Like Java, the Cocoa framework is a singly rooted class hierarchy starting with NSObject.
  • An interface in Java is known as a protocol in ObjC
  • instead of Java's instanceof, NSObject has several methods for accomplishing similar functionality, isKindOfClass:, isMemberOfClass:, conformsToProtocol:
Method Syntax
  • ObjC methods define labels for each parameter. For example, an instance method for a Person class might look like this:
    • - (Person *)initWithFirstName:(NSString *)first Last:(NSString *)last;
    • This method returns a Person instance and takes two NSString parameters.
    • The first parameter is described by "initWithFirstName:".
    • The second parameter has the label "Last:".
    • The full method name is: "-initWithFirstName:Last:"
  • Using Smalltalk-like messaging syntax you would cause this method to be invoked with something like this:
    • [person initWithFirstName:@"Bob" Last:@"Builder"];
    • More generically [object methodName:param1 Label2:param2];
    • The nice thing about this calling syntax is that it's easy to tell from the calling side what each parameter is for whereas in traditional C, Java, and C# you need some documentation to help out.
    • Like Java, each method call is dynamically looked up and invoked.
  • ObjC's object oriented features are based on Smalltalk. As a result, the idea of invoking an object's method is better phrased as "sending a message to an object". In ObjC it is completely valid to send a message to an object that cannot respond to it and you will receive no error. This stands in stark contrast to Java's strong type checking at compile time. When coming from a Java background this seems strangely odd, but as you become accustomed to this dynamic behavior you soon begin to recognize its power.
  • There is a special ObjC type called id that is a pointer to an object of any class. By judicious use of id and ObjC's dynamic message mechanism you can avoid a lot of typecasting that is so prevalent in Java code. Naturally you can (and should) use the variables and parameters of the types you are expecting but in some cases where the type cannot be known ahead of time the id type is very valuable and produces succinct easy to understand code.
Memory Management
  • To create an instance of an object use alloc (e.g., [Person alloc];)
  • ObjC's constructors are responsible for initializing instance variables. The default constructor is init. Constructors that take parameters use init as a prefix.
  • Typically alloc and init are called together (e.g., [[Person alloc] init];
  • ObjC does not include any kind of automatic memory management. There is no garbage collector. Instead Cocoa uses reference counting. You use the instance methods retain and release to increment and decrement the reference count. When the count reaches zero the object is freed.
  • The alloc method automatically increments the reference count by one.
  • ObjC's destructor is dealloc. It is responsible for releasing instance variables that point to objects.
  • There is a second instance method that you can use to express your intention to release an object called autorelease.
    • GUI Cocoa application automatically instantiate NSAutoReleasePool.
    • It is this object that becomes responsible for actually releasing your object at some point in the future.
    • This autorelease mechanism allows you to return new objects from a method and is frequently employed by class factory methods (e.g., [NSString stringWithString:@"This will create an autoreleased copy"];)
    • If the calling method does not retain the returned object then it will be automatically released.
    • It is the event loop in a GUI application that creates and destroys release pools.
  • In practice this memory management scheme is more error-prone than languages with garbage collection and requires diligence to implement properly. However, memory releases happen relatively frequently and the application's memory footprint is more predictable and manageable.
Inheritance
  • Use super to refer to superclass methods or variables.
  • Use self to refer to the instance's method or variables.
  • Constructors should call the super constructor first. (e.g., -(Person *) init{if (self = [super init]){/*initialize variables*/} return self;}
  • Destructors should call the super dealloc last (e.g., -(void)dealloc{/*free instance variables*/[super dealloc];}
Properties
  • ObjC is similar to Java in using accessor and mutator methods to get and set private instance variables. The only difference is that the get methods are named the same as the instance variable.
  • I prefer C#'s and Delphi's ability to declare properties as first-class citizens. I believe it makes the code easier to read.
  • Java didn't include operator overloading because it typically gets abused in practice. ObjC doesn't include it either but having seen C#'s and Ruby's implementations I think if used properly it could make code more readable (I say "could" because I haven't used either extensively and hesitate to say with certainty)
Selectors
  • When using Java's Swing components (a.k.a., GUI Controls) you typically register an event listener with each component to be informed when the user interacts with it (e.g., clicks on a button). Because each listener must conform to a specific interface you end up creating a lot of anonymous inner classes. The code's intention is lost in the overly-verbose mechanics. Even if the IDE is generating this stuff for you, it's still ugly.
  • ObjC's selector specifies the signature of a message and is not bound to any particular class.
  • Create one using @selector( selectorName )
  • Or use NSSelectorFromString(@"selectorName:") to create one from a string.
  • You can programatically invoke a selector using one of the performSelector:, performSelector:withObject: variants in NSObject.
  • InerfaceBuilder, the tool for creating user interfaces for Cocoa applications, uses selectors in the target/action paradigm to graphically wire visual controls to methods that look like - (IBAction) methodName:(id)sender; with absolutely no code.
Collections
  • Cocoa has NSArray, NSSet, and NSDictionary and their mutable counterparts, NSMutableArray, NSMutableSet, and NSMutableDictionary which are functionaly similiar to Java's List, Set, and Map interfaces and various implementations.
  • Cocoa uses NSEnumerator to traverse a collection's members which is similar to Java Iterator.
  • Cocoa doesn't have any of the syntactic sugar of Java or C#, such as Java's enhanced for loop but because of ObjC's dynamic messaging infrastructure the need for typecasting isn't nearly as onerous so perhaps it's not needed.
Categories
  • An interesting feature of ObjC called categories, is its ability to dynamically add methods to existing classes even if you don't have the source code for those classes. Now when you think "Why didn't they add a method that does blah blah blah", you can just add it yourself!
  • mixins provide a similar feature in Ruby.
  • NSObject also has a method called poseAsClass: which allows a subclass to stand in for its superclass. This subclass can override superclass methods and add new methods.
Summary

ObjC has no garbage collector and doesn't generate bytecode which are two pretty big features of Java and C# but regardless it has just about everything that those other languages have plus more. It is a good solid object oriented time-tested application framework and unlike Microsoft with its .NET framework, Apple "eats its own dogfood". It uses Cocoa extensively to build its applications (e.g., GarageBand, iPhoto, iCal, iChat, Mail, etc). I've been fairly happy with the toolset although I wish refactoring support was available in XCode (which is also at least partially built with Cocoa). Next step is to go into building a "real" application, stay tuned...

Tuesday, July 12, 2005

Airshow accident in Moose Jaw

My family and I attended the Saskatchewan Air Show in Moose Jaw, Saskatchewan on Sunday. We were treated to some spectacular aerobatic maneuvers. A couple of American F15s opened the show and then the SkyHawks, a Canadian Forces parachute team, took over with some great demonstrations. We were then treated to the Canadian CF-18 and the American A-10. Then there was a civilian act known as the "Masters of Disaster". The group consisted of three bi-planes (one jet assisted) and a jet powered truck. They each performed individually and were very impressive. Then in a finale all three planes got together for a mock dog fight.

But unfortunately on this day something went terribly wrong when two of the planes collided in mid air. Both pilots died. The entire crowd of 10-20,000 people were shocked. There was some initial confusion about what actually happened. Many thought the explosions were part of the show.

My wife and I discussed the incident with our kids who may be a bit too young to understand what they witnessed. We made sure that they understood the difference between the explosion they saw and the kinds of things they may see in a movie and that families lost fathers and brothers that day. Those men were experts in their business and knew the risks they were taking. I only wish that it would have ended like all the shows they had performed in the past...

Tuesday, June 28, 2005

Podcasting

Apple finally got onboard with podcasting by delivering a simple (and free) way to subscribe to podcasts via iTunes. Just go to the iTunes Music Store and select the podcasts that you're interested in, wait for the MP3 download, and start listening. The selection isn't huge at the moment but it does cover a wide variety. I subscribed to the "CBC Radio 3" podcast and the decidedly more adult "Dawn and Drew show". After you have the files, you can sync with your iPod and listen to them on the road and unlike radio you can skip, pause etc. Very cool. You can of course listen to podcasts with any MP3 player but Apple, in typical fashion, makes this really simple to use.

Friday, June 17, 2005

GIMP, BSD, Linux and Mac OS X

Let's start by talking about GIMP, the GNU Image Manipulation Program. I've used a few other graphics tools in the past including Adobe Photoshop (LE edition) and Paint Shop Pro and the height of awfulness, Windows'Paint brush. So I can say from this position of authority (not) that the GIMP is pretty good. It runs on Mac, Windows and Linux equally well. It supports layers, each with independent opacity values to dynamically composite an image. Text is treated as an object that can be easily changed. Bezier paths can be used for creating smooth paths and image selections. And I think the whole thing is scriptable (via Scheme) but I haven't gotten into that.

So the GIMP is pretty cool but what I recently discovered is that it's related to Mono... When I was messing around with Mono's implementation of WinForms (the C#.NET way to create Windows applications) I found myself using Fink to download and compile the source code for GNOME. Apparently Mono's WinForm implementation is tied to GTK+ and GNOME uses GTK+ as its base widget set which in turn is an offshoot of the GIMP project. (Starting to talk in circles here).

Now when I think about GNOME I think about Linux, but here I am running the GNOME desktop on my Mac. What's up with that? What exactly is Linux anyway? Well apparently what many people tend to call Linux (like a Red Hat distribution for example) isn't really just Linux. Linux is the kernel and the rest, the compilers, the bash shell, the command line applications, GIMP, and the GNOME desktop, are part of the GNU project. In fact, the GNU project was started in 1984 and Linus Torvalds didn't start work on Linux until 1991. The GNU project was working on a kernel too but Linus got there first. The Free Software Foundation even prefers people more accurately call it GNU/Linux with the GNU in front because they (quite accurately) are the major contributors.

So now I'm thinking well what the heck? How does BSD (Berkeley Software Distribution Unix), the base for Mac OS X, fit into all this. Well today's FreeBSD (from which OS X most heavily borrows), OpenBSD, and NetBSD distributions are descendants of the original AT&T Unix of 1970s. At some point in 1990s the BSD project attempted to free itself of AT&T copyright entanglements with replacements for all original AT&T Unix code. It was at this point that BSD came under legal scrutiny. It was under this legal ambiguity that Linux was created and prospered. In 1995 everything was squared away and BSD became truly free. And that's how we come to have two competing Unix-like open-source kernels. And it's probably because NeXT came before Linux that Mac OS X uses BSD.

Now if you throw out the kernel issue then I'm left with the impression that Mac OS X (sans Quartz, Cocoa, and all the other good Apple layers that sit on top) is more like GNU/Linux than I originally thought. Apple bundles a lot of the same GNU project stuff (like the compilers, the bash shell, the command line applications, etc). I'm even of the impression that because OpenStep ran on a host of other Operating Systems that if Apple were so inclined they could even put the Mac OS on top of Linux if they wanted. Ahhh Unix... I feel like such a newbie sometimes ;-)

Next time maybe I'll talk about all these crazy open source licenses: BSD, Apache, Copyleft/GPL, etc... Ahhh maybe not... ;-)

Thursday, June 16, 2005

.NET Disillusionment

Messing around with C# and ASP.NET has been pretty boring so far. Apparently my boss really meant:
do you want to do take over another developer's project which is really just the installation and configuration of the Microsoft Web Portal Starter Kit?
instead of:
how would you like to do some cool C# stuff for fun?
But as a diligent, "pragmatic" coder I familiarized myself with the code and data model (damn ugly), created a nant build script (which is almost exactly like Ant BTW), cleaned up the ASPX and CSS and checked the whole mess into CVS. Ho-hum.

So now that I've been using Visual Studio 2003 for awhile I have some not so nice thoughts about it. It has some okay graphical tools for working with XML and XSD but I'm not really thrilled with the junk HTML it spits out. It really should be creating XHTML and use CSS where possible. Even Nvu does that! And how about some integration to a source control tool other than VSS for crying out loud? And don't get me started on the code editor. Maybe I'm just accustomed to Eclipse now but I sure hope Visual Studio 2005 is a lot better than this (Anders thinks so).

And today Visual Studio decided to start hanging on me. All I'm trying to do is pin the toolbox panel. That's it! I can just hear all the MS-loving developers crying out "just reinstall!". And normally I might. But unlike an Eclipse installation which involves deleting a directory, downloading a new version and unzipping, I get the feeling that a VS/.NET installation is just a bit more involved and not likely to succeed.

Finally, my mono experiment came to a grinding halt. My Nant script required a bit of tweaking to get the application to compile (needed references to the core .NET assemblies for some reason) but it just won't run in XSP (the mono ASPX server). I keep getting a null pointer reference exception but without the ability to debug while running in the Mono runtime, I decided it's just not worth the effort. Maybe Java's not so bad afterall...

Monday, June 06, 2005

Mac on Intel

Well that one was a difficult rumour to believe. I've been pretty happy with my dual-processor 2GHz G5 since I bought it about 20 months ago. It's a well engineered machine with lots of memory headroom, a fast front-side bus, a decent graphics card, etc... and with Apple optimizing its OS for the past few years, things have even gotten faster than when I first bought my machine. So why switch?

Well apparently Jobs made the announcement that Apple will begin shipping Macs with Intel processors next year.

On the one hand I'm a bit disappointed that Apple will lose some of its distinctiveness. Will it just be a pretty box with the same guts as everyone else?

On the other hand, I'm happy that Apple will no longer have to try and prove that it's machines are as fast or faster than everybody else's. As long as it uses the latest and greatest from Intel, people can finally put that argument away (for the most part). Instead they'll have to focus on what counts, the user experience. That was my reason for buying Macs anyway.

Finally, as a developer, I'm very interested in being able to run Windows applications at full speed on a Mac once in awhile. Being able to do .NET development with MS tools if needed would give me the ultimate flexibility without sacrificing my ability to run the Mac OS and Mac applications for the majority of my computing needs... Maybe it's not such a bad thing... We'll just have to see how this whole thing works out.

Thursday, June 02, 2005

ASP.NET and Mono

I recently started on an ASP.NET C# application at work. But since I'm a Mac guy at home I didn't have IIS to play with. Fortunately The folks at the mono project have a little ASP.NET web server called XSP. Unfortunately it doesn't come in the Mono distribution but with a simple download (and a make) I'm in business. It runs and the sample pages seem to work. I have no idea how robust it is nor how compliant it is but for now I'm happy that it just works!

Tuesday, May 31, 2005

Computers, Robotics and Foosball

What a fantastic combination. I'm surprised I didn't try to come up with that one myself ;-) Apparently I'm too late, the University of Freiburg's (German city of about 200,000) Computer Science Department has developed KiRo, the table soccer robot:
KiRo is a completely autonomous table soccer playing robot: using a camera it perceives the playing field and, dependend upon the current game situation, it decides how the rods under its control should be moved.
Even better is that they commercialized it under the name StarKick. Now if you have a broadband connection go check out some video of what it's like to go up against a robotic foosball opponent. ;-)

Thursday, May 26, 2005

Quicktime 7, H.264 and HDTV

Although H.264 was originally going to be one of those gotta-have-it features offered in the latest version of Mac OS X Tiger, Apple decided to give it away with Quicktime 7. Currently it's only available for Macs and not Windows ("Quicktime 7 for Windows Coming Soon") so you need a Mac to see it but it's worth checking out.

I still have an antenna in my attic for viewing over-the-air broadcasts (a.k.a., peasant-vision) so I'll be the first to admit that I'm a bit quality-picture challenged. But expectations aside, when I downloaded a couple of samples from Apple's HD Gallery I was very very impressed! The 1080p version of the Batman Begins trailer is just huge! My crappy VGA monitor can't even display that resolution (1920 x 816)!

So what's next from Apple? Well it's difficult (if not impossible) to predict. Apple was late to the whole MP3 thing when they introduced iTunes. They weren't the first with a portable hard drive based MP3 player, the iPod, and they weren't the first with an online music store either but look where they are now. They dominate. Microsoft has a Windows XP Media Center and both they and Sony with their next generation game boxes are vying for a spot in the living room. But Apple has the technology, the ingenuity and the ability to make products that resonate with consumers so I'd expect to see something from them that not only embraces the Mac and iLife (as digital hub) but goes beyond to make digital video simple and approachable to the masses.

[Update: I found this blog where the author goes into quite abit more depth. He sounds way more upbeat than me!]

Tweaking log4j

Despite the inclusion of logging APIs into the JDK since 1.4, I still continue to use log4j for my logging needs. Generally I'll also use the commons logging API on top of log4j so that if I should ever change my mind and want to use the "built-in" logging facilities it will be easy.

My recent foray into production deployment highlighted one of the problems with my standard configuation. I have the typical log4j.properties file in the root of my source directory, and log4j is quite happy to find it there. The problem is that it eventually gets buried inside a JAR (Java ARchive) which is inside a WAR (Web Archive) when I build my application and therefore it's not very easy to change the logging parameters once my application is deployed. Specifically, the location of the generated log files is now essentially hard coded, which sucks for deployment.

Fortunately there's a way out of this. If you specify the location of a log4j.properties file in a Java system property called log4j.configuration, log4j will use that file instead of the one buried in your classpath. The only trick is to specify the location as a URL:

java -Dlog4j.configuration=file:/e:/log4j.properties ...

If you're using a Windows Service for starting an instance of Tomcat you can add a system property to the registry value found in HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Procrun 2.0/Node1/Paramaeters/Java/Options where Node1 in my example is the name of your instance of Tomcat.

Secondly, if you're want to define the location relative to a Tomcat installation you can use a dynamic location like this within your log4j.properties file:

log4j.rootLogger=error, R

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.base}/logs/MyApp.log
log4j.appender.R.MaxFileSize=200KB
log4j.appender.R.MaxBackupIndex=2
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{ISO8601}] %5p (%F:%L) - %m%n

Notice the ${catalina.base} expression. The nice thing about this in a clustered environment like I described yesterday is that you can use the same log4j.properties file for all the instances of Tomcat and can change the configuration for all of them all at once.

Wednesday, May 25, 2005

Tomcat and IIS

I've been busy lately deploying my latest Java web application to production. It's been a bit of an adventure since I don't usually get to play the deployer role. Fortunately I already had my Ant script building the WAR (Web ARchive) file so I was only working on deploying to Tomcat 5.5.9. The twist is that I was deploying to four instances of Tomcat on two physical Windows 2003 servers fronted by the latest version of IIS.

The only reason IIS is involved at all is so that I could use the JK 1.2 Tomcat Connector to do the load balancing. This connector works as an ISAPI Filter and intercepts requests to my appliction (based on the URI) and forwards them on to an instance of Tomcat running my application. The connector does a weighted round robin load balancing and ensures that a request that is tied to a particular session on a particular Tomcat instance (from a previous request) is directed back to that same Tomcat instance.

But perhaps I'm a bit ahead of myself. Let's back up to the Tomcat installations. The first thing I wanted to accomplish was the sharing of the Tomcat JAR files among the various instances of Tomcat. By doing that, I know all Tomcat instances are running the same version and upgradable in one shot. The steps were:
  1. Unzip jakarta-tomcat-5.5.9.zip
  2. Rename jakarta-tomcat-5.5.9 to tomcat for simpler upgrading in the future (if only Windows had symbolic links)
  3. Create a directory called tomcat-cluster-node1 that looks something like this (the files in the subdirectories were copied from the standard Tomcat installation):


/tomcat (renamed from jakarta-tomcat-5.5.9)
/tomcat-cluster-node1 (The subirectories' files are copied from the tomcat
installation.)
/bin (contains service.bat)
/conf (contains catalina.policy, catalina.properties, context.xml,
server.xml, tomcat-users.xml, web.xml)
/Catalina
/localhost (contains manager.xml, host-manager.xml, myapp.xml)
/logs (empty)
/temp (empty)
/webapps (empty)
/work (empty)

Because this installation is on a Windows server I decided to follow the adage "When in Rome, do as the Romans do" and make my Tomcat instances run as Windows Services. Fortunately Tomcat is ready to go with a Tomcat5.exe and a batch script to create the registry entries call Service.bat. The only changes I had to make to the batch file were a few lines at the top to set some environment variables:

set CATALINA_BASE=E:\tomcat-cluster-node1
set CATALINA_HOME=E:\tomcat
set JAVA_HOME=E:\jdk1.5.0_03

then I ran "Service.bat install Node1" and I now have a service that I can easily start and stop. You may want to change the service to "Automatic" to ensure that it gets restarted in the event of a server restart.

Now back to the Tomcat connector installation. I like keeping the redirector stuff separate from the tomcat installation so I created a directory called /tomcat-iis-connector that contains the following files:

isapi_redirect.dll (downloaded from the jakarta site)
isapi_redirect.reg (see below)
uriworkermap.properties (start with a copy from the tomcat/conf directory)
workers.properties (ditto)

The reg file contains some registry entries that the DLL uses at runtime to find your configuration information. Mine looks like this:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\1.0]
"extension_uri"="/jakarta/isapi_redirect.dll"
"log_file"="e:\\tomcat-cluster-node1\\logs\\isapi.log"
"log_level"="error"
"worker_file"="e:\\tomcat-iis-connector\\workers.properties"
"worker_mount_file"="e:\\tomcat-iis-connector\\uriworkermap.properties"

Now you have to actually tell IIS about the redirector DLL (notice the /jakarta/ prefix in the extension_uri entry in the reg file. This becomes important in a moment)
  1. Open IIS Manager and create a new Web Site.
  2. Create a virtual directory called "jakarta". This name must be the same as the prefix from the extension_uri value in the registry, and it must be executable.
  3. Go to the "ISAPI Filters" tab of your website's properties dialog and add a filter that points to the isapi_redirect.dll
  4. In the "Web Sites" properties dialog's Service tab select the "Run WWW service in IIS5.0 isolation mode" checkbox.
  5. Disable session state for your website (Properties dialog->Home Directory tab-> Configuration...->Options tab). Just let Tomcat handle your session timeouts.

Now all you have to do is configure your workers.properties file. Mine looks like this:

workers.tomcat_home=E:\tomcat
workers.java_home=E:\jdk1.5.0_03

ps=
worker.node1.port=8009
worker.node1.host=localhost
worker.node1.type=ajp13
worker.node1.cachesize=10
worker.node1.cache_timeout=600
worker.node1.socket_keepalive=1
worker.node1.recycle_timeout=300

worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=node1
worker.loadbalancer.sticky_session=1

worker.list=loadbalancer

And then in the cluster-tomcat-node1/conf/server.xml make sure you identify the server with the same name you used when defining the worker in workers.properties, in this case "node1". Without this the "sticky sessions" won't work.

<engine name="Catalina" defaulthost="localhost" jvmroute="node1">

At this point I've only described the installation of a single Tomcat instance, but in reality I have four tomcat instances. So you can imagine more tomcat-cluster-node directories and a few more entries in workers.properties and the addition of those worker names to worker.loadbalancer.balanced_workers:

worker.loadbalancer.balanced_workers=node1, node2, node3, node4

Next you must define the URIs that should get redirected from IIS to Tomcat in the uriworkermap.properties file. Mine looks like this (of course you'll need to change the value of "mycontext" to the context of your app:

/mycontext/*.jsp=loadbalancer
/mycontext/*.do=loadbalancer
/mycontext/*.exe=loadbalancer
/mycontext/*.jpg=loadbalancer
/mycontext/*.gif=loadbalancer
/mycontext/*.png=loadbalancer
/mycontext/*.css=loadbalancer
/mycontext/*.js=loadbalancer
/mycontext/*.jpeg=loadbalancer
/mycontext/*=loadbalancer

Normally, I would like IIS to serve all my static content but I use struts tags to specify the location of images and the JSTL c:url tag to dynamically generate URLs. These tags rewrite the URL and not only include the name of the context (which is configurable at deployment time) but also include the jsessionid in the URL when not using cookies. Unfortunately IIS can't figure out what to do with the jsessionid so your pages come back without CSS or images. Not only do they look pretty awful but if you use js files some functionality may not even work. So I just map everything to Tomcat. On the plus side, deployment is simpler with the single WAR file.

Finally restart IIS and hope everything works! :-)

Monday, May 09, 2005

Updating my Resumé

I recently decided to update my resumé and decided that instead of using a proprietary document format that I would use HTML. If you think about it, a resumé is a great document for HTML. There's no need for an index, foot notes or a table of contents and the elements that remain aren't very complicated either. You have a couple levels of headers, some bulleted lists, and maybe a paragraph or two.

My initial step was to take my RTF document and dump it in a WYSIWYG editor. I used Nvu. I kept everything plain vanilla (no fancy fonts, font styles or colours) and basically edited away. When I was done, I had a factually correct document. The HTML was pristine and wasn't mucked up with a bunch of tags describing appearance. But on the other hand it was an incredibly boring looking resumé. No one was going to give me any extra marks for style.

So I decided I'd spice things up with some CSS. I ditched the WYSIWYG editor and broke out my favourite code editor, jEdit. The first step was to make everything XHTML compliant. I put in the correct doctype, made everything lowercase, closed every tag, and put quotes around all attributes. Then once that was passing the W3C XHTML validator I added a style section to the header and started editing. (Normally I'd use an external CSS and link to it from my HTML but I figured I'd probably be e-mailing my resumé to people and didn't want them to have to worry about multiple files)

The one thing that I wanted to avoid was adding structure to my document just so that I could lay things out (i.e., I didn't want to add tables all over the place just for the sake of layout). Secondly, I wanted the document to still render properly if someone decided to turn off stylesheets entirely within their browser. So I introduced several div elements as containers so that I could style and position blocks of content. My document is pretty hierarchical so this was actually pretty simple and wasn't really breaking my rule about adding tags for layout. As I worked I needed to read a bit more about CSS topics I had only briefly touched on in the past (specifically, float, relative and absolute positioning). I also had to decide on some colours and fonts but I just used some of my favourite sites as templates for those choices.

In the end I have an XHTML/CSS standards-compliant document that looks good in Firefox, Mozilla, Camino, Internet Explorer, and Safari. The content and the visual appearance code is nicely separated, even if they are in the same document, and it serves as a nice little showcase for my appreciation for standards and my ability to apply them to a web application.

I got my first callback. Was it the content or the styling? Maybe a bit of both. ;-)

[Update: I forgot to mention that the Firefox "Web Developer" extension is a great tool for graphically viewing outlines around the structural element of your HTML document and for seeing what would happen if CSS, graphics, or other browser functionality were disabled]