Adding several URIs to SOAP Envelope using Java - java

I am trying to write a SOAP pull. I am running into difficulty formatting the message correctly.
I am only using the included javax.xml.soap.* library with Exclipse
I need the Envelope to have multiple URIs in it. This is the example provided for use with SOAPUI.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sh="http://www.website.com/ems/soap/sh" xmlns:user="http://www.website.com/ems/soap/sh/userdata" xmlns:ser="http://www.website.com/ems/soap/sh/servicedata">
However after looking through several tutorials I am only able to produce
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sh="http://www.website.com/ems/soap/sh">
I have haven't been able to find any documentation on how to achieve the required output. I am still new to SOAP and Java so I am not sure how to articulate exactly what I need.
Here is the code I have so far minus the child element portion
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
soapMessage.getSOAPPart().getEnvelope().setPrefix("soapenv");
soapMessage.getSOAPPart().getEnvelope().removeNamespaceDeclaration("SOAP-ENV");
soapMessage.getSOAPBody().setPrefix("soapenv");
soapMessage.getSOAPHeader().setPrefix("soapenv");
String serverURI = "http://www.website.com/ems/soap/sh";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("sh", serverURI );

If you want to get this soap-envelope,
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sh="http://www.website.com/ems/soap/sh" xmlns:user="http://www.website.com/ems/soap/sh/userdata" xmlns:ser="http://www.website.com/ems/soap/sh/servicedata">
Just add addNamespaceDeclaration after your code like this.
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("sh", serverURI );
//added code here
envelope.addNamespaceDeclaration("user", "http://www.website.com/ems/soap/sh/userdata" );
envelope.addNamespaceDeclaration("ser", "http://www.website.com/ems/soap/sh/servicedata" );

Related

Dynamically adding namespace to SOAP Envelope in Java

