Why can I set a faulString, but can't I set a custom fault code in a SOAPFault? When I throw the exception, the text "Code X" does not appear in the SoapFaultException. Someone could tell me why? Thanks.
SOAPFault soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault();
soapFault.setFaultString("String Y")
soapFault.setFaultCode("Code X");
throw new SOAPFaultException(soapFault);
It is possible to get the fault code in the soap response with the following example:
String faultString = "String Y";
String faultCodeValue = "Code X";
QName faultCode = new QName("nameSpaceURI", faultCodeValue);
SOAPFault soapFault = null;
try {
soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault(faultString, faultCode);
throw new javax.xml.ws.soap.SOAPFaultException(soapFault);
} catch (SOAPException e1) {
//
}
I get the following soap fault back:
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope" xmlns="">
<faultcode xmlns:ns0="nameSpaceURI">ns0:Code X</faultcode>
<faultstring>String Y</faultstring>
</S:Fault>
</S:Body>
</S:Envelope>
From documentation:
Fault codes, which given information about the fault, are defined in
the SOAP 1.1 specification. This element is mandatory in SOAP 1.1.
Because the fault code is required to be a QName it is preferable to
use the setFaultCode(Name) form of this method.
faultCode - a String giving the fault code to be set. It must be of
the form "prefix:localName" where the prefix has been defined in a
namespace declaration.
Notice that the fault code your're setting has to be this format: prefix:localName. You're setting: Code X, that is why you do not see it. Use this method and all should be OK.
Related
I'm trying to construct a simple header element (i.e. contextID) with org.apache.cxf.headers.Header
The XML representation should be like:
<soapenv:Header>
<contextID>someString</contextID>
</soapenv:Header>
I was trying like this in an interceptor:
String contextID = "someString";
List<Header> headers = message.getHeaders();
//this could be possibly wrong
Header contextIdHeader = new Header(new QName(CORE_NAMESPACE, "contextID"), contextID);
headers.add(contextIdHeader);
message.put(Header.HEADER_LIST, headers);
But I'm getting an exception:
java.lang.ClassCastException: java.lang.String cannot be cast to org.w3c.dom.Element
I suppose, the construction of the Header element is wrong.
What would be the correct way to do it?
Thank you!
Found the solution:
the Header element has to be created like this
Header contextIdHeader = new Header(new QName(CORE_NAMESPACE, "contextID"), contextID, new JAXBDataBinding(String.class));
I am pretty new in the WebServices interrogation using Java and I have the following problem.
I have a web service that provide to me a getConfigSettings() method that, by its response, say to me some informations including whether a user is enabled or not on a certain service (it say if the couple username and password is correct and if the user can log into the system).
In particular I have the following REQUEST of the getConfigSettings() method:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:getConfigSettings>
<!--Optional:-->
<tem:login>name.surname</tem:login>
<!--Optional:-->
<tem:password>rightPawssword</tem:password>
<!--Optional:-->
<tem:ipAddress>144.44.55.4</tem:ipAddress>
<!--Optional:-->
<tem:clientVersion>1</tem:clientVersion>
<!--Optional:-->
<tem:lastUpdateTime>2</tem:lastUpdateTime>
</tem:getConfigSettings>
</soapenv:Body>
</soapenv:Envelope>
And this is the webservice RESPONSE in case the couple username and password is correct and the user can log into the system:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<getConfigSettingsResponse xmlns="http://tempuri.org/">
<getConfigSettingsResult>
<![CDATA[
<root>
<status>
<id>0</id>
<message></message>
</status>
<drivers>
<drive id="tokenId 11">
<shared-secret>Shared 11</shared-secret>
<encoding>false</encoding>
<compression />
</drive>
<drive id="tokenId 2 ">
<shared-secret>Shared 2 </shared-secret>
<encoding>false</encoding>
<compression>false</compression>
</drive>
</drivers>
</root>
]]>
</getConfigSettingsResult>
</getConfigSettingsResponse>
</s:Body>
</s:Envelope>
In this response the important section is:
<status>
<id>0</id>
<message></message>
</status>
because <id>0</id> means that the user can log into the system
On the contrary if the couple username and password is incorrect I will obtain the following RESPONSE:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<getConfigSettingsResponse xmlns="http://tempuri.org/">
<getConfigSettingsResult><![CDATA[<root>
<status>
<id>-1</id>
<message>Login or password incorrect</message>
</status>
</root>]]></getConfigSettingsResult>
</getConfigSettingsResponse>
</s:Body>
</s:Envelope>
As you can see in this case I have that <id>-1</id> (that represent a situation of error) and in the message tag it specify the type of error occurred.
Ok, now I have to create a Java method that call this getConfigSettings() method passing to it the requested 5 parameters: login, password, ipAddress, clientVersion and lastUpdateTime (also if at this stage the only important parameters are login and password, the others can be whatever...)
And now I have no idea about how do it.
In my project there is another method that call another request report of the same web services that is:
public String getVersion() {
java.net.URL url = null;
java.net.URLConnection conn = null;
java.io.BufferedReader rd = null;
String soapResponse = "";
String risultato = "";
// SOAP ENVELOP for the request:
String soapRequest;
soapRequest = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tem=\"http://tempuri.org/\">" + "<soapenv:Header/>" + "<soapenv:Body> " + "<tem:getVersion/>" + "</soapenv:Body>" + "</soapenv:Envelope>";
try {
// Try to open a connection
url = new java.net.URL(_webServiceUrl);
conn = url.openConnection();
// Set the necessary header fields
conn.setRequestProperty("SOAPAction", "http://tempuri.org/IMyService/getVersion");
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setDoOutput(true);
// Send the request:
java.io.OutputStreamWriter wr = new java.io.OutputStreamWriter(conn.getOutputStream());
wr.write(soapRequest);
wr.flush();
// Read the response
rd = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));
// Put the entire response into the soapResponse variable:
String line;
while ((line = rd.readLine()) != null) {
//System.out.println(line);
soapResponse = soapResponse + line + System.getProperty("line.separator");
}
rd.close();
// PERFORM SOME ELABORATION ON THE RESPONSE
..........................................
..........................................
..........................................
..........................................
return risultato;
}
Looking at this working method it seems to me that do something like that:
It create a String object that contain the SOAP Envelop for my request.
Try to connect to my WebService.
Then Set the necessary header fields (and this is not clear for me, what exactly mean? and what is tempuri?), what exactly do the following lines:
conn.setRequestProperty("SOAPAction", "http://tempuri.org/IMyService/getVersion");
conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
conn.setDoOutput(true);
Send my prepared request to the WebService
Obtain the response and put it into my String soapResponse variable
This is what I want to obtain creating the other authentication() method, I have to create the SOAP Envelop using the previous parameters, send it to the webservice and obtain the SOAP response.
I think that my main problem is how to create the right String soapRequest object that use the parameter to do that.
I'm using jpachube and am running into problems with .POST on creatDatastream. I am getting POST error 400, and the following details from COSM's debug tool:
{"title":"JSON Parser Error","errors":"lexical error: invalid char in json text. <? xmlversion=\"1.0\"encoding=\"U"}
My XML request body from the COSM debug tool is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<eeml xmlns="http://www.eeml.org/xsd/005"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd"><environment><data id="0">
<tag>CPU</tag>
<current_value>0.0</current_value>
</data>
</environment>
</eeml>
COSM's API documentation for what the xml request body should look like is as follows:
<eeml xmlns="http://www.eeml.org/xsd/0.5.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" version="0.5.1" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd">
<environment>
<data id="23">
<tag>apple</tag>
<tag>jag</tag>
<tag>tag</tag>
<tag>lag</tag>
<current_value>11</current_value>
<max_value>211.0</max_value>
<min_value>7.0</min_value>
<unit type="conversionBasedUnits" symbol="symbol">label</unit>
</data>
</environment>
The only difference I found was the version #, but I made that switch in the code already and got the same error.
I thought for the v2 of the COSM API was set up so xml and JSON are interchangeable but it converts everything to JSON.
The error is coming from this method call in Pachube.java
public boolean createDatastream(int feed, String s) throws PachubeException {
HttpRequest hr = new HttpRequest("http://api.cosm.com/v2/feeds/"
+ feed + "/datastreams/");
hr.setMethod(HttpMethod.POST);
hr.addHeaderItem("X-PachubeApiKey", this.API_KEY);
hr.setBody(s);
HttpResponse g = this.client.send(hr);
if (g.getHeaderItem("Status").equals("HTTP/1.1 201 Created")) {
return true;
} else {
throw new PachubeException(g.getHeaderItem("Status"));
}
}
Any input appreciated.
Day two...
Modified the createDatastream method using input from bjpirt (much thanks). Method looks like this
public boolean createDatastream(int feed, String s) throws PachubeException {
HttpRequest hr = new HttpRequest("http://api.cosm.com/v2/feeds/"
+ feed + "/datastreams.xml");
hr.setMethod(HttpMethod.POST);
hr.addHeaderItem("X-PachubeApiKey", this.API_KEY);
hr.addHeaderItem("Content-Type:", "application/xml");
hr.setBody(s);
HttpResponse g = this.client.send(hr);
if (g.getHeaderItem("Status").equals("HTTP/1.1 201 Created")) {
return true;
} else {
Log.d("create data stream", "prob");
throw new PachubeException(g.getHeaderItem("Status"));
}
}
This throws the following error for .POST on the COSM debug tool (error code 422):
<?xml version="1.0" encoding="UTF-8"?><errors><title>Unprocessable Entity</title> <error>Stream ID has already been taken</error></errors>
So, naturally, I need to get a title on this request. That is done through the toXMLWithWrapper in Data.java
public String toXMLWithWrapper() {
String ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<eeml xmlns=\"http://www.eeml.org/xsd/005\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"5\" xsi:schemaLocation=\"http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd\"><environment>";
ret = ret + ">\n\t<title>" + "cosm app" + "</title>\n\t";//inserted this line to add title
ret = ret + this.toXML() + "</environment></eeml>";
return ret;
}
And the request body looks like (from COSM debug tool):
<?xml version="1.0" encoding="UTF-8"?>
<eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd"><environment>
<title>cosm app</title>
<data id="0">
<tag>CPU</tag>
<current_value >0.0</current_value>
</data></environment></eeml>
This comes back as error code 500 (ouch!)
Response body is
<?xml version="1.0" encoding="UTF-8"?><errors><title>Oops, something's broken</title> <error>We've been unable to complete your request due to a problem with our server</error></errors>
day three
it was pointed out that there was a problem with the xml (see below). I fixed the typo and I'm back to a 422 error. So, looking more closely at the response body I thought maybe that there was something wrong with the data stream. I delete all of the datastreams in the feed, create a new feed, and I get exactly ONE AWESOME HTTP:/1.1 201 - happy, right? Wrong, after the first .POST I get nothing. When I turn the app off and then back on, I'm back to 422 error and the same response body "Stream ID has already been taken". Yikes!
It seems like the xml may be invalid.
The opening <environment> node seems to be closed twice <environment>>
The 422 is probably because you are trying to POST to an existing feed.
To update a feed you need to send a PUT request.
See the Updating a feed docs
The clue is that the system looks like it's expecting json but you're feeding it XML. The default for the v2 api is json, so you'll need to make sure that you're including XML in the URL, e.g:
https://api.cosm.com/v2/feeds/113/datastreams.json
Alternatively, you can set a content type header on the request to indicate this:
Content-Type: application/xml
I am using java soap request and response in my code. I am getting the request and response properly.
But I am not able to iterate the response
Please see my response and code used to iterate below. Please help me to resolve this issue.
Response
<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUserResponse xmlns="http://XXXX.com/XXXXXXXX.XXXXXXX.WS">
<GetUserResult>
user
<PersonID>111113</PersonID>
<Username>0987654321</Username>
<Password />
<FwyMember>Y</FwyMember>
<WebMember>Y</WebMember>
<FirstName>Mohamed</FirstName>
<Tier>firstclass</Tier>
<CountryOfResidence>IN</CountryOfResidence>
<PreferencesChanged>false</PreferencesChanged>
<FamilyRelationship />
<Title>Mr</Title>
<MiddleName />
........ continue like this
Java code
SOAPBody responseBody = response.getSOAPBody();
QName bodyName1 = new QName("http://XXXX.com/XXXXXXXX.XXXXXXX.WS","GetUserResponse");
java.util.Iterator iterator = responseBody.getChildElements(bodyName1);
while (iterator.hasNext()) {
SOAPBodyElement responseElement = (SOAPBodyElement)iterator.next();
String val = responseElement.getValue();
System.out.println("The values are "+val);
}
There is only one GetUserResponse element below Body. getChildElements only gets child elements, as opposed to descendant elements. You must first reach GetUserResponse and then iterate over its children.
I am at the end of my ropes so its time to ask the community for help, i've been pillaging the web for any resource I can find on this issue but none helps me.
I am currently trying to communicated with a Java Webservice server through PHP. I can pull down a WSDL and list its functions and types through __getFunctions(); and __getTypes();
I am creating the client in this format
new SoapClient("https://username:password#ip:port/path/to/wsdl?wsdl");
Now initially this poses no problems, but when I try to make a function call on this service I get 1 of 2 responses.
I know one of them is a timeout error, the second one I do not understand as of yet.
Error : SoapFault exception: [SOAP-ENV:Client] [MT-IP] SOAP message is not well formed in...
Here is the code:
// All of this works
$options["login"] = "login";
$options["password"] = "password";
$wsdl = "https://" . $options["login"] . ":" . $options["password"] . "#ip:port/path/to/wsdl?wsdl";
$client = new SoapClient($wsdl, $options);
try {
$functions = $client->__getFunctions();
$types = $client->__getTypes();
$params = new stdClass();
$params->pong = (string)"Hello World!";
// This fails
$result = $client->ping($params);
var_dump($result);
} catch (SoapFault $exception) {
echo $exception;
}
To add I have also attempted to call methods in all the ways available such as
$client->__soapCall("ping", array($params));
$client->__soapCall("ping", array(array("pong" => "Hello World!)));
$client->__soapCall("ping", array("pong" => "Hello World"));
$client->__soapCall("ping", array("parameters" => array("pong" => "Hello World"));
// and some more..
You can also see the WSDL I am testing against
WSDL
You can also view the page where I try to call webservice
SOAP TEST
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="com.computas.mt.extern.Ping">
<SOAP-ENV:Body>
<ns1:ping>
<pong>Hello World!</pong>
</ns1:ping>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In my case the schematics the server wanted was different than that of the request PHP was sending out. The solution was to physically change the request XML before it was sent out by extending the SoapClient. We found the changes to the issue once we had the XML layout that the server usually gets provided with.
class MySoapClient extends SoapClient {
function __doRequest( $request, $location, $action, $version, $one_way = NULL ) {
$request = str_replace("SOAP-ENV", "soapenv", $request);
$request = str_replace("xsi", "com", $request);
$request = str_replace("ns1", "com", $request);
var_dump($request);
return parent::__doRequest( $request, $location, $action, $version, $one_way );
}
}
Do not put username and password into the url. SoapClient accepts an option array that offers parameters for this purpose. http://de2.php.net/manual/en/soapclient.soapclient.php