Problems with Java/J2EE Programming Model

Jeff Vroom
1/7/2004

I wanted to put down a quick placeholder about problems I see with the J2EE specification. This is not to say that I don't think great applications can be built using J2EE and if I had to build certain types of applications today, I'd choose J2EE. I do want to take a direct look at how we program applications using J2EE so we understand the best way to improve it and future programming tools.

EJB

EJB adds tremendous complexity to the programming model while actually restricting the flexibility and portability you get when you don't use it. It has a persistence framework but one that only operates in a J2EE container. Since pretty much all code has to do persistence of one form or another, this means you have to write special code that can then only be used in a managed EJB container. It bundles together remote programming, transactions, persistence etc. It defines the EJB deployer role, giving them them ability to define security and transactionality constraints but in my view that just requires extra configuration information for the Java developer. Now they have a whole nother file format to learn and maintain either by hand, which is painful, or through a UI tool which is painful.

This was a spec written by people primarily considering the manageability of code assets. They wanted to create a "safer" programming environment for a less skilled type of Java programmer. But in my view, this really does not exist. Those types of programmers use perl, python, or vbscript productively and will never get or be able to adhere to the complexity of the EJB interfaces. It imposes a lot of discipline and structure which you must learn and offers limited real functionality by itself. I think manageability is an important feature for a development environment, but it is something you layer on a design with constraints, test suites, performance measuring tools, and tools for helping automate the important programming tasks.

There are a lot more bad things about EJB - the content of the XML files - the fact that you cannot use threads or static variables, the performance of remote invocation, but I think these problems are relatively well known so I won't go into their specifics.

No standard, universal persistence model

Really this is a problem with Java - there should be a standard way to persist Java classes which is compatible with SQL, file system, OODBs etc. This should be part of the standard Java toolset for maximum code portability, interoperability and reusability. Rather than specifying a single way to do persistence, hooks are designed to let folks plug in their own persistence engines.

Right now, Java implements persistence using the serializable facility but this is clearly too restrictive a mechanism to perform general application state maintenance. I think this is a particularly hard thing to integrate into a language and that is why I'm looking at building it in from scratch on my own. The language Jade is one of the cleanest implementations of what I'm talking about here (www.jadeworld.com) but I think the performance of their stuff is probably not that good based on their architecture.

The big problem though is that persistence is a big political hot button for just about everyone. No big company will agree to a standard which conflicts with the revenue goals of that company and large companies have a lot invested in existing persistence standards. It may be that they have a lot invested in the lock-in you get with today's persistence standards but even if that is not the case, getting a single universal persistence solution past most standards committees has been a daunting task. JDO may be the best candidate and it has limited acceptance and (in my opinion) has only standardized a small fraction of what we need in this area.

Poor component configuration and lifecycle support

One of the most important things in designing a programming language in my opinion is to define high level abstractions that are easy for people to learn. Java is a class based object system where instances get created by procedural operations at runtime, object instantiation time, class load time etc. These are all clearly important events but programmers have many more important lifecycles which they care about: per-user, per-request tied to some specific operation invocation, e.g. per-checkout.

A more generalized scope concept (similar to that as implemented in ATG's nucleus) that is built in to the language will both improve the power of logic you can implement with a simple declarative construct. This reduces the amount of code, potentially improves the efficiency of the system, and I believe will improve the manageability of the code. Also, by recognizing the applications are assembled by merging together layers, we can reduce the amount of copying and improve the manageability of the code assets that way too.

As a result of these missing features in the base language, they are implemented time and again in other specs popping up in J2EE. If there was one standard persistence model which was used for managing all component configurations, we would not need all of the DTDs for all of the XXX specifier files and all of the wizard tools for managing that state. There could be one set of admin UIs for managing application configuration, centralized application deployment and management.

Too many languages

For each problem, J2EE architects have added new specs which define new interfaces and in some cases new languages or even language frameworks like the JSP tag library. Unfortunately, these languages are hard to integrate and we end up with a lot of complexity at the boundaries. It is true that we need different levels of detail for different types of programmers but you can do this by a) building applications in layers suited for folks in a given skill set and b) UIs which allow a programmer to interface with the program in a custom mode emphasizing the constructs they understand. It also helps if the language is well defined so that even naive programmers can view and edit simple components and configuration. The next level of programmer knows about functions, loops, assignments, but not synchronization, casting, etc.

The newest part of J2EE is the web services which adds a whole new "glue" layer - yet one more programming interface for programmers to learn and more code for them to write to accomplish even the simplest of programming tasks. To me, there should be one overriding model of the program which is rich enough to generate all of the glue necessary. I think Java is trying to get to this with their meta-data JSRs - at least they are headed in the right direction. I'm not sure you can accomplish this properly though without a generative programming environment and better integrated persistence.

Still not finished

Even with all of the complexity in the current J2EE programming model, there are still large unsolved problems, mostly surrounding the management, deployment and maintenance of all of the various files and file formats in the J2EE spec. App server vendors fill in the gaps with proprietary interfaces, which usually generate and maintain large amounts of server configuration state. Though it may not seem like it, this configuration becomes a big part of the code for your application. Worse, it is written in a proprietary language and edited iva tools which likely won't implement revision control. From what I've seen, they typically do a lot of "generating" of configuration - i.e. with a new install or cluster member, you end up with many lines of XML configuration. And since these admin UIs are changing all the time, the management of this configuration may be difficult in a migration. Importing settings essential to the functioning of the application could be lost.

I think part of the problem is that folks really want a software grid like architecture (see www.globus.org, though I think this is primarily used by the scientific community and may lack the necessary notions of transactions and data integrity for enterprise programming in this form). Once again, how modules are configured and deployed are problems that if solved at the foundation layer, minimize copying and thus minimize maintenance. When state is replicated in a XML files stored as special locations in some Jar file, it seems to me that you have a much more complicated beast to manage. Configuration is as important as code and should be managed with a more powerful environment than replicated proprietary monolithic XML files.