javax.xml.stream.XMLStreamException when using Axiom to send a SOAP - java

I have the following code
final String METHOD="test";
final String PARAM1_VAL="Hello";
final String TARGET_EPR="http://bhanuka-TECRA-M11:8280/services/SoapToRestProxy";
SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();
OMNamespace samplesNamespace = factory.createOMNamespace("http://services.samples/xsd", "m");
SOAPEnvelope envelope = factory.getDefaultEnvelope();
OMElement requestElement = factory.createOMElement("request", samplesNamespace);
OMElement methodElement = factory.createOMElement("method",samplesNamespace);
OMElement param1 = factory.createOMElement("val",samplesNamespace);
param1.setText(PARAM1_VAL);
methodElement.setText(METHOD);
requestElement.addChild(methodElement);
requestElement.addChild(param1);
envelope.getBody().addChild(requestElement);
try {
ServiceClient serviceClient = new ServiceClient();
Options options = new Options();
options.setTo(new EndpointReference(TARGET_EPR));
serviceClient.setOptions(options);
OMElement response = serviceClient.sendReceive(envelope);
System.out.println(response);
} catch (AxisFault axisFault) {
axisFault.printStackTrace();
}
What I am doing is making a SOAP envelope and sending it to a specific Endpoint. but in the sendReceive method, it throws an
javax.xml.stream.XMLStreamException: Can not output XML declaration,
after other output has already been done.
What I am doing Wrong here ? somebody please help me.

ServiceClient#sendReceive(OMElement) doesn't expect a SOAPEnvelope as input, but the content of the SOAP body. Instead of passing it envelope, you should pass it requestElement.

Related

System property "javax.xml.soap.MessageFactory" for two different soap versions

i need to communicate with two webservices from my application.
For one webservice i need to use soap1_1 version and for the other soap version is soap1_2. In this case what should be the value set for the system property "javax.xml.soap.MessageFactory"
Client 1:
public class SoapClient1 {
protected static Logger _logger = Logger.getLogger ("TEST");
private static Long retryDelay = null;
public String sendSoapMessage (String xml) throws Exception {
SOAPMessage resp = null;
String response = null;
String endpoint = "http:xxxx";
System.setProperty("javax.xml.soap.MessageFactory","com.sun.xml.internal.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl");
SOAPConnectionFactory connectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = connectionFactory.createConnection();
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
//URL endPoint = new URL(endpoint);
//setting connection time out and read timeout
URL endPoint = new URL (null, endpoint, new URLStreamHandler () {
#Override
protected URLConnection openConnection (URL url) throws IOException {
URL clone = new URL (url.toString ());
URLConnection connection = clone.openConnection ();
connection.setConnectTimeout (60000);
connection.setReadTimeout (60000);
// Custom header
return connection;
}});
try{
start = System.currentTimeMillis();
resp = soapConnection.call(getSoapRequest(xml), endPoint);
end = System.currentTimeMillis();
ByteArrayOutputStream os = new ByteArrayOutputStream();
resp.writeTo(os);
response = os.toString();
if (!resp.getSOAPBody().hasFault()) {
response = "SucCess:" + response;
}else{
response = "FaiLure:" + response;
}
}else{
response = "FaiLure:" + response;
}
}catch(SOAPException se){
_logger.log(Level.ERROR," Service Provisioning Call Failed");
_logger.log(Level.ERROR,"The call duration before SOAPException =" +(end-start)+" ms.");
se.printStackTrace();
throw se;
}
soapConnection.close();
return response;
}
private SOAPMessage getSoapRequest(String xml) throws SOAPException,Exception{
MessageFactory mf = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
/* Create a SOAP message object. */
SOAPMessage soapMessage = mf.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
soapEnvelope.getHeader().detachNode();
soapEnvelope.addNamespaceDeclaration("soap","http://yyyy");
SOAPHeader header = soapEnvelope.addHeader();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
InputStream stream = new ByteArrayInputStream(xml.getBytes());
Document doc = builderFactory.newDocumentBuilder().parse(stream);
_logger.log(Level.DEBUG, "Adding SOAP Request Body");
soapBody.addDocument(doc);
soapMessage.saveChanges();
return soapMessage;
}
}
sample request
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soap="http://bridgewatersystems.com/xpc/tsc/entity/soap">
<env:Header/>
<env:Body>
<TempTierChangeRequest xmlns="http://bridgewatersystems.com/xpc/tsc/entity/soap" credentials="root" principal="root">
<temp-tier-change xmlns="">
<service-components>
<service-component name="DSL_Tier_2"/>
</service-components>
<duration-sec>300</duration-sec>
<description>1024 SC</description>
<activation-date>2017-02-09T10:29:16</activation-date>
<subscriber-id>26752018010#wholesale1.com</subscriber-id>
<partition-key>26752018010</partition-key>
<ttc-id>3706043</ttc-id>
<validity-period>
<duration>30</duration>
<expires-with-billing-reset>1</expires-with-billing-reset>
</validity-period>
</temp-tier-change>
</TempTierChangeRequest>
</env:Body>
</env:Envelope>
It is not possible to set the value of System variable javax.xml.soap.MessageFactory for two different purposes. The default value is set for SOAP 1.1
Remove the system property javax.xml.soap.MessageFactory and depending on the type of client you are building use
Building the soap message with MessageFactory.newInstance()
If you want SOAP1.1, use the default constructor
MessageFactory factory = MessageFactory.newInstance();
If you want SOAP1.2, use
MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
See Java Tutorial.
JAX-WS clients configured with annotations #BindingType
#BindingType is used when the JAX-WS client is configured using annotations, for example if client is generated from WSDL. The annotation is added to Port to set the binding to SoapBinding.SOAP11HTTP_BINDING or SoapBinding.SOAP12HTTP_BINDING.
#WebService(targetNamespace = "https://myservice.services.com", name = "myserviceProxyProt")
#BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface MyServiceProxyPort {

