I am trying to build a custom SOAP processor that will wrap services that I want to expose as doc/literal Web Services. In one post it was recommended to use pub.xml.NodeType to get the QName of the actual service that you want to call. I tried this but ran into problems. I figured that I could just extract the SOAP body and pass the body object returned from that into the pub.xml.NodeType. This did not work. I get the following message: com.wm.app.b2b.server.ServiceException: [ISS.0086.9090] Parameter rootNode is of incorrect type
The only way I could get it to work was using the following sequence in my custom SOAP processor flow:
This seems awfully clunky. I figure I must be doing something wrong. Any ideas? Would it be better to use pub.soap.utils:getQName or stick with pub.xml:getXMLNodeType? I think that I can get the same values using both.
I get the same exception when passing the node returned by the pub.soap.utils:getBody into the pub.xml:getXMLNodeType. Interesting, since this node is perfectly valid to pass into the queryXMLNode service.
This sequence works for me to get the QName and optionally to convert the contents of the body node to a properly structured document type
pub.soap.utils:getBody to get a body node
pub.xml:queryXMLNode with the XQL queries /*/namespace() to get the namespace and /*/nodeName() to get the element name. /*/prefix() will also get the prefix although this is not usually needed
Based on the QName, derive document types or processing service names
You can pass the “body” node into pub.xml:nodeToDocument to populate an input document if you have derived the document type name from the QName, then you can populate the documentTypeName parameter.
You may need a utility service that renames the input document to the correct name.
The result of passing the soap body node to pub.xml:nodeToDocument is a document named “document” containing another document named : where could be any prefix supplied by the sender and is the name of the element inside the soap body.
Your target service, the one you want to invoke, is probably expecting a input document type named “createOrderRequest” or “createOrder” not “document\ns1:createOrder” or “document\foo:createOrder”.
My renameDocument java service accepts the document produced by the pub.xml:nodeToDocument service (Step 4) and the prefix and localName produced by the pub.xml:queryXMLNode service (Step 2) to produce a document called “renamedDoc” with a child document with a name equal to the localName without any prefix. There is probably a more elegant way to do this without having to pass in the prefix and localName.
When “renamedDoc” is mapped to the “inputs” document of a java service that invokes the target service, only the contents of “renamedDoc” are passed to the target service resulting in the target service only receiving a correctly named document type extracted from the soap body.
This posting of mine explains why you could not extract the SOAP Body and use the XML node as input to services such as pub.xml:getXMLNodeType or in my case pub.schema:validate.[INDENT][URL=“wmusers.com”]wmusers.com
[/INDENT]To make a long story long, pub.soap.utils:getBody does not actually return a valid xml node. For whatever reason, it does not contain the “<?xml version="1.0"?>” header and therefore subsequent services that use XML nodes don’t work. You’ll see in my posting that one solution to the problem is your approach below which adds the version header when you call pub.xml:documentToXMLString. Another alternative is to get the XML string from the SOAP body, append the xml version header to the string, convert the string back to a node and then use the node as needed (essentially the same thing).
I’m not sure why pub.soap.utils:getBody doesn’t return a “valid” XML node. I guess it makes sense that it simply returns the XML as it exists in the SOAP body, it just seems a little misleading as it implies that the node can be used in conjunction with other services that require XML nodes as input. Sounds like a bug to me!
Is it possible for you to post a copy of your renameDocument java service here. I thought I saw it somewhere already but haven’t been able to find it on this forum.
The attached java service removes the prefix from a document contained inside the “document” input parameter. This can be used to remove document prefixes from the top level of a document extracted from a soap message body.
Hi,
I was trying to expose one our existing process as a webservice and
trying to build a custom soap processor as mentioned in the other posts
and I’m coming across the same situation which the original poster has
pointed
I tried to use the following sequence
pub.soap.utils:getBody
pub.xml:xmlNodeToDocument
pub.xml:documentToXMLString
pub.xml:xmlStringToXMLNode
pub.xml:getXMLNodeType
But after step 3 the xml generated no longer has the namespace attribute
Not sure what I’m doing wrong here?
Your response is greatly appreciated.
That seems like a few too many steps. Once you have the body of the soap message as a node you can use pub.xml:queryXMLNode to extract the namespace, nodeName.
Why do you have steps 3, 4 and 5? What are you trying to accomplish with the pub.xml:getXMLNodeType?
OK, it looks like you were following the steps in the first post. I don’t think that is the correct approach.
Mark,
All I was trying to do after getting the soap body is get the name of
the document type(local name of the service) and
namespace (universal name of the service) which
I want to use to find the service dynamically and execute it
The problem i’m having is after the step2 there is no longer the
namespace attribute?
I have written a guide on how to build a basic custom soap processor following the standards we use at my place of work. Unfortunately it is a bit big to post here (5.8Mb word file), so if you are interested, drop me a line at craig.harper@westernpower.com.au and I will send you a copy.
It took over 2 months to work out, with lots of help from Mark, so maybe it will save you some time.