I am new to all of this but I am trying to create a SOAP message and get stuck at the off, I am using Java 8 and the standard javax.xml.soap classes but seem unable to add namespaces to the Envelope
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPPart part = message.getSOAPPart();
SOAPEnvelope envelope = part.getEnvelope();
envelope.addNamespaceDeclaration( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
If I try this at runtime I get the following error
NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
I have done this now by creating the required envelope definition as an XML String and then setting the SOAPPart content using that string

How do you programatically encrypt SOAP messages in Java?

I'm creating a SOAPMessage object, and before I send it I want to encrypt the contents. I'm creating it in a similar way to many examples that can be found on SO, for example:
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
// Retrieve different parts
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
// Two ways to extract body
SOAPBody soapBody = soapEnvelope.getBody();
soapBody = soapMessage.getSOAPBody();
//Modify body
// Etc
I can't find examples of how to encrypt the contents of an object that I create like this.
Soap Encryption is different from normal encryption process we do, as Encrypted XML payload has to be in a standard structure specified by WS-Security.
Use any WS-Security implementation like Axis, WSS4J.

From WDSL to java

I've been tasked with querying a soap client in java and i'm a bit confused as how to move forward.
The first thing i did was use the Wizdler chrome plugin to prototype my SOAP request. The soap "envelop" must be of this format I believe for it to work.
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
<Body>
<GetMyProjectCharges xmlns="http://COMPANY.IWWeb.Data.Service.ProjectCharges">
<Employee>[string?]</Employee>
<FiscalYear>[string?]</FiscalYear>
<ApiKey>[string?]</ApiKey>
<AppName>[string?]</AppName>
</GetMyProjectCharges>
</Body>
</Envelope>
Next I've gone through some various tutorial as how to build a soap envelop in java but i keep getting into a strange situation where i'm getting <SOAP-ENV: prefixes on everything and when i take the generated envelop and try to paste it into the chrome plugin it doesn't work.
So I'm wondering where I go from here? I realize soap is a pretty heavy protocol and so maybe that is what is confusing me but what I'm looking to do (for now) is:
1) Generate a soap request in java that matches the format above, and print out the results.
I understand i "might" have the option of Maven or some program to generate some class files for me from the WDSL but I'm not exactly sure what i do with that either. Thanks!
Any help would be appreciated.
You have two way to do a soap request.
Solution 1
If you use netbeans as code IDE, you have to create a project, right click on a package and choose New >> Web Service Client. Insert the url of the soap endpoint and click ok. If you have jax-ws/Metro extension installed in your ide netbeans will generate all necessary classes to invoke the service programmatically. (ask me if you have troubles)
Solution 2
you could realize a soap request using simply javax.xml
private SOAPMessage invoke(QName serviceName, QName portName,
String soapActionUri) throws Exception {
Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
Dispatch dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);
dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, new Boolean(true));
dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, soapActionUri);
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPBody body = envelope.getBody();
Source source = new DOMSource(getQueryString());
soapPart.setContent(source);
message.saveChanges();
System.out.println(message.getSOAPBody().getFirstChild().getTextContent());
SOAPMessage response = (SOAPMessage) dispatch.invoke(message);
return response;
}
private Node getQueryString() throws SAXException, IOException, ParserConfigurationException {
StringBuilder builder = new StringBuilder();
builder.append("<soapenv:Envelope");
// create your body
builder.append("</soapenv:Body>");
builder.append("</soapenv:Envelope>");
DocumentBuilderFactory docfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docbuilder = docfactory.newDocumentBuilder();
Document stringDocument = docbuilder.parse(new InputSource(new StringReader(builder.toString())));
return stringDocument;
}
and to call the service use
String targetNameSpace = "your target namespace";
QName serviceName = new QName(targetNameSpace, "your service name");
QName portName = new QName(targetNameSpace, "Your port name");
String SOAPAction = "your soap action";
SOAPMessage response = invoke(serviceName, portName, SOAPAction);
if (response.getSOAPBody().hasFault()) {
System.out.println(response.getSOAPBody().getFault());
}
P.S. forgive me for my english :(
I am not sure if I got the point. Anyway I think you need to have the correct namespace for your soap messages. A blank SOAP message would look like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
So in your case I think this should work:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<GetMyProjectCharges xmlns="http://COMPANY.IWWeb.Data.Service.ProjectCharges">
<Employee>[string?]</Employee>
<FiscalYear>[string?]</FiscalYear>
<ApiKey>[string?]</ApiKey>
<AppName>[string?]</AppName>
</GetMyProjectCharges>
</soapenv:Body>
</soapenv:Envelope>
But normally you use a namespace in the payload as well (which means GetMyProjectCharges would be something like jeef:GetMyProjectCharges).
Watch the 2nd namespace in the root tag
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:jeef="http://COMPANY.IWWeb.Data.Service.ProjectCharges">
<soapenv:Header/>
<soapenv:Body>
<jeef:GetMyProjectCharges>
<jeef:Employee>[string?]</jeef:Employee>
<jeef:FiscalYear>[string?]</jeef:FiscalYear>
<jeef:ApiKey>[string?]</jeef:ApiKey>
<AppName>[string?]</jeef:AppName>
</jeef:GetMyProjectCharges>
</soapenv:Body>
</soapenv:Envelope>
To parse the SOAP messages it would be a good choice to use some wsdl to objects conversion tool. There are maven plugins for this as you already found out. To process the SOAP messages it would be worth to take a look at Apache Camel.
Note: namespaces are defined by xmlns:whatever="http://some.url.to.a.model/".
#Jeff you have to do something like this :
MyWebService service = new MyWebService(new Url(wsdlStringEndpoint));
Port port = service.getHttpsoap11port();
port.makerequest();
I've wroted a genericall call to make you understand how it should look. If you have some problems ask again (the code is a sample code)

How do you add XML prolog in javax.xml.soap.SOAPBody

I am trying to send an XML document via SOAP to a server that requires the payload XML to contain an XML prolog e.g., <?xml version="1.0" encoding="utf-8" ?>. The following is very similar to the code I'm using:
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPPart soapPart = getSoapMessage().getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
soapHeader = envelope.getHeader();
soapBody = envelope.getBody();
soapHeader.detachNode();
SOAPBodyElement bodyElement = soapBody.addBodyElement(getEnvelope().createName("my_element_name"));
bodyElement.addAttribute(getEnvelope().createName("my_attribute_name"), "my_attribute_value");
bodyElement.addChildElement("my_child_element");
...
A XML prolog can only exist at the very start of a XML document.
From the XML Specification available here : http://www.w3.org/TR/2000/REC-xml-20001006#sec-prolog-dtd
The document type declaration must appear before the first element in the document.
Writing a prolog in the middle of a SOAP document, therefore, is invalid - and I doubt you'll find a SOAP library or implementation that will allow you to do that. There may be a requirement you and/or your "client" have misunderstood in requiring this.
You can try a XML validator softare (e.g. http://www.w3schools.com/xml/xml_validator.asp ), it should report an error for your expected result.
Here is how to add xml prolog declaration right before the first SOAP Envelope tag:
soapMessage.setProperty(SOAPMessage.WRITE_XML_DECLARATION, Boolean.TRUE.toString());

JAX-WS get soap without actually sending to a web-service

Using JAX-WS and a custom WSDL, is there a way to get the message that would be sent to a web-service without actually making a call to the service? I need to generate a soap message conforming to a WSDL, but that soap message is actually embedded into another message. I was thinking I could create a local web-service that just echos back the message but it seems like there should be a way without doing this or using a handlerchain when it doens't really matter that the message is sent.
Maybe the easiest thing to do is just to generate the soap manually?
I hope this helps:
http://www.java-tips.org/java-ee-tips/java-api-for-xml-web-services/writing-a-handler-in-jax-ws.html
You can intercept message before being sent, get the body, get the header, sign it with SAML or whatever you want, and then send it to server.
maybe this example helps (from Understanding Web Services, Part 1: SOAP, IBM Developer Works, page 21):
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage();
SOAPPart SOAPPart = message.getSOAPPart();
SOAPEnvelope envelope = SOAPPart.getEnvelope();
SOAPBody body = envelope.getBody();
SOAPElement bodyElement = body.addChildElement(envelope.createName("echo", "req", "http://localhost:8080/axis2/services/MyService/"));
bodyElement.addChildElement("category").addTextNode("classifieds");
message.saveChanges();
SOAPPart SOAPpartbefore = message.getSOAPPart();
SOAPEnvelope reqenv = SOAPpartbefore.getEnvelope();
System.out.println(reqenv.toString());

Categories

Resources