Java's fundamental premise of Write Once, Run Anywhere (WORA) ensures that J2EE apps are far more portable than apps written using any comparable platform. We can be sure that Java objects will behave consistently in different environments, while the Sun J2EE Compatibility program helps guarantee that different J2EE servers fulfill the requirements of the J2EE specifications. As J2EE servers tend to be written in Java, servers themselves are usually supported on multiple operating systems. Unfortunately, the CTS doesn't present the complete picture. It's good that an app written within the bounds of the J2EE specifications can be ported between servers. However, what if a real-world app needs to go beyond the scope of the specifications? Let's examine what portability actually means in a J2EE context.
There are several issues around the portability of J2EE apps:
Portability of apps between app servers
This is probably the first issue that comes to mind when we think about portability in a J2EE context. Portability of apps between app servers will usually depend on the following factors, most of which are under our control:
How faithfully does the target server implement the J2EE specifications?
The Sun CTS helps eliminate the first issue. The second can be avoided by a thorough understanding of J2EE, and discipline during app development. This leaves the third: a much harder problem (we should, of course, only use proprietary server features when they deliver real benefit). I'll discuss strategies for ensuring that access to proprietary extensions does not break portability below.
Change to a comparable, competing resource. Imagine that we need to migrate from a proof of concept with Cloudscape to a deployment on Oracle. JDBC provides a basic level of abstraction here, although it will usually be necessary to modify SQL statements.
It's vital to distinguish between these issues. I feel that far too much emphasis is placed on database portability, in particular. This reflects an unrealistic J2EE-centric view of enterprise IT. Organizations invest a lot of money in databases. They don't jump ship often, and expect this investment to be leveraged. Thus, it's unwise to ignore the potential of proprietary database features in simplifying app code and improving performance. Portability between app servers, on the other hand, is more easily achievable and may deliver greater business value. It's important to remember that we can enjoy some benefit from J2EE's portability even if we never choose to migrate our apps to a different platform. Since J2EE supports such a wide variety of implementations, there is a large community of J2EE developers with experience on a variety of platforms. This makes for a valuable mix of skills in J2EE teams. I'm reminded of this whenever I work with a Microsoft-only organization.
In summary, the J2EE portability news is good, but complete portability is neither possible nor desirable. The limits of portability largely reflect performance imperatives and the limits of the J2EE specifications, and the resulting need to use platform-specific technologies. As we shall see, there are techniques we can use to work around these issues.
As we've already discussed, refusing to use any vendor-specific functionality is dangerous. Architects and developers are employed to deliver working solutions for real organizations, not produce "pure" J2EE apps. However, this doesn't mean that it's impossible to design for portability. This can be achieved in three ways:
Write code that complies with the J2EE specifications. Adopt organization-wide standards for writing J2EE-compliant code, and ensure that all developers understand and follow them. Use the J2EE Reference Implementation verifier tool regularly to check compliance.