XML Soap Request coming in as a org.apache.xerces.dom.DeferredDocumentImpl Java Object

I'm using ColdFusion as a webservice implementation tool and am getting the request argument as an xml object.
I can view the entire soap request, but all I really want is the xml document object that is suppose to be passed to me. Unfortunately for my limited brain, The document isn't coming to me as a coldfusion XML object, it is classified as an object and is of class
org.apache.xerces.dom.DeferredDocumentImpl
Now, coldfusion, for those who don't know, now runs on java and I have access to the methods, etc of the underlying java class.
I can parse out the relevant data when I call the webservice because I'm passing a nice clean xml structure. Unfortunately, the partner who is sending me the real requests, is sending me an object that has MultiRef statements in it and the XML is all disjoint. I can't seem to use xpath on it because the path structure doesn't really have the nodes I need, they are referenced elsewhere and called in.

I'm a NOOB at all this so I'm not having a fun time (well, not as fun a time as I'd like).

Can anyone help me understand how I can take this
org.apache.xerces.dom.DeferredDocumentImpl
object with multiRef elements in it and get to to reconstitute as a fully realized xml string that resolves the multiRef in a manner that I can apply xpath to it?
LVL 16
RCorfmanAsked:
Who is Participating?
 
CEHJCommented:
>>as far as the DOM is concerned has no children, true?

Yes, it would seem it's empty
0
 
dberner9Commented:
DeferredDocumentImpl implements the Document interface.  See the following API:

http://java.sun.com/j2se/1.4.2/docs/api/

Also see the following for working with Document objects:

http://javaalmanac.com/egs/org.w3c.dom/pkg.html
0
 
CEHJCommented:
Just try taking it as a Document (which it implements) and serializing it to a String:


   public static String writeDocumentToString(Document doc) {
         String documentAsString = null;
        try {
            // Prepare the DOM document for writing
            Source source = new DOMSource(doc);
   
            // Prepare the output
            StringWriter sw = new StringWriter();
            Result result = new StreamResult(sw);
   
            // Write the DOM document to the file
            Transformer xformer = TransformerFactory.newInstance().newTransformer();
            xformer.transform(source, result);
            documentAsString = sw.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return documentAsString;
    }
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
CEHJCommented:
>>// Write the DOM document to the file

should say

// Write the DOM document to the String

of course
0
 
x4uCommented:
The xml was obviously already parsed for you as a DOM tree. This DeferredDocumentImpl object is the root of this tree. It provides several methods that allow you to access the data you want with methods like getElementById() or getElementsByTagName(). This will give you Node objects that you can ask for attributes with getAttributes() and getNodeValue() gives you the character data of an Element (Node object).

You can browse the entire API here: http://xerces.apache.org/xerces-j/apiDocs/index.html

If you still want to see the tree as xml string you can reconvert it to xml with some code like this:

DeferredDocumentImpl doc = <your doc>;
CharArrayWriter tmp = new CharArrayWriter();
XMLSerializer serializer = new XMLSerializer( tmp, new OutputFormat( doc ) );
serializer.serialize( doc );
String xml = tmp.toString();
0
 
RCorfmanAuthor Commented:
If you believe, as we work through this, you think I'm in the realm of a new question, don't hesitate to remind me...).

OK, so first, I'm using coldfusion, not java. I know I posted here, but it is because I know you all can help me work through this.  I did find the link regarding the api already and have played with that with some success.

The biggest problem I'm having is how to resolve the multiref on the soap.  I'm not sure if that got lost of not.  I also don't know how to instantiate other classes not directly related to this one, I don't know what classes are available to the coldfusion engine. I am sure, based on the API tree above, that I can call inherited methods (of course). I'm also going to make a good bet that other classes in that api are likely available to me.

First, and foremost on my list is to determine if, in the DOM that has been parssed, I have all the data needed to resolve the SOAP message.  How do I explore all the tags in the DOM passed to me?

If you know SOAP, you know there is an envelope that eventually leads to the payload. This xml DOM is just the payload. But the way the multiref works is that there is data outside the payload proper.  I don't know if all this was resolved so that indeed all the data I need is in the DOM.

I started with this (It isn't Java, but coldfusion, it should be obvious).  <cfdump> resolves variables/methods and outputs the answer to the browser.

----------------Code segment -----------------------
<p>Rbom Integration<br>
<p><cfdump var="parent=#rbom_integration#"></p>
<cftry>
<p><cfdump var="parent-name=#rbom_integration.getDocumentElement().getNodeName()#"></p>
<cfcatch type="any"/></cftry>
<cftry>
<p><cfdump var="parent-length=#rbom_integration.getDocumentElement().getChildNodes().getLength()#">
<cfcatch type="any"/></cftry>
<!---cfloop index="n" from="1" to="rbom_integration.getDocumentElement().getLength()">
<p><cfdump var="#rbom_integration.getDocumentElement().item(n).getNodeName()#"></p>
</cfloop--->
<cftry>
<p><cfdump var="first-child-name=#rbom_integration.getDocumentElement().getFirstChild().getNodeName()#"></p>
<cfcatch type="any"/></cftry>
-------------------------------------------------------
Output from above:
Rbom Integration
parent=[#document: null]
parent-name=rbom_integration
parent-length=0

There is no first-child-name, obviously because it threw and exception because it isn't there.  There has to be one though, per the .xsd. I know they are passing <rbom_request>, but it is being passed as a multiRef.
0
 
CEHJCommented:
>>There has to be one though, per the .xsd

What if the message contains an invalid Document?

I don't know what you mean by 'multiref'

I'm not sure of the syntax, but it would help if empty catch blocks could be avoided
0
 
RCorfmanAuthor Commented:
Yeah, I'm filling them in.  multiRef appears to be a valid tag in SOAP. it seems to be part of the soap seraliazing process in Websphere.  It seems to pull the document apart.  If I understand what I did with my code though, this document, as far as the DOM is concerned has no children, true?  It is esencially a <rbom_integration />
0
 
RCorfmanAuthor Commented:
This is the soap request that I'm getting that I'm struggling with:
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/><soapenv:Body soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><p705:subscription xmlns:p705="http://RBOM.whse"><rbom_integration href="#id0"/></p705:subscription><multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m301="http://CR036_1/DataTypes" xsi:type="m301:CMRBOMRequest_rbom_integration"><rbom_integration href="#id1"/></multiRef><multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m301="http://CR036_1/DataTypes" xsi:type="m301:rbom_request"><source xsi:type="xsd:string">Velocity</source><ip xsi:type="xsd:string">WingTipL2</ip><line_no xsi:type="xsd:string">LINENO9003845</line_no></multiRef></soapenv:Body></soapenv:Envelope>

This is the nice, clean version that I sent myself that I have no problem with:
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:subscription soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://rbom.whse"><rbom_integration xmlns:ns2="http://xml.apache.org/xml-soap" xsi:type="ns2:Document"><rbom_integration><rbom_request ip="WingTipL2" source="Velocity" line_no="LINEN09003845"/></rbom_integration></rbom_integration></ns1:subscription></soapenv:Body></soapenv:Envelope>

I've already told the people writing the other end of the integration that they are sending elements instead of attributes, for ip,source, and line_no, they are fixing that. What I have a problem with is the only argument I'm expecting is <rbom_integration><rbom_request ...... /></rbom_integration>  On my run at it, it appears this is what I'm getting. On their's with the multiRef, it doesn't appear to be passing the right data.  I'm not sure if they are siblings, or what... I didn't think you are allowed siblings of the root, which means I'm out of luck with mutiRef on the argument and am going to have to manually resolve the multiRef stuff. It doesn't seem right though that I should have to do that, there should be code that does that all for me. errrrr.

0
 
RCorfmanAuthor Commented:
I have access to the full soap header... is there something that should have been done to pass me back a 'resolved' soap payload?
0
 
CEHJCommented:
As a general principle, you should probably be making them validate the content before sending it, such that it doesn't get sent at all unless it's valid. Then there can be no doubt about it

It would appear the their message is multi-reffed as you say. Yours appears to have nested rbom_integration, although it's all difficult to read as it's unindented
0
 
RCorfmanAuthor Commented:
Yes, that is true. They are fixing the attribute. Once they get their definition right, they assure me it will be validated to the definition. No problem. My problem is how to resolve the multiRef. I'm guessing that it didn't make it into the passed DOM.  I'm going to guess that the only thing in the passed dom is
<rbom_integration href="#id1"/>
and this is correct as my webservice is <subscription> and the argument is <rbom_integration>.
In my method of the soap call I get:
<rbom_integration><rbom_request ip="WingTipL2" source="Velocity" line_no="LINEN09003845"/></rbom_integration>
passed in by the dom, in their's I get
<rbom_integration href="#id1"/>

ugg.
0
 
CEHJCommented:
Theirs has the same info referred to by multiref. I would be as surprised as you if you need to resolve these references. 'manually'. What API are you doing all this with?
0
 
RCorfmanAuthor Commented:
I'm not, coldfusion is.  I define an argument (name rbom_integration) for my webservice ( named subscription) that is an xml type. in the WSDL, it translates to:
<wsdl:part name="rbom_integration" type="apachesoap:Document"/>

When it is passed to me by the coldfusion engine, it is an
org.apache.xerces.dom.DeferredDocumentImpl
that appears to be <rbom_integration href="#id1"/>
0
 
CEHJCommented:
>>I've already told the people writing the other end of the integration that they are sending elements instead of attributes

Are you sure that this is the case? The multiref reference is given as an attribute, not an element

Maybe you should try

<cfdump var="parent-length=#rbom_integration.getDocumentElement().getAttributes().getLength()#">
0
 
RCorfmanAuthor Commented:
ok, but there should be one element anyway, the rbom_request
I'm adding that code... few minutes.
0
 
RCorfmanAuthor Commented:
Here is the output. attributes length is 1, but it is interesting, I can't get .item(1) for it, it fails...

Rbom Integration
parent =rbom_integration
parent-length =0
loop children
first-child-name exception( [empty string] )
attribute-length =1
loop children attrs get attributes: get item( 1 ): exception( The selected method item was not found. ) exception( The selected method item was not found. ) exception( The selected method item was not found. )

Here is the code right now.  I think I'm going to close this though as I believe I got my answers, I can interrogate this object somewhat. It doesn't appear to have the entire data. I'm going to have to go to the envelope... or get them to pass me a string with the xml in it that doesn't attempt to use multiref.

<p>Rbom Integration</p>
<p>parent
<cftry><cfdump var="=#rbom_integration.getDocumentElement().getNodeName()#">
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

<p>parent-length
<cftry><cfdump var="=#rbom_integration.getDocumentElement().getChildNodes().getLength()#">
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

<p>loop children
<cftry>
<cfset toval=rbom_integration.getDocumentElement().getLength()>
<cfloop index="n" from="1" to="#toval#">
 <cftry><cfdump var="<br>#rbom_integration.getDocumentElement().item(n).getNodeName()#">
 <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
 </cftry>
</cfloop>
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

<p>first-child-name
<cftry><cfdump var="=#rbom_integration.getDocumentElement().getFirstChild().getNodeName()#">
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

<p>attribute-length
<cftry><cfdump var="=#rbom_integration.getDocumentElement().getAttributes().getLength()#">
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

<p>loop children attrs
<cftry>
<cfset toval=rbom_integration.getDocumentElement().getAttributes().getLength()>
<cfloop index="n" from="1" to="#toval#">
 <cftry>get attributes:<cfset attr=rbom_integration.getDocumentElement().getAttributes()>
   <cftry>get item(<cfdump var="#n#">):<cfset node=attr.item(n)>
     <cftry>get item.name:<cfset itemname=node.getNodeName()>
     <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
     </cftry>
   <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
   </cftry>
 <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
 </cftry>
 <cftry><cfdump var="<br>name=#rbom_integration.getDocumentElement().getAttributes().item(n).getNodeName()#">
 <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
 </cftry>
 <cftry><cfdump var="<br>value=#rbom_integration.getDocumentElement().getAttributes().item(n).getNodeValue()#">
 <cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
 </cftry>
</cfloop>
<cfcatch type="any"> exception(<cfdump var="#cfcatch.message#">)</cfcatch>
</cftry></p>

I'm also going to complain to Adobe, I don't think they did a good job of implementing type="xml" on their webservice objects. It is broken. MX7, the version we are on has this as a new feature... I don't think it was well tested or so it appears from my knothole.
0
 
CEHJCommented:
Attributes are indexed from 0 to length - 1
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.