Archive for the ‘java’ Category

I’d forgotten what a lame pile J2EE is

Sunday, October 5th, 2008

I’d kind of sworn off doing Java a few years ago but a little contract fell into my lap that seemed like it would be some quick cash for not too much work. I already had a lot of code in the can that would help me do it quickly. Also, I still have IntelliJ 6, which can make Java almost tolerable.

Unfortunately, part of the system required a servlet to handle http requests (using http as an RPC mechanism). I’ve used Jetty in the past with good results so I downloaded it. Despite the existence of a “plugin” for IDEA to work with it, the debugger never worked.

So I moved on to Tomcat. I finally got IDEA configured to use Tomcat, the debugger worked, but the servlet was ignored every time without any kind of error message being logged. Did it fail to link or something (it used a lot of external libs I had to bring in). No clue. I simplified the servlet to just printing “Hi there” and still it refused to load.

This resulted in a refamiliarization with web.xml files and all the rest of it. In disgust I switched back to Jetty. Jetty at least logged the errors to the console and I fixed all the link issues, but still no debug. Back to Tomcat but it still wouldn’t load my servlet at the url I wanted. Eventually, I found the invoker servlet settings, turned that on, and the servlet began to work.

The bottom line is that the entire J2EE architecture, the servlet containers, the zillion xml files specifying garbage I never want to change anyhow, all of it is MUCH TOO FRIGGIN COMPLICATED FOR WHAT IT DOES. Too many descriptors. Too much config. Too much cargo cult xml.

Compare to PHP where I just drop a file in a folder under document root and I’m good to go. Or rails, which is pretty much the same deal – just putting the file in the folder ought to be all that’s required to make the thing work.

I think this will be my last foray into Java hell. At least for a few years until I forget how stupid it all is again.

Software Design Tip: Minimize Number of Languages

Tuesday, April 1st, 2008

I was recently asked about taking over support for an existing application. I’ll leave out what it does – suffice it to say it is web based, has a simple 3-5 page UI for the public to buy something, and about a 15-20 page set of back end interfaces for trained customer service and admin people to use. So less than 30 screens overall mKay?

The application was said to be written in Java. I know Java – I don’t like it, but I know it. If its small, I could be persuaded to pick up the maintenance.

However, I got a source drop and I was totally appalled. First, it suffers from the usual Java framework-itus.

Its J2EE – so we got Jetty container. They used Hibernate – so we have generated Java code based on some XML schema files. There’s also a mysql database – which duplicates the information in the Hibernate XML schema files. It uses cocoon – cocoon make use of xml and xsl to define navigation and transformations. There is also reporting that uses xsl. Workflows use flow – more xml only they used the Javascript extension so the workflows are actually defined using server side javascript.

Got all that? We have Spring, Coccon, Flow for Javascript (flowscript), Hibernate, Jetty, Javascript, Html, CSS, SQL, XSL and god knows how many dozens of distinct flavors of XML. For a 25 page web app. Wait, did you notice I didn’t mention Java? There is Java – the Hibernate generated classes are used – but indirectly – they may as well not exist at all since all the application code is some fractured XML or Javascript fragment stashed who knows where.

It seems we’ve lost track of something here. “Locality of Reference” In general, all the stuff that deals with the product selection page ought to be visible by looking into the file representing that page, then maybe drilling into components. The problem here is that, everytime I have to drill down, I have to switch languages. And context switches are bad for programmer productivity – mKay?

I’ve turned down the job. I don’t have time to learn all that junk for this little app. The client needs a new installation – for 25 pages that do mostly CRUD to mysql. If I do it, I’m thinking plain old PHP with an ORM. If I can find an ORM for PHP.

So far I’ve looked at Doctrine (not yet ready for production but it looks cool), Propel – and some others. The really off-putting bit is their slavish insistence on creating the xml mapping file – just like Hibernate. Of course, I have an existing database. The XML file they want is in the db. It just isn’t XML. Still, all the information is available for query – so why are they bothering me with this junk? Read the damn schema and make me some classes. I’ll eliminate the many to many mappings by hand. Sheesh. No wonder there’s a software crisis.

Hey framework people, stop making me write monkey code – figure out how to eliminate extra work – not make it. One meta model is enough.

Got Class?

Tuesday, October 31st, 2006

In Object Oriented languages, the class is the definition of a kind of object. Classes are arranged in tree-like hierachies with the roots of the tree being very general and the leaves being most specific. So a dessert is a kind of food, and cake is a kind of dessert. Because the class serves as the definition of an object, it makes sense that objects are created by using the class as a template. In other words, classes are used to create objects of the class’s type.