Java Created Soap Client is not getting response but same is working from SOAPUI

I am creating a simple soap client payload in java but server replied that "Server didn't recognize the value of http header". I copied the created soap payload and pasted in SOAP-UI and performed the request, the payload works perfectly.
I also double checked soap header information. Everything is correct. But still I am not getting response from my java client.
Can anyone provide me any idea on this?
public class SoapClientClass {
public static void main(String[] args) throws UnsupportedOperationException, SOAPException, IOException, TransformerException {
// TODO Auto-generated method stub
//Getting an instance of Soap Connection factory
SOAPConnectionFactory myFct = SOAPConnectionFactory.newInstance();
//Getting a Soap Connection from the soap connection factory object
SOAPConnection myCon = myFct.createConnection();
//Getting a message factory object to create a message
MessageFactory myMsgFct = MessageFactory.newInstance();
//Using the message factory to create a message
SOAPMessage message = myMsgFct.createMessage();
//Adding message to the body
SOAPPart mySPART = message.getSOAPPart();
SOAPEnvelope myEnvp = mySPART.getEnvelope();
myEnvp.addNamespaceDeclaration("web","http://www.webservicex.net/");
//SOAPHeader header = myEnvp.getHeader();
//javax.xml.soap.Name HeaderName = myEnvp.createName("GetGeoIP", "web","http://www.webservicex.net/");
//SOAPHeaderElement hltp = header.addHeaderElement(HeaderName);
SOAPBody body = myEnvp.getBody();
javax.xml.soap.Name bodyName = myEnvp.createName("GetGeoIP", "web","http://www.webservicex.net/");
SOAPBodyElement gltp = body.addBodyElement(bodyName);
javax.xml.soap.Name myContent = myEnvp.createName("IPAddress","web", "http://www.webservicex.net/");
SOAPElement mySymbol = gltp.addChildElement(myContent);
mySymbol.addTextNode("192.128.62.43");
message.saveChanges();
message.writeTo(System.out);
URLEndpoint endPt = new URLEndpoint("http://www.webservicex.net//geoipservice.asmx");
SOAPMessage reply = myCon.call(message, endPt);
//reply.writeTo(System.out);
System.out.println("\n");
TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();
Source sc = reply.getSOAPPart().getContent();
StreamResult result = new StreamResult(System.out);
tf.transform(sc, result);
System.out.println("test");
//conn.close();
SOAPBody body1 = reply.getSOAPBody();
if ( body1.hasFault() ) {
SOAPFault newFault = body1.getFault();
QName code = newFault.getFaultCodeAsQName();
String string = newFault.getFaultString();
String actor = newFault.getFaultActor();
System.out.println(string);
}
myCon.close();
//System.out.println(reply);
}
This is very old request but still answering if some one might run into similar issue. As per the error it is expecting HTTP header SOAPAction. Above code required two lines of HTTP header setting code.
SOAPEnvelope myEnvp = mySPART.getEnvelope();
MimeHeaders mheader=message.getMimeHeaders();
mheader.setHeader("SOAPAction", "http://www.webservicex.net/GetGeoIP");
myEnvp.addNamespaceDeclaration("web","http://www.webservicex.net/");

How to add xmlbean document element to soap header spring-ws

I am trying to hit a webservice using spring-ws, but the webservice producer requires a custom element in the soap header. I am very new to webservices, and am having trouble trying to inject the values into the soap header. I am using XMLBeans to transform from xsd to java and also to do the marshaling and unmarshaling. I have constructed the xmlbean document and set all values for the custom header element, I just need to get the document or maybe even just the element attached to that document to be injected into the soap header. Listed below is the wsdl (just header) in soapui (what I used to learn and do initial testing)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0" xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Rate/v1.1" xmlns:v12="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
<soapenv:Header>
<v1:UPSSecurity>
<v1:UsernameToken>
<v1:Username>name</v1:Username>
<v1:Password>password</v1:Password>
</v1:UsernameToken>
<v1:ServiceAccessToken>
<v1:AccessLicenseNumber>accesskey</v1:AccessLicenseNumber>
</v1:ServiceAccessToken>
</v1:UPSSecurity>
</soapenv:Header>
I found a solution that works, and isn't much code. I had to ditch using xmlbeans, and just create the elements, but at least the functionality is there and the webservice calls works.
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException
{
try
{
SOAPMessage soapMessage = ((SaajSoapMessage)message).getSaajMessage();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPHeaderElement soapHeaderElement = header.addHeaderElement(new QName("http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0", "UPSSecurity", "v1"));
SOAPEnvelope envelope = soapMessage.getSOAPPart().getEnvelope();
envelope.addNamespaceDeclaration("v1", "http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0");
SOAPElement usernameToken = soapHeaderElement.addChildElement("UsernameToken", "v1");
SOAPElement username = usernameToken.addChildElement("Username", "v1");
SOAPElement password = usernameToken.addChildElement("Password", "v1");
SOAPElement serviceAccessToken = soapHeaderElement.addChildElement("ServiceAccessToken", "v1");
SOAPElement accessLicenseNumber = serviceAccessToken.addChildElement("AccessLicenseNumber", "v1");
username.setTextContent("username");
password.setTextContent("password");
accessLicenseNumber.setTextContent("key");
}
catch (SOAPException e)
{
e.printStackTrace();
}
}
You can marshal to a SoapHeader's Result, like so:
SoapMessage msg = ...
SoapHeader header = msg.getSoapHeader();
XmlBeansMarshaller marshaller = ...
MyXmlBeansDocument doc = ...
marshaller.marshal(doc, header.getResult());
You can convert an XmlObject (XmlBeans model) to a SOAPElement using the following factory method:
YourModel xmlObject = YourModelDocument.Factory.newInstance().addNewYourModel();
SOAPElement soapElement = SOAPFactory.newInstance()
.createElement((Element) xmlObject.getDomNode());
The XmlObject must be part of a document otherwise getDomNode() will return an XmlFragment rather than an Element.
Once converted to a SOAP element, the XML can be added to most parts of a SOAPMessage using addChildElement(). For example:
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addChildElement(soapElement);

Soap Web Service client from java class using saaj

I am working in application in wish i need to invoke soap web services. To do so i am using SAAJ. For testing I made the method below to call a service. This service return a String that receives as input.my problem is that the service is called but it doesn't receive the input parameters. Can anyone give me an idea about how to resolve this please?
2. I have also another question, how can i do to invoke a service who has objects as input?
3. is SAAJ the best solution to create distant client to invoque soap services?
Thank you
public void invokeExtractMetadata(Service service,String path) throws Exception {
System.out.println("invoke");
QName serviceName = new QName(service.namespace, service.serviceName);
QName portName = new QName(service.namespace, service.portType);
String endpointAddress =service.endPointAddress;
javax.xml.ws.Service myService = javax.xml.ws.Service.create(serviceName);
myService.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
Dispatch<SOAPMessage> dispatch = myService.createDispatch(portName, SOAPMessage.class, javax.xml.ws.Service.Mode.MESSAGE);
BindingProvider bp = (BindingProvider) dispatch; //Use Dispatch as BindingProvider
MessageFactory factory = ((SOAPBinding) bp.getBinding()).getMessageFactory();
SOAPMessage request = factory.createMessage();
// Request Header
SOAPHeader header = request.getSOAPHeader();
// Request Body
SOAPBody body = request.getSOAPBody();
// Compose the soap:Body payload
QName payloadName = new QName(service.namespace,service.inMsgTag );
SOAPBodyElement payload = body.addBodyElement(payloadName);
QName name = new QName("pathT");
SOAPElement message = payload.addChildElement(name);
message.addTextNode(path);
SOAPMessage reply = null;
//Invoke Endpoint Operation and read response
reply = dispatch.invoke(request);
//process the reply
body = reply.getSOAPBody();
QName responseName = new QName(service.namespace, service.outMsgTag);
SOAPBodyElement bodyElement = (SOAPBodyElement)body.getChildElements(responseName).next();
QName elementName = new QName("", "return");
Iterator t =bodyElement.getChildElements(elementName);
System.out.println("tt");
while(t.hasNext()){
SOAPBodyElement bodyElementTest = (SOAPBodyElement)t.next();
String valeur = bodyElementTest.getValue();
System.out.println("valeur"+valeur);
}
}

Java version of SoapClient

I have a working soaprequest in PhP and i'm trying to create a java program that requires the same call, However i am really struggeling to find the way to create the below php code in java, i have found numerus websites explaining soap requests in java but i cant seem to work how how to send the $param_auth array.
Any help would be most appreciated as i've been stuck on this for a while.
Thanks in advance.
$param_auth=array(
'user'=>$username,
'id'=>$userID,
'message'=>$userMessage
);
$soapclient = new soapclient(WebsiteAddress);
$data->_db = $soapclient->call('uploadMessage',$param_auth);
Finally solved my issue (Ive changed Element names etc.), using eclipse shows you the Soap envelope and XML response which i found useful for debugging the envelope).
Hope this helps anyone trying to do similar.
The "UploadMessage" is the "Login" string and the
$param_auth=array(
'user'=>$username,
'id'=>$userID,
'message'=>$userMessage
);
is the Username and Password, (Left out the Message part).
This code sends an Envelope like this the server:-
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:Login="Your URL"><SOAP-ENV:Header/><SOAP-ENV:Body><Login><UserName>YourUserName</UserName><Password>YourPassword</Password></Login></SOAP-ENV:Body></SOAP-ENV:Envelope>
Code To create the above Envelope is below:-
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
public class SoapCall {
public static void main(String args[]) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server.
String url = "Your URL";
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// Process the SOAP Response
printSOAPResponse(soapResponse);
soapConnection.close();
} catch (Exception e) {
System.err.println("Error occurred while sending SOAP Request to Server");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest() throws Exception {
String YourUsername = "UserName";
String YourPassword = "Password";
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "Your URL";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("Login", serverURI);
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("Login");
SOAPElement soapBodyElem2 = soapBodyElem.addChildElement("UserName");
soapBodyElem2.addTextNode(YourUserName);
SOAPElement soapBodyElem3 = soapBodyElem.addChildElement("Password");
soapBodyElem3.addTextNode(YourPassword);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "Login");
soapMessage.saveChanges();
/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}
/**
* Method used to print the SOAP Response
*/
private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}
}

Categories