Legacy code integration using Windows Communication Foundation (WCF) and Java Axis in a Service Oriented Architecture
What are the options when you need to integrate Windows legacy code in a heterogeneous Service Oriented Architecture (SOA)?
The proposed problem was to expose a set of Windows C++ DLLs to a global SOA platform written in Java. Those DLLs would be then exposed as backend computation services.
One of the options used in some past projects was to use the Microsoft SOAP Toolkit. But your C++ DLLs needs to be COM Objects for that. I experienced it and still have production code running with it. It works quite well even with surprising complex data structures. But as today it is definitely not the way to go.
The service oriented world has evolved rapidly over the last years and using such an old deprecated technology (Microsoft SOAP Toolkit) is not really efficient for a project.
So at last it was time to check .NET in this entire Java world ;-)
The general idea was to define a layered solution. From bottom up I first defined an interoperability layer using .NET Interop to be able to call the C++ DLLs from .NET. Then on top of this first layer I added another layer exposing the whole as a web service.
Now that I had the backend web service working I had to call it from Java. So are all those promises of web service interoperability just working out of the box?
Yes and No. You need to first have a real look at the different frameworks stack you want to use. For example, when you are working with Java Axis you are tied to SOAP 1.1, so you have to take care that the other side can understand this version of the SOAP standard.
So what do I have? First I have a client that must be written in Java using Axis 1.2-1.4 using SOAP 1.1, then a C++ Windows DLL backend that must be exposed in an interoperable way. By luck I was free to choose the technology used on that backend. Both ASP.NET web services (ASMX) and WCF can interoperate with the SOAP 1.1 standard, so I decided to go on with C# and WCF.
The way I approached the problem was to go on iteratively, making a first proof of concept to integrate the C++ layer with the .NET layer, then to integrate this upper layer with WCF and a .NET client to finally finish with a Java client.
Due to the ease of the interface exposed by the web service I didn’t wrote it using data contract design first. In more complex scenarios I would definitely go on with it because it leads to better success with interoperability.
So I finally adopted the following final solution.
Adopted solution
On the backend a Windows Communication Foundation web service written in C# using the .NET Framework 3.0. The web service layer uses .NET interop to make a call to the legacy C++ Dlls.
On the client side; a Java 1.5 proxy/stub class generated using WSDL2Java out of the WSDL exposed by the service.
Hosting
The last question concerning the web service was to define the way I wanted to host it?
Two possibilities in my case: Windows Service and Internet Information Services (IIS).
After making some load test on the web service I realized that it was leaking memory so I finally went to the IIS solution because it provides you all the services for recycling a buggy process. It was also easier because some part of the deployment process for web services hosted in IIS were already implemented and tested.
Faced problems
The first minor thing I went through was to check which versions of WCF and Axis are compatible.
Then the C++ interop was the main work because it is not such an easy task to marshal between the different worlds in a correct way.
And finally the last one was that the legacy C++ Dlls where using ifstream to load configuration ini files, without a possibility to specify the full path of those files. As the web application was running in the Application Pool process (w3wp.exe), loading the ini file was using the base path of w3wp.exe; C:\WINDWS\System32\inetsrv. That would force me to deploy the ini files in that folder. What an ugly solution. Adding the bin folder of the application to the PATH was not making the trick too. And as we couldn’t change the C++ Dlls I had to find something else.
The solution I came to, thanks to David Wang (yes you also Richard ;-), was to use this little method before calling into the legacy Dlls, changing the current directory:
<span style="color: rgb(128,128,128)">///</span><span style="color: rgb(0,128,0)"> </span><span style="color: rgb(128,128,128)"><summary>
/// Sets the current directory.
///
private static void SetCurrentDirectory()
{
string binpath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, “bin”);
Directory.SetCurrentDirectory(binpath);
}
Conclusion
I really like the way WCF is handling the separation between the service description, the implementation and the configuration that will define how you expose the service to the world.
The other thing I still enjoy to see is complex systems using so different technologies talking to each other. Here we had a caller written in Java running on a Linux server calling a web service written in C# calling multiple C++ Dlls running on a Windows server.
I am still amazed about those little things!!!