Creating a Highly
Productive Java-based Development Environment 2
Introduction
Six months ago at Oracle OpenWorld, I gave a talk with this same title. JDeveloper 3.0 had just been released and it looked as though this would be a very interesting product and important strategic direction for Oracle. At this point, I am pleased that the product has finally matured and our early impressions were correct. As of this writing, the JDeveloper release 3.1 CD is still warm and I have not had a chance to investigate any of the new features and changes from the 3.0 release. Given what I have been told, there seems to be an incremental improvement.
An exciting aspect of the future development of the JDeveloper product is the inclusion of all UML (Unified Modeling Language) development within the Oracle JDeveloper development team. I believe that we are at least a year away from seeing the impact of this move, which could result in a unified development environment based on object-oriented principles.
Six months ago, it was not clear what the best tool would be to build Java systems in an Oracle environment. Oracle development teams worldwide have used and continue to use a variety of products to create web-based e-commerce applications. With JDeveloper 3.0 and 3.1, there is now a compelling reason to stick with Oracle. I have no doubt that other products will continue to be used, but the best product to develop Java-based applications to be deployed over the web or elsewhere is JDeveloper.
Why Java as opposed to PL/SQL or Developer?
There are several reasons why it is necessary to move to a Java language environment.
First, the market forces (all of which may not be entirely rational) have already mandated that all new development work be done in Java.
Second, Java is simply a better development environment than PL/SQL-Developer for the following reasons:
1. Rather than having an application development tool and language as two distinct entities, any Java 4GL tool such as JDeveloper or Visual Café create Java programs that are essentially very large text files. The strength of this unified environment does away with many of the limitations in the Developer environment, especially with respect to the creation of user interfaces.
2. You can build reusable components. This is not to say that you cannot do this using Developer. Dulcian’s entire business has been created around this concept. However, there is a limit to what these components can do in the Developer environment. Java allows for the creation of a sophisticated user interface to compete with VB, Delphi or C++ that was not possible before, despite the fact that these products were nowhere near as productive for database “bread and butter” applications such as payroll and common business systems.
3. Java is explicitly a multi-tasking programming language. Working in PL/SQL to support multi-tasking involves the use of DBMS Job and writing arcane logic to detect when tasks have been completed. Coordination of tasks is easily supported in Java.
4. Class inheritance allows you to define a class in Java that extends a prior class. In Java, a class can be anything from program units, GUI objects (such as buttons) to complete applications. This means that you can build reusable components similar to field SmartClasses in Developer up to whole system application portions corresponding to an entire .FMB file in Forms.
5. All of these factors allow developers to apply object-oriented thinking to the entire development environment and build reusable structures of any size. The behavior of any GUI object in Java can be modified. For example, you can define your own calendar widgets, etc.
6. Java is an emerging industry standard. Everyone is going Java-crazy. As a result, we will likely see third party, Java components that can be purchased and brought into our own applications.
7. Because of Java’s open environment, it will be easier to find developer talent.
8. Java now provides a high level of server-side/application-side transparency of code. Code can reside in the application or server and move seamlessly between the two. You can even place and execute code anywhere on any machine involved in the application.
Is the Java Environment Ready for You?
The answer to this question is Yes and No. The Java programming language is great by any standards. JDeveloper provides a very solid development environment with the developer interface largely built by Borland. Its development environment is as good as any other in the industry.
The Business Components for Java (BC4J) addition to the JDeveloper tool suite eliminated the nightmare of connecting Java applications to the database in a civilized way. It is now easy to create middle layer objects.
What is still missing?
For anyone who has actually tried to take advantage of the myriad of possibilities that Java affords, you must recognize that this is still a very new development environment. There are very few mature developers with years of experience with these tools. In the object-oriented world, many developers still insist on using C++ to create reusable code. Others are willing to jump onto the Java bandwagon but there is still no clear consensus.
What makes the difference between Java success and failure?
In order to use Java effectively, it is critical to be an object-oriented thinker. It is possible to use Java to build applications in the traditional way. Java is a fully featured 3GL language. However, to take advantage of the tremendous potential of object-oriented components available in Java, you must understand OO theory.
Another critical success factor for a Java development environment is the creation of carefully thought out and rigorously enforced GUI standards. This includes building large libraries of reusable components. As I have often discussed with reference to making Developer a great product through the use of extensive PL/SQL libraries, SmartClasses and object groups, the same is true in the JDeveloper environment. Here, you can build even larger reusable structures to achieve even better productivity than was possible using Developer. My greatest fear is that developers will use these new tools with the same thinking they have been using in the past.
Features that Java does not support
The Java language does not support certain fundamental features due to the security conscious, object-oriented premise that is the foundation for this powerful and dynamic language. Perhaps the most significant difference is the deliberate elimination of pointers in Java. Pointers have been around since the beginning of modern programming. They were suitably designed for isolated applications that could run independently, and had total ownership of all system resources. Pointers do not exist in Java because of their inherent lack of security. The use of traditional pointers allows any application to have access to memory outside of the limits set aside for it in a multitasking environment. Pointers thus make it possible for the “bad guys” to gain access to data, or to damage other programs that were running concurrently. Thus many programming techniques such as indirect addressing, and incremented-pointer array access must be implemented in other ways when coding in Java.
Some Other Important – “Missing Features”
· Java does not allow the use of Default arguments. All parameters must be defined and passed, as coded in the more rigid Java statements.
· Java does not support function overloading or operator-overloading. It was a judgment call to eliminate these features to reduce the confusion they might create during code development and maintenance.
· Java does not have global variables, as such. Instead, Java is an object–oriented language where code is encapsulated in one or more classes. Each class can have access to all of its inherited classes and objects, thus providing a way for the code to share objects that act like traditional global variables.
· Java’s class structure does not support multiple super-classes. Java’s simple inheritance structure provides for a single-class inheritance hierarchy (i.e. C inherits B, and B inherits A… thus C has access to A).
· Java does not provide for automatic type conversions. All conversions must be explicitly cast.
Strategy
To make the Java environment efficient, you need to develop very
precise coding and GUI standards so that developers do not waste a great deal of
time "doing their own thing". In
creating a strategy to overcome the conversion problems, you must deal with the
code structures that have changed in the basic language, and select an
appropriate Java toolset to reduce the laborious task of producing Java source
code. The key to success in
creating a rapid development process is the construction of reusable components
that bridge the gap between the old and new tools.
Some Examples that deal with the basic language conversion concepts
The following examples illustrate some of the issues of converting to the Java language.
1. Converting code to handle Indirect-Addressing
For the most part, it is easy to upgrade pointers to the Java development environment. Since Java passes all objects by reference, it is possible to create Java "Classes/Methods" that can act like pointers in many respects. By implementing object-reference-variables, it is possible to access both an object and its reference. By passing references to a temporary variable in Java, it is possible to create an implementation, which functionally acts just like an Indirect-Address-Pointer.
See the following example, which calculates the Volume of several Boxes and uses a Temp variable to access/update these Boxes by reference.
Indirect-Address
Example
Create a simple Class to hold the dimensions for a Box:
public class Box {
double width;
double height;
double depth;
}
Create a second Class to calculate the Volume of two Boxes, using a single Temp reference object as an indirect address reference to the Box objects:
public class BoxDemo {
public static void main(String args[]) {
double volume; //variable to hold the results
/* Create 1st Box */
Box mybox1 = new Box(); //allocates memory for 1st Box
/* Assigns values to variables for 1st Box */
mybox1.width = 10;
mybox1.height = 20;
mybox1.depth = 15;
/* Show Results: Calculate Volume and print output */
volume = mybox1.width * mybox1.height * mybox1.depth;
System.out.println("Volume 1 is " + volume);
The Output produced by this
line:
Volume 1 is 3000.0
/* The 2nd Box */
Box mybox2 = new Box(); //allocates memory for 2nd Box
mybox2.width = 20;
mybox2.height = 20;
mybox2.depth = 15;
volume = mybox2.width * mybox2.height * mybox2.depth;
System.out.println("Volume 2 is " + volume);
The Output produced by this
line:
Volume 2 is 6000.0
/* Now create a plain Box Reference Object that can be used to
point at the two boxes that have already been created */
Box myboxTemp; //No allocation - just a reference
/* Copy 1stBox's reference(like a pointer) to the Temp variable */
myboxTemp = mybox1;
/* Now the Temp references the 1stBox's data */
// Show resutls:
volume = myboxTemp.width * myboxTemp.height * myboxTemp.depth;
System.out.println("Volume Temp is " + volume);
The Output produced by this
line:
Volume Temp is 3000.0
/* Change the Temp variable to reference 2ndBox */
myboxTemp = mybox2;
/* Now the Temp references the 2ndBox's data */
volume = myboxTemp.width * myboxTemp.height * myboxTemp.depth;
System.out.println("Volume Temp is " + volume);
The Output produced by this
line:
Volume Temp is 6000.0
/* Change 2ndBox's width using the Temp variable as a reference */
myboxTemp.width = 1;
volume = myboxTemp.width * myboxTemp.height * myboxTemp.depth;
System.out.println("Volume Temp is " + volume);
volume = mybox2.width * mybox2.height * mybox2.depth;
System.out.println("Volume 2 is " + volume);
volume = mybox1.width * mybox1.height * mybox1.depth;
System.out.println("Volume 1 is " + volume);
The Output produced by these
lines:
Volume Temp is
300.0
Volume 2 is 300.0
Volume 1 is 3000.0
}
}
The preceding example illustrated how Java could use an object-reference-variable as a workaround for Indirect-Addressing. Note that when a reference is copied to the Temp object, all data remains unchanged. Only when explicit calls are made to the underlying data stored in the width, height, and depth variables, are changes actually made to the stored data.
2. Example that deals with Java language conversion
A second example for converting to Java is presented below.
Converting code to
handle Default Arguments
One extensively used feature of Oracle Forms and PL/SQL, that Java does not support, is Default Values for function-arguments. A traditional Oracle practice for overloading functions is to use these Default Values for some arguments. Java does not allow this practice since it requires unique methods to be defined for every function. Consider the following PL/SQL function, which calculates the area of square or rectangle by passing either one or two arguments.
Function area (Length In number, Width In number := 0 )
RETURN number
IS
areaOut number;
BEGIN
IF (width ==0)
THEN
areaOut := Length * Length;
ELSE
areaOut := Length * Width;
ENDIF;
RETURN (areaOut);
END;
Procedure TestArea
IS
BEGIN
Dbms_output.put_line('Area of 2.2 by 3.4 rectangle: '||
area(2.2, 3.4) );
Dbms_output.put_line('Area of 3.0 by 3.0 square: '||
area(3.0) );
END;
As you can see in this PL/SQL example, if the area function is called using just one argument it calculates the area for a square. When the function receives both arguments, then the area of a rectangle is calculated using the length and width. While this is very convenient and saves writing almost duplicate blocks of code, using Default Arguments for Overloading is not actually a necessary construct for the language. In Java, you can quickly construct a workaround by writing two overloaded methods. Construct one method for the area of a square with one argument, and a second method for the area of a rectangle with two arguments.
Using this approach the PL/SQL area function can be rewritten as follows:
//Java version of the PL/SQL area function
Class TestArea (
/* First method for a Square */
static double area(double Length) {
RETURN Length * Length;
}
/* Second method for a Rectangle*/
static double area(double Length, double Width) {
RETURN Length * Width;
}
/* Test methods */
public static void main(String args[] {
System.out.println("Area of 2.2 by 3.4 rectangle: " +
area(2.2, 3.4);
System.out.println("Area of 3.0 by 3.0 square: " +
area(3.0);
}
}
2. New Features that have been added by Java
The following is a list of some new features Java uses to make a significant impact on its applicability to today’s multitasking environment.
· Java can spawn multiple “threads” concurrently. This significant Java feature allows the simultaneous execution of several code-segments using simple and straightforward commands.
· Java incorporates an improved memory allocation methodology. It does not require any explicit commands to free memory when an object no longer has any valid references. A garbage collection routine automatically deletes the object after it detects that the last reference has been dropped.
·
Java adds its own API's classes that provide an
ever-growing library of new code segments that improve functionality and
productivity. With the Internet GUI
as its prime focus, Java encompasses an almost limitless supply of new
Look-and-Feel components for the application developer. The use of these object-oriented
components is not limited to just Java applications; they can also be used
directly in the Oracle Developer Products (Form Builder and Report Builder R6.0)
and can be stored in the latest releases of the Oracle RDBMS products.
3. Features that are implemented differently
While Java has many features that are very similar to other languages, they are implemented slightly differently. Generally, Java uses a more disciplined and restrictive implementation for its coding practices.
· Access specifiers in Java only apply to the object directly following the specifier. In other languages, they may apply to a whole group of objects that follow the specifier.
· Exceptions in Java must be "caught". Other languages may not be as strict in their handling of exceptions.
· Boolean operators in Java are predefined as literals "true and false", and these are the only values that Java will recognize. Other languages may allow Non-Zero values to represent True, etc....
What are the Steps Necessary to Create a Productive Java Development Environment?
If you are a part of a Designer/Developer shop currently writing applications using PL/SQL and Developer or generating from Designer, there are several steps you can take in order to make the transition to a Java/JDeveloper environment.
Step 1: Learn about Java
Read a Java book. One useful one I have found is Java 2: The Complete Reference by Patrick Naughton & Herbert Schildt 3rd edition (Osborne McGraw-Hill, April 1999). Taking a Java class may also be very useful.
For someone coming from a strictly Oracle environment, there are some really odd things about Java that you will need to understand. For example, in Java, strings are implemented as objects and therefore cannot be updated once assigned. If you are unaware of factors like this and assume that Java works in the same way that PL/SQL does, developing applications will be a difficult process. Other areas where Java differs significantly include subclassing and multi-task programming. It is important to recognize that Java is not the same as any other programming language. Even experienced PL/SQL and C++ programmers will need to learn some new concepts.
Step 2: Learn the vocabulary
As in learning any new language, there are many new terms to understand: applets, servlets, IIOP. Java beans, infobus, CORBA, XML to name a few. So far, I have not found any single reference work that clearly and succinctly defines all of these terms. Whole books can be written about each one of these aspects of the Java environment. Again, either reading about Java or taking a class may be the best strategy.
Step 3: Learn the JDeveloper product along with Business Components for Java
If you already know Java (I suggest you learn the basics first), many of the features of JDeveloper will make more sense. Some examples of the new concepts to learn in JDeveloper include:
· Integration between Java and the file structure of your computer and the way that packages are defined
· The relationship between Java program files and class files
JDeveloper is a sophisticated product. It is wise to approach it from a Java perspective and then look at the implementation in JDeveloper.
One long-term theme in much of my past writing about the Developer product has been the steep learning curve required to be an effective Forms and Reports developer. Is the situation any better for JDeveloper? From the application architect’s perspective, the answer is no because the environment is that much richer and there are so many more options to consider. However, a good application architect can create an environment with a carefully thought out set of GUI and design standards within which the intellectual burden placed on a junior developer could be very small. Any number of sophisticated reusable components can be created by more experienced developers. Less experienced developers can bolt these components together and write any additional custom code.
This is a real strength of the Java/JDeveloper environment. Application architects can create a development environment limited only by their imaginations and the resources available to develop it.
Step 4: Learn Object-Oriented Theory and UML
While clearly not mandatory, trying to build Java-based systems without object-orientation can be done but this approach does not take advantage of the most powerful aspects of the language.
Ultimately, you will also want to learn UML since it is the emerging standard for object-oriented development. UML also helps to guide your thinking in an object-oriented direction. At Dulcian, we have used UML to support database designs implemented in a relational database, application designs as well as the articulation and storage of complex business rules. UML is an extraordinarily rich modeling environment that nicely complements the rich application development environment of Java. Oracle is in the process of adding UML capability into JDeveloper to be available within the next year or so.
Step 5: Build Your First JDeveloper Application
Don’t worry about using object-oriented principles for this first try. Port an existing application into Java/JDeveloper. This will provide enough experience to determine what reusable components you need. For example, in Developer, there is a field with a label. In the components delivered with JDeveloper, there are fields, labels and frames. For each field and label on the screen, you must use three objects – the field, the label and the frame to contain them. By creating a reusable component for this three-object combination, you won’t have to recreate this every time.
Initially, these small types of “widget” may be the only things you build. Once you have created a set of these, you can move on to creating more complex objects, such as calendar widgets and multi-select LOVs. These commonplace items may also be available from third party sources or you may want to modify or build them on your own. There is no limit to the size of reusable components you can build using Java/JDeveloper. However, by building large abstract components, you can greatly improve the productivity of your development process.
Step 6: Set Your GUI and Design Standards
Java provides an environment as rich as anything you can imagine. In comparison to the past development environment, there is a dizzying array of objects available. For example, in Forms, you have only a handful of UIG objects to select from on the toolbar. In Java, there are thousands.
JDeveloper is not especially helpful in selecting appropriate GUI standards and provides a GUI environment not much richer than Forms did. The difference is that the JDeveloper environment can be extended in almost any way desired. How should this be done? There are several alternatives:
A. Bring in a Java expert familiar with many of the available components.
B. Plow through the Swing components and all of the available third party component libraries to find something that fits your needs. This must be done carefully. It is easy to fall into the trap of using many colors and incomprehensible widgets all over the screen.
Conventional wisdom says that web development is inherently different from client-server development. This is not necessarily true. Good application design is influenced by the tools used, the applications themselves and the users. Ultimately, good application design is good application design in any environment.
In making the transition from client-server to web development, there are many software vendors who went from very sophisticated, highly efficient products to products that look as though their GUI design standards were copied from an undergraduate art major’s web page. The GUI design may be extremely attractive, but grossly inefficient and ultimately harder to use that the client-server version (although much more colorful).
As we make the transition from client/server-style to Java-based applications development, a fine balance that must be achieved. On one hand, applications should maintain the clean design and efficiency attained in a client/server environment while taking advantage of the additional functionality of web-based components. Improving the aesthetic qualities of the applications is all well and good but should not be done at the expense of efficiency and ease of use. If the application you are creating is an e-commerce site to support users that can never receive any training, the design must be modified to improve user-friendliness. However, just because you are deploying your payroll system over the web does not mean it has to look as though it escaped from a cartoon.
Step 7: Design and Build Application Components
Components that were difficult to build in a traditional Developer environment can now be built and used relatively easily in Java applications. Multi-select LOVs, calendar widgets, tree widgets and date fields with complex validation can all be written, tightly encapsulated and made easily available to developers.
The creation of these components requires skilled Java programmers. However, once these components are built, they can be seamlessly integrated into the applications. This means that your development team can have a mixture of functions. Some will be devoted to setting the GUI standards and testing and maintaining the components. Others will use the components to build and deploy the applications. This strategy assumes a number of people on your development team. If you are a small shop, you should probably avoid building a large library of components. Find a successful Java development environment, use its GUI and coding standards along with pre-built application components, and stick with what is provided. The JDeveloper tool suite alone is not sufficient for this purpose.
Deciding what components to build and how to build them is part of the artistry of the application design process. My co-author on the Oracle Developer: Advanced Forms & Reports (Oracle Press, 2000) book, Peter Koletzke and I have been building and working with Forms templates for years. Several years ago, we took our respective templates and combined them. Since then, our philosophies have diverged. I prefer to have a vast array of reusable components assembled with which to build applications. Peter uses a much small number of components and a very different user interface and style of application design.
Decisions about the appropriate objects to include in your architecture must be made early on in creating the appropriate development environment. Two similarly skilled teams could arrive at different but equally valid solutions to the same application development problem. Part of the inconsistent reception of the third party Forms template tools has been due to the fact that a template provides, not only a set of objects and utilities, but also an implied development style and user interface. If your vision is different from that of the template designer, then you will be unsatisfied with any applications that are built based upon that template. You either need to create your own template or be willing to modify your GUI standards and application development philosophy to match that of the template product designer.
Step 8: Expand Your Vision of Reusable Components
Java allows you to create whole portions of applications as reusable components. In Forms, we have been building larger and larger reusable components that fully abstract portions of the system. However, building such components using Developer was always a bit of a stretch. It was possible to build the structures to do what we needed them to do but not easily. This required us to try to make the Forms and Oracle DBMS products do things that they were never intended to do.
With a Java development environment, these formerly difficult tasks became straightforward. Larger application components that are completely encapsulated can be easily bolted onto other applications.
In Forms, we began by building small, isolated structures to handle odd utilities such as Comments. The data structures and details to support this were written up in the paper “Advanced Object-Oriented Design Using Developer/2000” which is available on the Dulcian website. This paper illustrates the roots of the reusable component idea. Since that time, we have created more and more structures to support various functionality within applications including:
· Audit History
· Field-Level Security
· Multi-Lingual Labels, Comments and Error Messages
· General Ledger
· Budget
Our philosophy has now evolved into building entire systems composed of fully abstract structures. For example, a system to process tax returns can be completely supported by the following abstract structures:
1. Parties
2. Party Obligations
3. Names, Addresses, Phones
4. Documents
5. Document Workflow
A full discussion of this topic is beyond the scope of this paper but it is included to explain why this new Java environment is so exciting for those of us who have been thinking along object-oriented lines for some time.
Conclusion
If you are not moving towards object-oriented development, the shift to a Java environment will be jarring, expensive, uncomfortable and not especially productive. If you are building forms through Designer generation or mostly hand-coding without SmartClasses, giving developers free reign to use their creative and professional talents, switching to Java development environment carries a huge cost and little benefit.
In a large development shop, without tight controls and clearly defined standards, chaos will ensue. Each developer will use his or her own style and there will be no consistency in the code or applications. In a Java/JDeveloper environment, it is critical to use a carefully thought-out set of GUI and development standards along with a library of the reusable components necessary to support your development environment.
If your thinking is moving in an object-oriented direction, including better ways of supporting increasingly abstract structures and taking advantage of code and application component reuse, the transition to a Java-based development environment will be liberating.
Java creates an environment that is flexible to a fault. Consider how Developer applications were developed by novices spending many hours writing complex triggers and trying to make the tool do things that it was not designed to do. With Java, the possibilities are virtually limitless.
About the Author
Dr. Paul Dorsey (pdorsey@dulcian.com) is the founder and President of Dulcian, Inc., (www.dulcian.com) an Oracle consulting firm that specializes in data warehousing, web and client-server systems development and products that support the Oracle environment. Paul is co-author with Peter Koletzke of Oracle Press’ Oracle Designer Handbook, Oracle Developer Forms and Reports: Advanced Techniques and Development Standards and with Joseph Hudicka of Oracle Press’ Oracle8 Design Using UML Object Modeling. Paul is an Associate Editor of SELECT Magazine and is President of the NY Oracle Users’ Group.
© 2000 Dulcian, Inc.