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);
}
}
Related
I need to consume a SOAP API which requests all the messages to be signed policy "SigOnly".
I've generated the client code from the WSDL using wsimport and I was expecting it to generate the code for signing as well but it's not.
MyWebservice service = new MyWebservice();
MyWebservicePortType port = service.getMyWebserviceSOAPportHttp();
// Build request
ObjectFactory objectFactory = new ObjectFactory();
MyRequest request = objectFactory.createMyRequest();
// Call endpoint
port.myRemoteMethod(request);
Is there an extra switch for the wsimport tool to generate code for signing or am I missing some steps in the client's code?
WS-Security is an extension to soap, so I don't think wsimport could handle it in code generation.
Anyway you can write your handler to add ws-security headers in your soap requests.
You can add a handler to your port in this way :
BindingProvider bp = (BindingProvider) port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add( new MyHandler() );
Binding binding = bp.getBinding();
binding.setHandlerChain(handlerChain);
MyHandler class must implement SOAPHandler.
This is an example of an implementation of handleMessage method of MyHandler, adding a header
#Override
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPElement security = header.addChildElement("Security", "wsse",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("MyUser");
}
}
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 {
I am trying to consume an authenticated webservice using SAAJ. This is the code I have so far:
import java.io.ByteArrayOutputStream;
import javax.xml.soap.*;
import biz.source_code.base64Coder.*;
public class Client {
private static String endpoint = "https://example.com/xxx.php",
username = "xxx", password = "xxx";
private static SOAPMessage getRequest() throws Exception{
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
//set authorization as a HTTP header
String authorization = Base64Coder.encodeString(username + ":" + password);
MimeHeaders hd = message.getMimeHeaders();
hd.addHeader("Authorization", "Basic " + authorization);
//Call getReportList operation
return message;
}
public static void main(String[] args) throws Exception {
SOAPConnectionFactory connFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = connFactory.createConnection();
// create request message and give it content
SOAPMessage request = Client.getRequest();
// call the API endpoint with the request
SOAPMessage response = connection.call(request, endpoint);
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.writeTo(out);
String strMsg = new String(out.toByteArray());
System.out.println(strMsg);
}
}
When I run this, it prints strMsg (response from the web service) as follows:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>WSDL</faultcode><faultstring>SOAP-ERROR: Parsing WSDL: Couldn't load from '/www/example.wsdl' : failed to load external entity "/www/example.wsdl"
</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
I am guessing I have authenticated myself but there was a problem with the web service not mine. But, I am not entirely sure. This error message doesn't seem that common.
Does this mean the authentication I provided was incorrect or insufficient? Or do I have to provide the SSL certificate because the web service uses SSL? If yes, Is there a tutorial on how to use SSL certificates with SAAJ?
The problem was that I was using "https://example.com/xxx.php" as the endpoint not "https://example.com/xxx.php?wsdl". That's why it couldn't load any wsdl file.
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/");
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.