All of the languages discussed so far, C++, Java, Smalltalk, and Objective C have the notion of a class. What is different is how the languages represent the class itself.

C++ has no runtime representation of a class at all. Instead, all class information is soaked up by the compiler and represented using standard functions and globals with the class name prepended to their “local” names. The way a programmer designates a function as belonging to a class is to declare it within the class’s declaration using the very overworked keyword ’static’.

class CPlusPlusClass : public BaseObject
{
public:
static void classMember(); // declare the function

}

void CPlusPlusClass::classMember() {…} // define the function

CPlusPlusClass.classMember(); // really just a long name for a global function

Ditto for class variables. There’s no such thing in C++ really. Instead the language fakes it by letting you declare the variable in the class declaration’s namespace and in the end what you’ve got is a global with a very long name. Since there’s no class object, there’s no “this” variable and no way to do anything the least bit object oriented in class methods without explicitly naming super classes.

There’s also no built-in way to abstract object creation. When one wishes to create an object in C++, one uses the ‘new’ operator in conjunction with the class name, which coincidentally is also the required name of the initialization function. So in C++ we write:

BaseObject *c = new CPlusPlusClass();
Notice that here – at the moment of object creation, it is necessary to reveal the actual type of the object. If one desires a more abstract method of instance creation, it is necessary to adopt a factory idiom. Of course, converting to a factory creation mechanism from the use of operator new requires extensive modification of code, similar to the extensive work required to handle a new kind of exception.

Smalltalk takes the opposite extreme. Classes are represented as regular objects and are arranged into an inheritance hierarchy. The special variable “self” refers to the class object itself and ’super’ refers to the object that represents the classes superclass. Smalltalk class methods exhibit full polymorphism and class variables are made available to class methods and instance methods in the class’s instances. The Smalltalk class takes responsibility for instance creation and is thus a factory by default.

For instance, in the Squeak implementation, ImageReadWriter is an abstract class for reading and writing image files. Concrete subclasses exist for JPEG, GIF, PNG and so forth. The abstract base class makes use of class hierarchy navigation to find the correct subclass to render the image data. It looks something like this (error handling omitted):

“Find the first subclass that claims to be able to understand the binary stream’s data”

readerClass := self withAllSubclasses detect: [:subclass | binaryStream reset. (subclass new on: binaryStream) understandsImageFormat].

“Instantiate a reader from the class”
reader := readerClass new on: (binaryStream reset).

“Return the image from the reader”
^reader nextImage.

The beauty of this approach is that one can always write a new subclass of ImageReadWriter for a new image format and the new format is instantly supported without having to deal with registries or factory idioms.

Techniques like this demonstrate the power of using the object paradigm to represent classes.

Objective C uses a similar approach to Smalltalk with a couple of odd constraints. Objective C class objects lack support for class member variables. Instead one fakes it with static (as in C variables with internal linkage) variables. Also, Objective C performs lazy loading of libraries which means that not all subclasses are necessarily present at any given time. So the subclasses trick is a little hard to perform.

On the other hand, Objective C uses the same object creation mechanism as Smalltalk. So its still possible that the actual class of the object is not the same as the class that created it for you. Thus, the power of using objects to represent classes is mostly preserved.

Java’s approach is closer to C++ than to Smalltalk. While Java has ‘objects’ of type java.lang.Class for representing classes, these ‘objects’ have more in common with C structs than with objects in any other sense. Object creation is not performed by the class. Rather Java slavishly copies C++’s use of operator ‘new’.

Java also makes use of a ’static’ keyword to denote ‘class methods’. But these ‘methods’ are actually nothing but functions with long names. In fact, its not possible to do anything polymorphic in a class method. There isn’t even a way to get ahold of the class object representing the class.

