[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

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

Posted on 2006-03-25
19
Medium Priority
?
1,402 Views
Last Modified: 2013-12-16
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?
0
Comment
Question by:RCorfman
18 Comments
 
LVL 5

Assisted Solution

by:dberner9
dberner9 earned 150 total points
ID: 16292917
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16292925
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16292942
>>// Write the DOM document to the file

should say

// Write the DOM document to the String

of course
0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 
LVL 11

Assisted Solution

by:x4u
x4u earned 300 total points
ID: 16292948
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
 
LVL 16

Author Comment

by:RCorfman
ID: 16293944
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16294140
>>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
 
LVL 16

Author Comment

by:RCorfman
ID: 16294159
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
 
LVL 86

Accepted Solution

by:
CEHJ earned 1050 total points
ID: 16294173
>>as far as the DOM is concerned has no children, true?

Yes, it would seem it's empty
0
 
LVL 16

Author Comment

by:RCorfman
ID: 16294182
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
 
LVL 16

Author Comment

by:RCorfman
ID: 16294185
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16294220
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
 
LVL 16

Author Comment

by:RCorfman
ID: 16294231
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16294242
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
 
LVL 16

Author Comment

by:RCorfman
ID: 16294277
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16294323
>>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
 
LVL 16

Author Comment

by:RCorfman
ID: 16294332
ok, but there should be one element anyway, the rbom_request
I'm adding that code... few minutes.
0
 
LVL 16

Author Comment

by:RCorfman
ID: 16294670
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
 
LVL 86

Expert Comment

by:CEHJ
ID: 16294720
Attributes are indexed from 0 to length - 1
0

Featured Post

Get your Conversational Ransomware Defense e‑book

This e-book gives you an insight into the ransomware threat and reviews the fundamentals of top-notch ransomware preparedness and recovery. To help you protect yourself and your organization. The initial infection may be inevitable, so the best protection is to be fully prepared.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When setting up new project requests for our site, one of the most powerful tools our team has available to use is Axure (http://www.axure.com/). It’s a tool for creating software and web prototypes that can function and interact as if it were the a…
Objective of This Article In 1990’s, when I was a budding software professional, I had a lot of confusion about which stream or technology, I had to choose to build my career. In those days, I had lot of confusion like whether to choose System so…
The purpose of this video is to demonstrate how to prevent comment spam on a WordPress Website. This will be demonstrated using a Windows 8 PC. Plugin Akismet will be used. Go to your WordPress login page. This will look like the following: myw…
This video teaches viewers about errors in exception handling.
Suggested Courses
Course of the Month20 days, 11 hours left to enroll

865 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question