Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Overcome J2SE 1.3-1.4 incompatibilities

Overcome J2SE 1.3-1.4 incompatibilities

Tutorial Details:

Overcome J2SE 1.3-1.4 incompatibilities
Overcome J2SE 1.3-1.4 incompatibilities
By: By Sam Mefford
Get help from the Reflection API and Ant
ava has added numerous APIs, like Java Database Connectivity (JDBC), to its standard set of libraries. This helps a wider audience adopt the APIs since optional packages don't need to be bundled with deployments. For groups writing implementations of these popular APIs, wider adoption makes their offerings more valuable. However, these groups might wish their APIs were still optional (as opposed to being included with Java's standard library set) when a newer Java version ships with an updated API that depends on classes and methods unavailable in previous Java versions. Suddenly you must maintain two versions of the implementation?one that complies with the old API and one that complies with the new API. This is exactly what happened with the JDBC API in Java 2 Platform, Standard Edition (J2SE) 1.4. Because of changes to the JDBC API, an implementation of java.sql.Connection cannot compile under both J2SE 1.3 and 1.4.
You might have found yourself in the same predicament as me: I needed to implement JDBC interfaces such as java.sql.Connection , but my code needed to compile under both J2SE 1.3 and 1.4. I didn't want to maintain different source files for J2SE 1.3 and 1.4, so I looked for a better solution.
Unfortunately, the famous Write Once, Run Anywhere (WORA) Java mantra does not include WOCA (Write Once, Compile Anywhere) if you rely on javac to do your compilation. Luckily, code tricks with the Reflection API and compile tricks with Ant can come to the rescue. I can have just one set of .java source files and Ant helps me compile it on both J2SE 1.3 and 1.4. Ant lets me modify the .java files on-the-fly to make changes appropriate for the Java version used for compilation. But before I can explain the full solution, I must explain the full problem.
Poor man's connection pool
Two years ago, my company needed a JDBC connection pool but wouldn't pay for one. At the time, we couldn't find a good free alternative, so we wrote an in-house connection pool. To better track how connections were being used throughout our applications, we created com.icentris.sql.ConnectionWrapper , which implements java.sql.Connection and some other wrapper classes that implement other java.sql interfaces. The wrapper classes only track database usage in our application and then pass through method calls to the real JDBC resource.
When J2SE 1.4 came along, we naturally wanted to migrate some of our clients to it so they could benefit from its many enhancements. But, of course, we still needed to support J2SE 1.3 for clients who saw no reason to upgrade. To our chagrin, ConnectionWrapper and our other JDBC wrapper classes would not compile on J2SE 1.4 without modification. To keep this article simple, I'll use ConnectionWrapper to demonstrate the techniques I applied to all classes that wouldn't compile under both J2SE 1.3 and 1.4. To comply with the updated JDBC API, I had to add several methods to ConnectionWrapper , which posed two big problems:
Since my wrapper classes need to pass through method calls, I would have to call methods that don't exist in the J2SE 1.3 sql classes.
Since some new methods rely on new classes, I would have to build in dependencies on classes that don't exist in J2SE 1.3.
Reflection to the rescue
Some code samples can best explain the first problem. Because my ConnectionWrapper wraps a java.sql.Connection , all my examples depend on the realConnection instance variable (in bold) set in the constructor:
private java.sql.Connection realConnection = null;
public ConnectionWrapper(java.sql.Connection connection) {
realConnection = connection;
}
To see what I would have done without incompatibility issues, let's consider setHoldability(int) (a new method to java.sql.Connection in J2SE 1.4):
public void setHoldability(int holdability) throws SQLException {
realConnection.setHoldability( holdability );
}
Unfortunately, this code does not compile under J2SE 1.3 because java.sql.Connection doesn't have a setHoldability() method I can call under J2SE 1.3. But to compile under J2SE 1.4, I must have a setHoldability() method to properly implement the API. To solve this catch-22, I assumed my setHoldability() method would only be called under J2SE 1.4, so I could use the Reflection API to call the method:
public void setHoldability(int holdability) throws SQLException {
Class[] argTypes = new Class[] { Integer.TYPE };
Object[] args = new Object[] {new Integer(holdability)};
callJava14Method("setHoldability", realConnection, argTypes, args);
}
public static Object callJava14Method(String methodName, Object instance,
Class[] argTypes, Object[] args)
throws SQLException
{
try {
Method method = instance.getClass().getMethod(methodName, argTypes);
return method.invoke(instance, args );
} catch (NoSuchMethodException e) {
e.printStackTrace();
throw new SQLException("Error Invoking method (" + methodName + "): "
+ e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new SQLException("Error Invoking method (" + methodName + "): "
+ e);
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new SQLException("Error Invoking method (" + methodName + "): "
+ e);
}
}
Now I have a setHoldability() method, so I can compile under J2SE 1.4. I don't directly call the formerly nonexistent method on my java.sql.Connection , so I can compile under J2SE 1.3. My callJava14Method() method uses the Reflection API to call the method, then wraps any errors inside an SQLException since that is all I'm supposed to throw. I used this strategy for all the new J2SE 1.4 methods so my code would still work properly under 1.4, calling the wrapped method, yet compile under 1.3. Now I just needed to solve the second problem and find a way to depend on classes that do not exist in J2SE 1.3.
Ant is the answer
In J2SE 1.4, java.sql.Connection depends on a new class: java.sql.Savepoint . Since this new class resides in the java.sql package, you cannot add it to J2SE 1.3. Java does not allow any third-party additions to the set of core classes in the java.* or javax.* packages. So this was my challenge: use the new java.sql.Savepoint class to write my code so it works under J2SE 1.4, yet make sure the code compiles under J2SE 1.3 where that class doesn't exist. Simple, right? All who answered "Yes!" get a brownie point. Well, at least, it's simple now that I found the answer.
First, I included the following conditional import:
// Comment_next_line_to_compile_with_Java_1.3
import java.sql.Savepoint;
Then I found a way for Ant to comment that import when compiling under J2SE 1.3. Simplified, the key part of the Ant script is:

Comment_next_line_for_Java_1.3
Comment_next_line_for_Java_1.3 //

This Ant tag has several options?you'll see more in my full example below?but the important part is that I search for and replace it with . The is the XML entity for "newline". When compiling under J2SE 1.4, Ant makes no change to the source file; and under J2SE 1.3, the import statement is commented:
// Comment_next_line_to_compile_with_Java_1.3
//import java.sql.Savepoint;
But I still have code in the body of my class that must depend on Savepoint :
public Savepoint setSavepoint(String name) throws SQLException { . . .
Again, I only expect to use these new methods under J2SE 1.4, so they don't need to function under J2SE 1.3; they just need to compile. I discovered that if I have a Savepoint class in my package, my code can compile without an import statement. Yet when the import statement is uncommented (under J2SE 1.4 compilations), my Savepoint class is ignored because of the more specific import. So I created my own dummy class called com.icentris.sql.Savepoint , which (javadoc excluded) is probably the shortest valid class:
package com.icentris.sql;
/** Dummy class to allow ConnectionWrapper to implement java.sql.Connection
* and still compile under J2SE 1.3 and J2SE 1.4. When compiled
* under J2SE 1.3, this class compiles as a placeholder instead of the
* missing java.sql.Savepoint (not in J2SE 1.3). When compiled
* under J2SE 1.4, this class is ignored and ConnectionWrapper uses the
* java.sql.Savepoint that is new in J2SE 1.4.
*/
public class Savepoint {}
Under J2SE 1.4, I can now properly import java.sql.Savepoint . Under J2SE 1.3, Ant comments the import line, so the Savepoint referred to in my code happens to be the dummy class sitting in the same package. Now I can add all the methods that reference Savepoint and still use the Reflection trick explained earlier:
// Comment_next_line_to_compile_with_Java_1.3
import java.sql.Savepoint;
. . .
public Savepoint setSavepoint() throws SQLException {
Class[] argTypes = new Class[0];
Object[] args = new Object[0];
return (Savepoint) callJava14Method("setSavepoint", realConnection,
argTypes, args);
}
public Savepoint setSavepoint(String name) throws SQLException {
Class[] argTypes = new Class[] { String.class };
Object[] args = new Object[] { name };
return (Savepoint) callJava14Method("setSavepoint", realConnection,
argTypes, args);
}
public void rollback(Savepoint savepoint) throws SQLException {
Class[] argTypes = new Class[] { Savepoint.class };
Object[] args = new Object[] { savepoint };
callJava14Method("rollback", realConnection, argTypes, args);
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
Class[] argTypes = new Class[] { Savepoint.class };
Object[] args = new Object[] { savepoint };
callJava14Method("releaseSavepoint", realConnection, argTypes, args);
}
Now all I need is my full Ant compile target to detect J2SE 1.3 and comment that import line on-the-fly when anyone attempts to use


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Overcome J2SE 1.3-1.4 incompatibilities

View Tutorial:
Overcome J2SE 1.3-1.4 incompatibilities

Related Tutorials:

Alternative deployment methods, Part 1: Beyond applets - JavaWorld May 2000
Alternative deployment methods, Part 1: Beyond applets - JavaWorld May 2000
 
Java security evolution and concepts, Part 2
Java security evolution and concepts, Part 2
 
Java security evolution and concepts, Part 5
Java security evolution and concepts, Part 5
 
J2SE 1.4 breathes new life into the CORBA community, Part 2
J2SE 1.4 breathes new life into the CORBA community, Part 2
 
Overcome J2SE 1.3-1.4 incompatibilities
Overcome J2SE 1.3-1.4 incompatibilities
 
Taming Tiger
Taming Tiger, Part 2 Understanding generics Welcome to the second part of this three-part series on Sun Microsystems' latest release of the Java 2 Platform, Standard Edition (J2SE). To refresh your memory, Part 1 was a quick introduction to J2SE 1.5
 
Inside Class Loaders: Debugging
Inside Class Loaders: Debugging This article will show how to solve class-loading problems and to overcome some debugging limitations of the JDK class loaders.
 
Taming Tiger, Part 3
J2SE 5—code named "Tiger"—is the most significant revision to the Java language since its original inception. Tarak Modi's primary goal with his three-part series on Tiger is to familiarize readers with J2SE 5's most important additions and show how t
 
Light-Weight Visual Components Library for different platform: SWT, J2SE, J2ME, .NET
Light-Weight Visual Components Library for different platform: SWT, J2SE, J2ME, .NET
 
Bridging the Gap: J2SE 5.0 Annotations
Bridging the Gap: J2SE 5.0 Annotations It takes a long time for the Java community to fully absorb a major new JDK release; it seems to take about two more releases after a brand new version of the JDK before everything settles down. Application server v
 
Using Timers in J2EE Applications
Using Timers in J2EE Applications Job scheduling is nothing new--most enterprise applications require the scheduling of tasks and activities. For example, your application may need a timer service to run a business process once a day, or to clean up a te
 
Create and Read J2SE 5.0 Annotations with the ASM Bytecode Toolkit
Create and Read J2SE 5.0 Annotations with the ASM Bytecode Toolkit Bytecode Attributes Annotations are actually stored in bytecode with several special attributes. The binary format for these and all other standard attributes is described in the Java Vi
 
Integrating Macromedia Flex with Java
Integrating Macromedia Flex with Java. Rich Internet Application (RIA) technologies are emerging to handle the limitations of the presentation layer. This article will teaches you Rich Internet Application development
 
Network Programming with JavaTM 2 Platform, Standard Edition 1.4 (J2SETM)
This article provides an overview of the new features and enhancements in the Java 2 Platform, Standard Edition 1.4 (J2SE), and shows you how to use them effectively.
 
Unclog the server bottleneck with active containers.
In server-side control architectures such as Java ServerFaces (JSF) or Struts, a majority of the control events must be handled on the server side to update the state of the control. For every user event, the entire page data is sent back to the server...
 
Using JConsole to Monitor Applications
JConsole is the Java Monitoring and Management Console, a new graphical tool shipped in J2SE JDK 5.0. This article describes how JConsole can be used to observe information about an application running on the Java platform, with an overview of the J2SE 5.
 
Tiger and Beyond, the Future of the Java Platform
Part Two of an interview with Sun Microsystems' Sun Fellow, Graham Hamilton, explores Java 2 Platform, Standard Edition 5.0 (J2SE 5.0) and the future of the Java language.
 
HPROF: A Heap/CPU Profiling Tool in J2SE 5.0
Having performance problems with your Java Application? Using too much Java heap space and don't know why? Sometimes simple software tools are all that's needed.
 
Five Reasons to Move to the J2SE 5 Platform
Five important reasons to move to the Java 2 Platform, Standard Edition (J2SE platform) 5.0, supported by data and references to prove that the 5.0 release will reduce development and runtime costs.
 
J2SE Platform Migration Guide (pdf)
This guide helps developers migrate Java applets, standalone applications, Java Web Start applications and development tools from version 1.3 and 1.4 of the Java platform to version 5.0.
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.