public class A
{
// something that doesn’t work – no ‘this’
static void printClassName1() { System.out.println(”"+this.class); }

// this doesn’t work either
static void printClassName2() { System.out.println(”"+getClass()); }

// this does – but in subclasses it will be wrong
static void printClassName3() { System.out.println(”"+A.class); }
}

So crippling is the decision to not provide proper class objects, that the Enterprise Java Bean designers found it necessary to simulate class objects with the notion of “Home” objects. The “Home” object is intended to provide the ability to find existing objects or create new ones for a given class. This is definitely behavior that would ordinarily be put into a class object.

If we had one.

I Love You – Now Change

Monday, October 2nd, 2006

Which company would you prefer to invest in?

Company A:

“Our company is a dynamic organization with the agility to quickly adapt to new market conditions.”or

Company B:

“Our company is stable, well structured, and organized. What we are doing now is a perfect basis for everything we will do in the future.”(Sounds a little like the Bush administration)

The dynamic organization that can change quickly is going to be more successful than a static organization that is set in its ways.

So how come the software industry pundits continue to try to push static programming systems over dynamic ones when dynamic systems are generally more successful? Its senseless.

In C++ and Java, the assumption is that the superclass designer knows best. Whatever interface the original developer has exposed is expected to be the perfect and complete interface for all time. There is no way to extend an existing interface without owning the source code to it.

The implementation, it is recognized, might not be exactly correct in all cases, so the implementation is left open to extension via the one mechanism made available – subclassing (maybe – Java actually allows the most arrogant developers to forbid subclassing via the ‘final’ keyword).

The problem with leaving only subclassing is that subclassing, by itself only provides for extension of the system, not for modification. Fans of Robert C Martin or Bertrand Meyer might recognize this as The Open Closed Principle. Sadly, The Open Closed Principle is only works if you happen to work for a static company like Company B.

The harsh reality is that organizations are organic – they evolve and grow to adapt to new environment conditions. Failure to evolve is death. How can you modify your organization if the software that runs your organization is closed to modification by design? Worse, the underlying tools and technology on which your software is built actually work to enforce The Open Close Principle.

So how else to evolve your system? Objective C has a construct called a Method Category or more commonly just “category”. A category is a collection of methods for a class that may be loaded dynamically – or not. These are collections of additional methods to be added to existing classes. These additions may be made part of the organizations core software assets, or they can be application specific extensions that are too specialized for general consumption.

For instance, a web services application may find it convenient to add some methods to the string class for parsing up web requests, but the billing system doesn’t need this category of methods and so doesn’t bother to load it.

Categories can also make adapting an existing class to a new protocol easy. Not having a number of separate adaptor classes all over the place keeps the number of classes low and the conceptual size of the application architecture smaller.

Finally, categories can allow the user of a class to replace a buggy or inappropriately implemented method with a new implementation without having the source code.

Another useful tool is the ability to replace one class with another. The Objective C tool for this is known as “posing”. One writes a subclass of the original class and then says

[NewClass poseAs: [OldClass class]];

Now saying [OldClass new] actually constructs an instance of NewClass. This can be handy for sneaking superclasses into the class hierarchy and also for debugging around code you don’t own.

Using these techniques, along with message forwarding and delegation, subclassing takes a back seat to application assembly and drops from the most used tool to the mechanism of last resort. After all, its much better to simply arrange the classes you already have into the right structure than to create entirely new code with entirely new bugs.

Smalltalk has similar mechanisms and results in similar designs. Method categories exist and can be loaded as packages. Posing is done quite easily by replacing a class in the Smalltalk class dictionary with another class and executing a become: on all of the old classes instances. Its easy to insert new classes anywhere in the hierarchy and all of the code is easily accessible and modifiable. Subclassing in Smalltalk application development is a relatively rare event.

Of course, if you’re sure you know what you’re doing – perhaps Java and C++ are the right languages. If you’re sure, that is.

Relax, It’s Nothing!

Tuesday, September 12th, 2006

Originally published August, 14, 2001

What’s the most frequently seen message produced by Java programs?

Its got to be the NullPointerException. In efforts to avoid this dreaded message, programmers have adopted an idiom that looks something like:

if(object != null) object.doSomething();

Which basically means – only send the message if there’s something there to receive it. Thats how you keep the exception from being thrown. The idiom must be burdensome as NullPointerExceptions continue to pop up at unexpected times and the fix is invariably to put this sort of test on the line from which the exception is raised.

This is an idiom adapted from C and later C++ where null is memory address zero by convention. Since important chunks of the operating system live down in that memory region, modern operating systems protect that region from fiddling and view trying to reference anything off of memory address zero as a likely programmer error. So its not allowed in the name of protecting the operating system.

C and C++ programmers, in efforts to get their programs to live long enough to let the program report whats going on, check pointers to make sure that they aren’t null before using them. This is because the penalty for using a null pointer in these environments is death.

These days, applications are developed using higher level languages, like Java and Smalltalk. These have no pointers at all. Instead we have object references and its not possible for the programmer to endanger the operating system by messaging a null object reference. (Objective C uses pointers as object references, but the programmer never directly dereferences them – its all done by the Objective C runtime).

So now, released from the need to steer clear of the operating system’s defense mechanisms, we can take a step back and think about what sending a message to nothing means.

Shouting across the street to someone who isn’t there may make you feel silly – but nothing really happens. Same for sending a letter to a non-existent address. If there’s no return address, the post office will eventually give up and toss it. Nothing too terrible there. There’s simply no one to receive the message.

So why does Java take the position that messaging null is so great a catastrophe that the programmer must be burdened with handling an exception? Especially when most of the time, the programmer’s method of avoiding the unwanted exception is to add a test for null before sending the message. In other words, the programmer will fix it with:

if(object != null) object.doSomething();

which is a just a way of saying “if there’s noone to receive the message – do nothing”. Worse, the programmer has to add this check to every single location in the code that tries to make use of the object reference.

This is the same nuisance condition we identified with typing of object references. Recall that the dynamic languages provided a means of handling this condition in a central location via the doesNotUnderstand, while the Java version required the programmer to handle it at each call site.

A similar situation exists with the use of null in Java. It must be checked for and handled at each call site. There must be a better way.

On the dynamic side of the world things are simpler. In Smalltalk, null (actually, in Smalltalk its referred to as ‘nil’) is a global singleton object of the class UndefinedObject. It implements hardly any messages and so messaging nil results in nil receiving doesNotUnderstand. The default behavior of doesNotUnderstand in nil is to halt the program and throw a debugger around it. Many deployed systems change this behavior on deployment to log the behavior and stack trace, or to simply return nil.

In Objective C, messaging nil results in nil being returned by default. This behavior can be changed in the runtime by adding a hook function to the runtime that could do logging, or raise an exception.

In either case, the consequences of messaging nil are under the control of the programmer and can range from totally benign to fatal, depending on the developer’s preference and the application domain. Experience with developing applications in this environment has shown that messaging nil is nearly always harmless, and not having to place tests for nil before every message send results in smaller, cleaner, and easier to understand code.

Plus, the applications don’t crash nearly as often. This is yet another example of how a feature in Java that is intended to improve software reliability, actually undermines it.

Blanchard’s Law

Tuesday, September 5th, 2006

When in the course of developing software, the growing feeling that code generation would be a great idea actually means that the environment or language in which you are working isn’t powerful enough for the task at hand.

Years ago I was a C++ fan. It was the first language I encountered that had user definable classes and objects and we used it to build Motif GUI’s that fronted legacy character based systems. After awhile we found that the amount of boilerplate code we were writing was becoming an impediment to change and someone came up with the idea of specifying a number of aspects of the system as models and generating the code from the model.

As I was the lead of the business domain model, this approach was particularly attractive to me as we had dozens of classes that were all implemented using the same idioms, but whose set of attributes changed in minor ways with some frequency. Furthermore, we weren’t actually implementing the business logic within the classes as they were being mapped into an inference engine that provided enforcement of cross object validation rules. So code generation seemed like a great labor saving solution.

Problems occurred fairly soon after with generated code being occasionally hand modified by some maintenance programmer and changes being lost down the road. The generated code had size impacts as well. It’s easy to generate a program too large to compile and run on your current hardware. Our compile times for the system went from 2 to over 30 hours – a problem we solved by parallelizing the build process across a fleet of machines. The project was ultimately cancelled and we didn’t have a chance to see if the giant could fly. But I was left with some lingering doubts as to the efficacy of generating code.

Later on I encountered CORBA. CORBA seemed pretty cool – like Remote Procedure Calls (RPC) but a little easier to use. Interface Definition Language (IDL) looked just like C++ with a couple minor tweaks. You generated your stubs, filled in your code, and you were off. At least until you wanted to expand or change an interface. Maintaining all the generated source files got cumbersome and once again added considerably to the build times.

Java RMI was the same kind of thing – define Java interfaces (instead of IDL) and a whole bunch of marshalling code gets generated. But you end up with an awful lot of code in the end.

A bit later in my career, I encountered dynamic languages. I got a glimpse of HP’s DST (Distributed Smalltalk) which implemented CORBA using a single proxy object that could stand in for any object. NextStep’s Portable Distributed Objects (PDO) was a similar take on this theme. These smart proxies were made possible by the dynamic typing and message sending nature of these languages. Static languages were stuck with code generation because they had to satisfy the compiler’s type constraints.

Consequently, I view the growing trend towards code generation with some horror. No wonder our systems are insanely resource intensive while delivering very little value. After a decade and a half developing software, I have yet to encounter a situation where code generation is a good idea in the end. The answer isn’t to automate your inefficiency. If this is not possible, then it is time to evaluate different tools and approaches.

Closures for Java?

Thursday, August 24th, 2006

Gilad Bracha of Strongtalk fame has a post talking about the proposed introduction of closures to Java.

I consider Java to be so broken at this point that I view it as “lipstick for a pig” and agree with Bracha’s position that its unfortunate that they were delayed to the point that all the common idioms that might have been done with closures have been established using less elegant techniques. In other words, I think its too late.

Its a chain of constraints produced by a couple of root decisions. First was the insistence on mandatory manifest typing. The Strongtalk system and Objective C language both support optional manifest typing. Objective C does it to provide compile time warnings for programmers to help them catch mistakes. Strongtalk actually uses the type information to call type optimized versions of operations. This technique is part of the foundation of the HotSpot JVM.

The second design problem is Java’s choice of C style function calling semantics vs Smalltalk’s message sending. Message sending is the more flexible and uniform technique. You have an entity at some distance, you send it a message asking it to do something. If it knows what you are asking, it does it and replies with your result. If it doesn’t know what to do, some default action occurs. This is how network available services perform and is also how Smalltalk objects interact.

Java, C++, C take the position that the compiler has assured that the receiver is of a type that MUST understand the message you are sending. They do this by constraining the messages you are allowed to send at compile time. This is meant to prevent errors but it also needlessly limits program flexibility and forces the developer to deal with a second interaction model – one for network resources and another for local ones. The Smalltalker has only one interaction model to contend with.

This is important and profound. In fact, Alan Kay, the man who coined the term “Object Oriented” laments the choice of words saying: “Object-oriented programming is about messages, not the objects. We worry about the objects, but it’s the messages that matter.”

But Java is function-call oriented. Consequently, the closures end up looking like local function declarations – which means they are awkward and ugly to declare and use inline and they are littered with extraneous type information. And they will most likely not catch on.

Java is what it is. Like a mutant frog it is trying to make it to land, asymptotically approaching Smalltalk, a language first released in 1980, and yet, its clear that it can’t get there and I suspect it will die trying. At least, I hope it will.

Function Calling vs Message Sending

Thursday, August 24th, 2006

“What happens if your reference refers to a different type of object than you expect?”

Its probably a programming error.

Or not.

In C++, because of the way vtable dispatching works, the program will either crash (hopefully) or the wrong member function will be called. Either way – the end result is probably fatal.

Java is slightly better. In order to call a member function, the java compiler checks to make sure that the function is defined in one of the interfaces implemented by the type of the object reference. The problem arises when the object reference has been widened to a more general type that does not define the desired member function.

How can this happen?

public class A extends Object { public void anAThing() {} … }

A myA = new A(); // make an A
someList.add(myA); // put it in a list … someList.get(0).anAThing; // error – List.get(int) returns Object.

so we have to downcast the Object reference returned by someList.get() to an A reference

((A)someList.get(0)).anAThing(); // Might be OK if someList has an A

Casting is completely type unsafe. Although in Java the result of incorrect casting is an exception. So we could write:

try { ((A)someList.get(0)).anAThing(); }
catch(ClassCastException ex) true

which allows us to handle the casting error and continue. This is a huge step up from the C++ behavior of crashing in that it allows the programmer some control over what to do if the cast is wrong. If we desire a more conventional means of writing this, it is possible to use the instanceof operator and do the check before the cast.

if(someList.get(0) instanceof A) ((A)someList.get(0)).anAThing();

which is pretty much the same thing. Of course, this forces programmers to clutter their code with all sorts of tests or try/catch blocks. It seems to me that getting away from that sort of thing was precisely the reason everybody wanted to switch to object oriented programming in the first place. Polymorphism replaced an awful lot of if ladders and switch statements and here we are putting them back in to work around a runtime system that throws an exception if we guess incorrectly about the type of an object.

Not to mention the idea that its quite possible to have this situation:

public class A extends Object { public void doAThing(); …}
public class B extends Object { public void doAThing(); …}

Object myB = new B();
((B)myB).doAThing(); // fine
((A)myB).doAThing(); // error – object is not an A!

which seems just silly. We have an object that we are pretty sure implements the operation doAThing – but that’s not good enough. We have to know exactly which interface this particular object implements in order to call that method. Thus, type defines protocol in the statically typed world.

The problem is that such an arrangement assumes the existence of what Bart Kosko calls crisp sets and hierarchies. The world isn’t nearly so neat. Its fuzzy. B might well be capable of performing some of A’s operations and in some (but perhaps not all) circumstances, B might be an excellent stand-in for an A. Its a more accurate model. To quote Kosko again. “fuzz up – precision up”.

OK, so what about the dynamically typed languages? How are they better? Assume we have the same classes A and B derived from Object and each implements doAThing.

| anA |

anA := A new.
anA doAThing.

anA := B new.
anA doAThing.

anA := ‘this is a string’.
anA doAThing.

This all works except for the last line when anA refers to a String rather than an instance of A or B. String definitely doesn’t implement doAThing. So what happens?

First, it helps to know that the runtime systems for Smalltalk and Objective C are “message sending” rather than “function calling”. When the programmer tries to send a message to an object that doesn’t respond to that message, the runtime packages the message up as an object and calls a catch-all message instead. In Smalltalk this is usually called doesNotUnderstand: message.

In Objective C, a special message called forwardInvocation: is called to give the programmer a chance to send the message to some other object such as a delegate. The default implementation of forwardInvocation: doesn’t do any forwarding. Instead it just calls another method doesNotRespondToSelector: which raises an exception.

The programmer may choose to respond to these messages in a class specific way – polymorphically, by overriding forwardInvocation: or doesNotUnderstand:

Doing this moves the error handling to a central location rather than forcing the programmer to scatter it throughout the code at the call locations. The end result is cleaner, smaller code.

Plus there’s a bonus. Being able to forward messages provides a clean mechanism for building chain of command patterns and allows an object to be “decorated” with new behaviors dynamically.

Its also easy to do distributed computing by having the forwardInvocation method perform remote procedure calls over the network without the need to do clumsy code generation of proxies and stubs common in C, CORBA, and Java RMI programs. A single proxy class can stand in for any kind of object.

The doesNotUnderstand: message can also provide a trigger for database fetching and object faulting. When a message is sent to a simple database query object that implements almost no messages, doesNotUnderstand: is invoked, the database query is executed, and the object replaced with the results of the fetch. The message is then delivered to the newly fetched object. Such faulting mechanisms can simplify programming and virtually eliminate the need for application programmers to directly interact with a database API.

These extra capabilities are nearly impossible to implement in the statically typed environments and this is clearly a case when the dynamically typed environment yields simpler application code (we don’t have all those try/catch blocks or instanceof tests). Simpler application code means greater reliability with reduced programmer effort. This all translates to faster development times and lower costs.

Java Swing returns

Tuesday, June 20th, 2006

Sun presented all day yesterday at work. I attended the session on desktop Java. So far as I can tell, the key changes are better windows integration (don’t care), an effort to get vendors to preload the JRE on both windows and linux, and a wizzy new demo app that makes heavy use of J2D to look a bit like a Mac OS X widget with lots of translucency, fades, throbs, and visual effects lifted right off of OS X.

I will say that the demo app was pretty, but having written swing and J2D in the past, I know how much work went into that app and I shudder at the level of effort it would take the average developer to replicate it. Most of the UI elements are not in the standard Swing package and are custom widgets making use of Java 2D graphics. Those that are swing widgets have been subclassed and had their rendering code replaced with some fancy hollywood quality graphics.

The NetBeans GUI builder (Matisse I think) was also shown. It looks so-so and it uses code generation which naturally makes it nearly useless.

The Q&A was also rather brutal with one attendee asking “why does it take 10 pages of code to replicate what I can do in six lines of HTML?” Their answer – they are working on a new app framework to hide the complexity of the Swing framework. Hello? Why isn’t the first framework simpler? Abstracting a framework behind a framework is excessive. No wonder the thing crawls at times.

My question/comment was to suggest that they bail on code generation and focus on the real pain point. Intelligent default sizes for widgets. For example, I constructed a standard outlook-style browser with a vertical split pane that has a scrolling list on the left and content area on the right. If there are no items in the list, it initially displays at something like 4 pixels wide. If I populate it with items first, it displays at a reasonable initial size.

So, under what circumstances does Sun imagine I might want a 4-pixel wide list? If I did want one that narrow, what are the odds that I’d want it to expand to 100 pixels when I added data? I’d say that Swing remains a nightmare framework of poorly chosen defaults, code generation gui builders, and ugly rendering. It can be improved with Java 2D rendering, but at that point, you might as well write all your own widgets as its not that hard to do raw mouse/keyboard event tracking.
Once again, Sun spends vast amounts of time, energy, and cash gazing at their navels instead of simply adopting proven solutions.