Tuesday, March 09, 2004


Oracle Bloggers Running Amok

Jeepers, the Oracle Bloggers are running amok ... I see today that Shay Shmeltzer, a huge JDeveloper advocate, has been blogging away for several months too.  Both of us were hired into the same group at Redwood Shores originally back in 2001 - he's ended up on the JDeveloper team and I have ended up on the OC4J team.



comment []
9:43:03 PM    

Sending a File to a Web Service 1

A recurring question folks seem to have in the Oracle Web services world and likely elsewhere is how to send a file to a Web service ... the typical use case being one or more XML documents from a partner, separate department or external client that needs to be shared/processed by a peer service.  This can be done in a number of ways - two outlined here:

  1. Read the file content as XML, turn it into an XML element and send it to a service endpoint where upon the service endpoint either works with it as is or writes it back out as a file to be dealt with by some other process.  This is quite easy in both OC4J 9.0.4 and 10.0.3 as this blog will show.
  2. Send the file content as an attachment to a Web service and again, as above, have the service endpoint  either process it or write it out to be picked up by some other process. This is possible in OC4J 10.0.3 using SAAJ, which I plan to tackle in another entry.

Recently, a customer had been asking me to provide a sample for #1 and I finally got around to getting this out today.  It's pretty easy to do once you have done it once; it's doing it the first time that seems tricky, especially to folks unfamiliar with XML and type support within Web services.

The Web service implementation is provided in below.   I did two things here - first, the inbound parameter is of type org.w3c.dom.Element, a supported parameter type in Oracle's and most other Web service implementations; second, I had the service endpoint write the inbound document out to a server file, another customer requirement.  I published this as a doc/literal Web service using the steps outlined in my JDeveloper Doc/Lit tip.  Remember from that entry the key thing is *not* to deploy the WSDL generated by JDeveloper (which is rpc/literal) so that the server side generates the correct doc/literal WSDL.  Here is the implementation:

package com.doc.server;
import org.w3c.dom.Element;
import java.io.PrintWriter;
import oracle.xml.parser.v2.DOMParser;
import oracle.xml.parser.v2.XMLDocument;
import oracle.xml.parser.v2.XMLElement;
import oracle.xml.parser.v2.XMLPrintDriver;
import org.w3c.dom.Document;
import java.io.OutputStream;
import java.io.ObjectOutputStream;
import java.io.FileOutputStream;
import java.io.File;

public class XMLDataHandler {

// Method to publish as  a Web service
public void WriteXMLFile(Element XMLData) {
 XMLDocument doc = new XMLDocument();
 XMLElement el = (XMLElement) XMLData;

 // Turn the inbound Element back into an XML document
 doc.adoptNode(el);
 doc.appendChild(el);
 // Stick the <?xml version="1.0"?> on the output doc

 doc.setVersion("1.0");
 try {
   // Now write out the document to a file

   XMLPrintDriver output=new XMLPrintDriver(new FileOutputStream(new File("/home/oracle/temp/result.xml")));
   output.setEncoding("utf-8");
   output.printDocument(doc);
   output.close();
 }
 catch (Exception e)  {
   System.out.println(e.toString());
 }

}
}

I then generated the client from the server WSDL (in my deployment available at http://127.0.0.1:8888/ws/XMLDataHandlerService?WSDL) and then did two things in the stub - first, I read the XML from a local file assuming it was an XML document; second, I converted it to an XML element and sent it off to the service endpoint published above.   Here is the relevant bit of code that does the work - this is the main method within the stub generated from the WSDL called XMLDataHandlerServiceStub.

  public static void main(String[] args)
  {
    Element inXMLFile = null;
    try {
      // Instantiate the Web service stub
      XMLDataHandlerServiceStub stub = new XMLDataHandlerServiceStub();

      // Read in some arbitrary XML document
      DOMParser parser = new DOMParser();

      parser.parse("
file:///home/oracle/temp/data.xml");
      inXMLFile = parser.getDocument().getDocumentElement();

      // Send the read in file data to the Web service endpoint
      stub.WriteXMLFile(inXMLFile);
    }
    catch(Exception ex) {
      ex.printStackTrace();
    }
  }

Not the prettiest code you've ever seen but it does the trick and gives hopefully the folks that are stumped with this problem a quick step up to a working example which can be easily enhanced to do things like schema validation, more efficient reads and writes etc etc.

Something to bear in mind with this approach is I had to read the entire document into DOM which can be a machine killer if your document is large; it is perfectly fine if your inbound file/document is small.  Larger documents likely need a different treatment - one being SAAJ.  For another day.

 



comment []
9:26:42 PM