Achieving the 3rd Dimension of Java Freedom with Extreme Decoupling
In my last blog entry I introduced the concept of Technology Independence as the often overlooked Java freedom. The idea is to keep the core logic of an application decoupled from the technology that delivers it. Then as selected technologies change, in our case clients are demanding web over Swing, the bulk of an application, the business logic, may be brought forward to the new platform with minimal effort. To better explain the concept I will delve into my experience at ASIX, Inc. while writing the Java Business Framework.
Extreme Programming was developed from the concept that if a practice is good (such as testing) then doing it all the time (Test Driven Development) is better. My focus is on decoupling, which tells us that we should separate out pieces of code that should change independently. Packages and visibility are ways that Java enforces decoupling. If we agree that decoupling in our code is good then decoupling our code from the technology that we wrap it in for delivery is better. Let’s call it Extreme Decoupling.
Say we want to keep our options open throughout the lifetime of our project and be able to switch between a number of Java solutions for delivering user interfaces and backend services. For the client let us focus on using a local Swing client or a client that runs on a remote web server using Servlets. On the backend we will choose between running in a single JVM or with distributed JVMs using Jini. The goal is to design and code an application and be able to switch between client technologies and server deployment options to best fit the needs of the current customer.
The UI Problem
Applying top-down techniques we can pull out the commonality of the options and isolate the variability behind pluggable objects using factories. You might be thinking, “What could possibly be common between Swing and Servlets?”, or something similar. Let me further define the problem by saying our application is a standard business application where users need to create business object, enter attributes, apply validation rules and save results. So we are talking about editing objects via forms and storing the results in a data store, which are both done similarly whether the UI is Swing or web.
The UI Solution
What is so different, from the user’s perspective, between entering data into a web form versus a Swing form? The user sees the same attributes displayed in basically the same components with almost the same behavior. The words that standout in this statement are “basically” and “almost”, but focus on “same” for now. Two pieces are needed to implement the sameness in a framework. The first is an abstract user interface definition that can be rendered in Swing or HTML. The second is business object metadata that is used to map attributes from the UI definition to the correct component type in the specific UI technology, for display or editing. So given “Month.Days” we find the Month class and a method called getDays() that returns a List of the days of the week and based on the return type of List. Given the return type we know that the Days should be displayed in some sort of multi-select widget.
We solve the problem of “basically the same components” by providing a factory for Swing components and a factory for HTML components as well as the ability to look up the correct physical component corresponding to “some sort of multi-select widget”. We already had a solution that worked with Swing and other heavy client-side components like AWT or SWT with the JuiPiter framework. Our project was already using JuiPiter, which ASIX developed and released, to switch between using standard Swing components and the set of custom Swing Components from Infragistics. So we took JuiPiter and have been extending it to handle web components from the open source Millstone web framework, see millstone.org for details. The component portion is working fine and our focus has shifted to sharing as much behavior, like component-based listener actions, as possible between Swing and Millstone apps. The new expanded web version of JuiPiter will be open sourced later, but you can find out about the Swing version at, http://sourceforge.net/projects/juipiter/
The Backend Problem
With the single JVM option, we want to be able to run the client and server within one JVM and later deploy into a multi-user environment with no additional developer effort. The single JVM speeds-up development by allowing us to run the backend in the same JVM as whichever UI technology we have selected. The multi-JVM option allows us to handle concurrent clients and to scale the application.
The Backend Solution
The single JVM part turned out to be the easiest problem to solve. We opted for a Jini solution, which relies on a new version of RMI called JERI. We are then able to swap out Jini and run the POJOs and O/R mapper in the same JVM as either Swing or Tomcat. We used the pluggability of JERI to override how objects are exported to hide the differences between running in local mode versus remote mode. We then used a Jini design pattern called Smart Proxy to hide the fact that the server is running on the client.
When using the multi-JVM option we look up a single Jini service that connects to a server running plain old Java objects (POJOs) sitting on top of an object relational (O/R) mapper that abstracts the database.
I am glossing over the details here, so if there is interest, I will write other blog entries covering how well Jini works in an enterprise environment, the Smart Proxy pattern and the trick we pulled with JERI to make the single JVM seamless.
Achieving Technology Independence
While this series of blogs may sound like a vendor or open source product pitch or even a pipe dream, the takeaway should be that it is possible to avoid locking ourselves into specific implementation technologies. Also notice that all of the technologies mentioned are freely available with source code and that having source code provides additional long-term benefits.
Staying technologically agnostic takes some thought and effort plus it only works within a limited range of similar technologies. For example, we initially wrote JuiPiter for Swing, but were able to adapt it to support the Swing-like Millstone open source web framework. JuiPiter should also extend well for Java Server Faces, as JSF has a similar server-side component model. But if an upcoming or alternate technology is radically different, there is less chance of a clean conversion from the current technology. Accepting that there are limits, pursuing the goal of staying technology independent will make current development, testing and deployment much easier and will lessen the cost of future conversions.
I have seen the benefits of technology independence and they are huge. We can save time when coding by fine–tuning our environment to speed the development cycle. We can also configure the deployment environment to be only as complex as needed to support scalability requirements. Using the discussed options as an example, this means that if I am using the web front-end I can choose to run the full backend inside of Tomcat’s JVM for a smaller user-base installation. For a larger installation, I slip in Jini and run the backend on a separate machine and get the scalability that I need.
Though the time and cost may be high for a completely independent solution, even small steps that keep application code divorced from the deployment technology can provide great savings. An obvious example is that testing is much easier if the test can be run without a supporting infrastructure or container. If the code is all Java then it can be unit-tested and debugged very quickly. With a bit more effort a whole system can be run without a container and the whole suite of QA tests can be run quickly and easily. This means that the tests will be run more frequently, say, as part of a nightly build.
Technology independence saves development time today, keeps deployment options flexible and reduces future risk. If any of these goals spark your interest then start finding ways to break technology ties and achieve freedom for your Java code. Start practicing Extreme Decoupling today.