Monday, May 25, 2009

The Curious Case of Web Services Migration - Part I

Vladimir Serebryany, Senior Consultant

During one of my recent BEA WebLogic to IBM WebSphere migration assignments at a major insurance company, I encountered an interesting problem.

The client had a large number of Web services which were running on BEA WebLogic and consumed by a .NET front-end. In the course of migration, our team had to not only migrate code to WebSphere but also help the customer refactor the source code repository and create a set of Maven scripts to provide a fully scripted build/deploy process for all environments - from unit test to production.

We started with the typical set of issues:
  • WSDL files and corresponding XSD files had relative namespaces in them - and the spec strongly recommends absolute ones
  • Source code was stored in typical WebLogic structures and deployable components were created by running four (!) different Ant scripts
  • Code and WSDL files were stored in PVCS and the revision history had to be preserved
  • WSDL2Java wizard was invoked every time scripts ran so binding Java code would be generated on the fly and not stored in PVCS - wise decision but binding implementation classes with client's code in them had to be preserved from being overwritten.

The first issue was easy to deal with – a couple sed/awk scripts took care of the namespaces. We gave WSDL files back to client; they validated them against their .NET environment and found no problems with new namespaces.

Item #2 was also relatively easy to solve - we manually rearranged code into a Rational Application Developer (RAD) structure and that was it. RAD is really good at that sort of thing. While doing that we also extracted PVCS archives as files from the central repository and rearranged these archives in the file system according to the new directory structure. We sent back these directories to the client’s PVCS team, and they imported these archives back into a new PVCS project. That way all the previous generations of source code have been preserved. We now were able to work with PVCS and track a file’s revision history right back to Noah's Ark.

Now we had to deal with WSDL to Java files generation. There were three sorts of files: custom code with business logic, binding code and classes generated from data types definitions in XSD files, and binding implementation classes. We did not have to worry about the first two types: the first set was permanent code which we shifted to another utility’s Java project for simplicity of maintenance. Generated Java was what it was - generated code which the wizard took care of, only the binding implementation classes was something we had to take care of. On one hand all the methods stubs are generated by the WSDL2Java wizard - on the other hand these methods already contained the customer's code. If we allowed the wizard to run "freely," this code would be overwritten.

Here we needed a trick and we found one. As it is well-known, RAD may designate one or more folders in the project to be the Source folders - meaning it will compile all Java code in these and only these folders into binary form. It happens that built-in RAD wizards are very sensitive to the order in which Source folders are listed in "Order and Export" tab of "Java Build Path" configuration page. If the WSDL2Java wizard for bottom-down Web services generation is invoked either from the pop-up menu or from the wsgen.xml script, it always places all generated files into the folder listed first in "Order and Export" tab. That "observation" provided us with opportunity to solve the problem. We would define two Source folders: “src/main/java” and “src/main/java2.” “src/main/java” would be listed first in "Order and Export" tab, “src/main/java2” would be the second. The single "target/bin" folder was designed for binary files. We placed all existing binding implementation files into “src/main/java2” folder, and we put WSDL and XSD files into a separate project. (Note that by using “src/main/java” folder structure we were shooting to use Maven.)

From that point on, if a WSDL definition changed, we would clean “src/main/java” folder and run the Web services wizard/script against new WSDL/XSD files. Newly generated binding files would go into “src/main/java” folder. As long as binding implementation files were also on the classpath, WSDL2Java wizard was smart enough to not regenerate *BindingImpl.java files, but rather pick them up from “src/main/java2” folder. IBM provided ws_gen Ant task, script and sample properties files were customized to run the whole task at any time for all 20 WSDL's we had in the service definition (see http://publib.boulder.ibm.com/infocenter/radhelp/v7r0m0/topic/com.ibm.etools.webservice.was.creation.core.doc/ref/rtdwsajava.html). We didn't include “src/main/java” folder into PVCS and never had to check-in transient generated code.

The remaining issue to solve was to reproduce in RAD the style in which WebLogic's WSDL2Java script generated the code. By tweaking WSDL2Java options on Window->Preferences->Web services->Websphere->JAX-RPC Code Generation->WSDL2Java tab in RAD, we matched the style of generated code so that RAD-generated code was almost drop-in replacement for WebLogic-generated code. The problem was solved - but only for development phase so far.

Coming in Part II: “My initial feelings were anger and frustration as Maven-enabled RAD essentially diminished RAD to be just a fancy code editor - and nothing more. Gone were round-trip interactive development, and my productivity as a developer really suffered. Only by the end of the project I found out how to keep RAD effective and fully engaged and still be able to build using Maven…”

Vladimir Serebryany is a Senior Consultant at Prolifics with in-depth knowledge and broad hands-on experience with the J2EE environment as well as expertise in EJBs, Servlets, JSP and JSF. Excelling at migrations, Vladimir has over 9 years of experience with a wide range of complementary skills including WebSphere, WebSphere MQ, WebSphere Business Integration Message Broker, UNIX, C/C++, Java, HTML/ASP, JavaScript, and Visual Basic. He has served as team leader/senior developer roles in large, complex projects and configurations with clients in the financial, insurance and telecommunication industries - among others.