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.
Related
I'm trying to consume an external api exposed a payment provider.
I user Jersey and javax.ws.rs for request, because I can easily send authent with Digest.
But when it comes to make the request, a GET with payload, Jersey returns
> IllegalStateException. Entity must be null for http method GET
CashTransactionResponse responseData = null;
//We connect to intouch server
String requestUrl = rootUrlTouchPay + agency.getAgencyCode() + "/" + IntouchMethodApis.TRANSACTION + "?loginAgent=" + agency.getLogin() + "&passwordAgent=" + agency.getPassword();
ClientConfig clientConfig = new ClientConfig();
//Open Digest authentication
HttpAuthenticationFeature feature = HttpAuthenticationFeature.digest(BASIC_LOGIN, BASIC_PWD);
clientConfig.register(feature);
clientConfig.register(JacksonFeature.class);
//Create new rest client
Client client = ClientBuilder.newClient(clientConfig);
clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
//Set the url
WebTarget webTarget = client.target(requestUrl);
Invocation.Builder invocationBuilder = webTarget.request(javax.ws.rs.core.MediaType.APPLICATION_JSON);
logger.info("Initialisation of cashout service successful for cash");
// create request
Gson gson = new Gson();
String transactionString = gson.toJson(cashRequest);
Response response = null;
// start the response
if (cashRequest.getServiceCode().contains(TelecomEnum.WAVE.name().toUpperCase())) {
response = invocationBuilder.method("GET", Entity.entity(transactionString, javax.ws.rs.core.MediaType.APPLICATION_JSON));
} else {
response = invocationBuilder.put(Entity.entity(transactionString, javax.ws.rs.core.MediaType.APPLICATION_JSON));
}
Please how could i do to send my GET request with body ?
Thanks
I believe the problem is in
Client client = ClientBuilder.newClient(clientConfig);
clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
The client copied the values from clientConfig and any further settings on clientConfig do not have any impact on the client.
Either switch the lines or set the ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION property on the client.
Instead of doing an invocationBuilder.method("GET", ...), use invocationBuilder.post(entity), as described here. This will allow you to POST your transaction String to the endpoint.
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 have written a Java client code using SAAJ for Primevera P6 webservices. I am getting the below authentication error. I am providing the http username + password to the code but it gives error: SEVERE: SAAJ0008: Bad Response; Unauthorized. Could some one please help me with this issue. I am stuck in this problem since a long time. The wsdl of the web service is: https://sunpower-p6.oracleindustry.com/p6ws-token/services/ProjectService?wsdl.
ERROR:
Request SOAP Message =
11106
Jul 18, 2016 1:03:19 PM com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection post
SEVERE: SAAJ0008: Bad Response; Unauthorized
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Bad response: (401Unauthorized
My code:
public class TestClient {
/*
Method used to create the SOAP Request
*/
private static SOAPMessage createSOAPRequest() throws Exception {
// Next, create the actual message
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String serverURI = "http://xmlns.oracle.com/Primavera/P6/WS/Project/V2";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("ProjectService", serverURI);
//start: setting HTTP headers - optional, comment out if not needed
String authorization = Base64Coder.encodeString("xyz:abc");
MimeHeaders hd = soapMessage.getMimeHeaders();
hd.addHeader("Authorization", "Basic " + authorization);
//end: setting HTTP headers
// Create and populate the body
SOAPBody soapBody = envelope.getBody();
// Create the main element and namespace
SOAPElement soapBodyElem = soapBody.addChildElement("ReadProjects", "ProjectService");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("Field", "ProjectService");
SOAPElement soapBodyElem2 = soapBodyElem1.addChildElement("Id", "ProjectService");
soapBodyElem2.addTextNode("11106");
hd.addHeader("SOAPAction", serverURI + "ReadProjects");
// Save the message
soapMessage.saveChanges();
// Check the input
System.out.println("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 {
// Create the transformer
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// Extract the content of the reply
Source sourceContent = soapResponse.getSOAPPart().getContent();
// Set the output for the transformation
System.out.println("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
System.out.println();
}
public static void main(String[] args) throws Exception {
try {
// First create the connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
//System.out.println(soapConnection);
//Send SOAP Message to SOAP Server
String url = "https://sunpower-p6.oracleindustry.com/p6ws-token/services/ProjectService?wsdl";
// Send the message and get the reply
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
// Process the SOAP Response
printSOAPResponse(soapResponse);
soapConnection.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
I realize this is an old question but would like to leave some assistance to anyone in the future who ends up here (like I did). There is a few likely situations that I have recently experienced regarding this.
Check that your details are correct, or that the connection is possible. Be 100% sure before moving on.
You will receive an unauthorized error if your database is not correctly configured for some setups (for instance, on JBoss). In my situation the data-source file was not being read properly when it attempted to connect causing the Unauthorized error on the client side.
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'm a bit confused about how to make a request to a webservice via java.
For now the only thing that I've understand is that webservices uses xml structured messages, but still I didn't quite understood how to structure my request.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getProductDetails xmlns="http://magazzino.example.com/ws">
<productId>827635</productId>
</getProductDetails>
</soap:Body>
</soap:Envelope>
Basically I've to send 2 parameters to the web service and in return I expect two other parameters.
I guess there are some jars that can do most of the job, but I didn't find any online.
Can someone please explain me the basis?
A SOAP request is an XML file consisting of the parameters you are sending to the server.
The SOAP response is equally an XML file, but now with everything the service wants to give you.
Basically the WSDL is a XML file that explains the structure of those two XML.
To implement simple SOAP clients in Java, you can use the SAAJ framework (it is shipped with JSE 1.6 and above):
SOAP with Attachments API for Java (SAAJ) is mainly used for dealing directly with SOAP Request/Response messages which happens behind the scenes in any Web Service API. It allows the developers to directly send and receive soap messages instead of using JAX-WS.
See below a working example (run it!) of a SOAP web service call using SAAJ. It calls this web service.
import javax.xml.soap.*;
public class SOAPClientSAAJ {
// SAAJ - SOAP Client Testing
public static void main(String args[]) {
/*
The example below requests from the Web Service at:
http://www.webservicex.net/uszip.asmx?op=GetInfoByCity
To call other WS, change the parameters below, which are:
- the SOAP Endpoint URL (that is, where the service is responding from)
- the SOAP Action
Also change the contents of the method createSoapEnvelope() in this class. It constructs
the inner part of the SOAP envelope that is actually sent.
*/
String soapEndpointUrl = "http://www.webservicex.net/uszip.asmx";
String soapAction = "http://www.webserviceX.NET/GetInfoByCity";
callSoapWebService(soapEndpointUrl, soapAction);
}
private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();
String myNamespace = "myNamespace";
String myNamespaceURI = "http://www.webserviceX.NET";
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI);
/*
Constructed SOAP Request Message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="http://www.webserviceX.NET">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<myNamespace:GetInfoByCity>
<myNamespace:USCity>New York</myNamespace:USCity>
</myNamespace:GetInfoByCity>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetInfoByCity", myNamespace);
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("USCity", myNamespace);
soapBodyElem1.addTextNode("New York");
}
private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl);
// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();
soapConnection.close();
} catch (Exception e) {
System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
createSoapEnvelope(soapMessage);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);
soapMessage.saveChanges();
/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");
return soapMessage;
}
}
When the WSDL is available, it is just two steps you need to follow to invoke that web service.
Step 1: Generate the client side source from a WSDL2Java tool
Step 2: Invoke the operation using:
YourService service = new YourServiceLocator();
Stub stub = service.getYourStub();
stub.operation();
If you look further, you will notice that the Stub class is used to invoke the service deployed at the remote location as a web service. When invoking that, your client actually generates the SOAP request and communicates. Similarly the web service sends the response as a SOAP. With the help of a tool like Wireshark, you can view the SOAP messages exchanged.
However since you have requested more explanation on the basics, I recommend you to refer here and write a web service with it's client to learn it further.
I have come across other similar question here. Both of above answers are perfect, but here trying to add additional information for someone looking for SOAP1.1, and not SOAP1.2.
Just change one line code provided by #acdcjunior, use SOAPMessageFactory1_1Impl implementation, it will change namespace to xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/", which is SOAP1.1 implementation.
Change callSoapWebService method first line to following.
SOAPMessage soapMessage = SOAPMessageFactory1_1Impl.newInstance().createMessage();
I hope it will be helpful to others.
if you have WSDL, You can create a new soap request in SoapUI with that WSDL file.
It would automatically generate the Structure/XML for input request.
Here is some simple version of Java code you can use to call Soap service if you have the input request xml from SoapUI:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SimpleSoapClient {
public static void main(String args[]) throws IOException {
String address="Hyderabad";
/* place your xml request from soap ui below with necessary changes in parameters*/
String xml="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://www.YourUrlAsPerWsdl.com/\">\r\n" +
" <soapenv:Header/>\r\n" +
" <soapenv:Body>\r\n" +
" <ws:callRest>\r\n" +
" <name>"+"Hello"+"</name>\r\n" +
" <address>"+address+"</address>\r\n" +
" </ws:callRest>\r\n" +
" </soapenv:Body>\r\n" +
"</soapenv:Envelope>";
String responseF=callSoapService(xml);
System.out.println(responseF);
}
}
static String callSoapService(String soapRequest) {
try {
String url = "https://gogle.com/service/hello"; // replace your URL here
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// change these values as per soapui request on top left of request, click on RAW, you will find all the headers
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type","text/xml; charset=utf-8");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(soapRequest);
wr.flush();
wr.close();
String responseStatus = con.getResponseMessage();
System.out.println(responseStatus);
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// You can play with response which is available as string now:
String finalvalue= response.toString();
// or you can parse/substring the required tag from response as below based your response code
finalvalue= finalvalue.substring(finalvalue.indexOf("<response>")+10,finalvalue.indexOf("</response>")); */
return finalvalue;
}
catch (Exception e) {
return e.getMessage();
}
}
}