Archive for March, 2013

Retrieving a MIME-encoded binary attachment through MTOM with ColdFusion 10

March 6, 2013

Setup:
A Oracle Weblogic (BEA) Web Service returning mime-encoded binary documents (word or pdf) in attachment through MTOM, matching the metadata specified in the request.
A client running on ColdFusion 10, using the automatically generated stub from the WSDL of the Web Service using axis2.

To start, we have ColdFusion generate the stub by invoking the WSDL:

variables.ws=createObject("webservice","http://testserver/CarsDocContentServiceWS/CarsDocContentServiceWSPort?WSDL",{wsversion="2",refreshwsdl="false",timeout=500});

Iomportant: we need to specify wsversion = 2 to force ColdFusion to use axis2. Refreshwdl can be false, we only want the stub to be generated once. Regenerating it each time is time-consuming.
To see what we get back from the Web Service it is always a good idea to dump it:

writeDump(variables.ws);

dump of the webservice and its methods

The method we are looking for is getmanifestationcontent. The first 8 variables are the metadata we need to provide, the last 5 are returned by the Web Service. I create a placeholder for them.


variables.result=StructNew();
variables.result.filenameOut='';
variables.result.errorMessage='';
variables.result.errorCode='';

All set up to invoke the method on the webservice:


variables.response=variables.ws.getmanifestationcontent('MYACC','ST',JavaCast("bigdecimal",5007),JavaCast("bigdecimal",2012),'INIT','EN','INTRA','PDF',JavaCast("bigdecimal",1),variables.result.filenameOut,dhl,variables.result.errorMessage,variables.result.errorCode);

Some of the metadata we passed in had to be casted to the expected datatype. The one oddity in this particular webservice was the ‘dhl’ variable that matches the expected javax.activation.DataHandler data type. Since this is a returned argument, I expected it would be enough to pass just the name of an empty variable and the stub would automatically return a DataHandler object. But the webservice refused to accept any null valued arguments, so I had to build a empty DataHandler object in which even the DataSource had to be specified, even if it would never be used on the Web Service. So I added these 2 lines of code prior to the invocation of the Web Service.


fds=CreateObject("Java", "javax.activation.FileDataSource").init('c:\temp.pdf');
dhl=CreateObject("Java", "javax.activation.DataHandler").init(fds);

Time to look at the response of our request. I would have expected the response to be in the DataHandler variable dhl. But this was not the case. The attachent was in the response of the invocation of the getmanifestation method itself.
So, again, I dumped it to see what I was dealing with.

writeDump(variables.response);

manifestationcontent response

Clearly, the filename was in the get_FileName_out() method:

saveToFileName="c:\"&variables.response.getFileName_out();

Now the only thing left is to get the binary attachment and I saved it locally to the disk. The getFileContent_out() contained the getInputStream() i was looking for. So I could loop through that until the end-of-file and stream it to the local disk:


inputStream=variables.response.getFileContent_out().getInputStream();
outStream=createObject("Java","java.io.ByteArrayOutputStream").init();

byteClass=createObject("Java","java.lang.Byte").TYPE;
byteArray=createObject("Java","java.lang.reflect.Array").newInstance(byteClass, javacast("int", 1024));
length=inputStream.read(byteArray);
offset=0;
while (length GT 0) {
outStream.write(byteArray,offset,length);
length=inputStream.read(byteArray);
}
outStream.close();
inputStream.close();
FileWrite(saveToFileName,outStream.toByteArray());

While dumping the objects returned from the Web Sevice, I noticed that the Oracle WebLogic WebService used the Apache James Mime4J library. Since it was not by default in my list of libs that ColdFusion is using, I had to download it and put it in the cfusion/lib directory. I didn’t need to reference it anywhere in my code, but it would not run without it, specifically throwing an error telling me that ColdFusion could not find a specific class within this library.