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
Related
please, this is y concern: I'll like to know how to query a web service defined as in the below code using postman for test purposes.
PS: I can't change the method signature
I have a web service like this :
#POST
#Path("/uploadOpenAccountRequestFiles/{requestId}")
#Consumes({MediaType.APPLICATION_JSON,MediaType.MULTIPART_FORM_DATA})
public Response uploadOpenAccountRequestFiles(#PathParam("requestId") String requestId,
MultipartFormDataInput multipartFormDataInput)
throws JsonGenerationException, JsonMappingException, IOException {
initContext();
logger.info("DIGIBANK : uploadOpenAccountRequestFiles END: ");
String msge = "";
try {
digiBean.saveToserver(requestId, multipartFormDataInput);
} catch (Exception e) {
msge = e.getMessage();
e.printStackTrace();
}
org.af.webservice.Response resp = new org.af.webservice.Response(
request.getSession().getId(), "uploadOpenAccountRequestFiles", "",
msge.equalsIgnoreCase("OK") ? true : false, msge.equalsIgnoreCase("OK") ? false : true, "",
msge.equalsIgnoreCase("OK") ? true : false, "Boolean", msge);
logger.info("DIGIBANK : uploadOpenAccountRequestFiles END: ");
return Response.ok().entity(mapper.writeValueAsString(resp)).build();
}
this is are images of my configurations:
enter image description here
enter image description here
For calling that service, you need to pass requestId like below:
http://localhost:8080/uploadOpenAccountRequestFiles/requestId-value-here
For sending MultiPart data such as a file, you need to select form-data option in the body section in Postman and select the file by selecting the File dropdown. Also, make sure to set the appropriate headers for the request.
Check the below stackoverflow answer for more details:
Tool for sending multipart/form-data request
The steps of uploading a file through postman along with passing some input data along with the multipart request is very well discussed in below blog along with the screenshot. In this blog, the api code is written in node js. You can go through it once. It may give some information.
https://jksnu.blogspot.com/2021/09/how-to-create-post-request-with.html
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
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.
I am using xmlstreamreader in java to read attribute values and other data. This is the xml String:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><samlp:AuthnReques
t xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL
="http://localhost:8080/consumer.jsp" **ID="abc"** **IssueInstant="2012-04-14T11:44:49
:796"** ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="
2.0">**<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://loca
lhost:8080/saml/SProvider.jsp</saml:Issuer>**<Signature xmlns="http://www.w3.org/2
000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.or
g/2001/10/xml-exc-c14n#WithComments"/><SignatureMethod Algorithm="http://www.w3.
org/2000/09/xmldsig#rsa-sha1"/><Reference URI=""><Transforms><Transform Algorith
m="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms><DigestM
ethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><DigestValue>VzKYOu1g
ert3DDrNUSO1/Au3PGeD1PEyPuJeI2GO6ec=</DigestValue></Reference></SignedInfo><Sign
atureValue>k7hVlbsEhGW5ryelSbrwWWyJq3cdyDuVeQCOqRilbky8hEk/1sHI9DNOvOlPZ7OC9bI4d
EHm46R1
CDXoXkyOoXdq+3M/HbUakHM7eNvF5+j+NUXUX9dijb/rDzq05VNHcSIDXRpvMc1IRBremi0voVqX
ZuHRn+IBeD8hSK1LXsE=</SignatureValue></Signature></samlp:AuthnRequest>
Then I tried to read the attribute ID, IssueInstant and the element Issuer. all the 3 are highlighted(actually between **) in the above string. I have used the following code:
while(reader.hasNext()){
reader.next();
if(reader.getEventType() == XMLStreamReader.START_ELEMENT){
if(reader.getLocalName().equals("AuthnRequest"))
{
String ns=reader.getNamespaceURI();
System.out.println(ns);
id=reader.getAttributeValue(ns,"ID");
rec_instant=reader.getAttributeValue(ns,"IssueInstant");
System.out.println("1"+id);
System.out.println("2"+rec_instant);
}
else if(reader.getLocalName().equals("Issuer"))
{
rec_issuer=reader.getElementText();
System.out.println("4"+reader.getElementText());
}
}
}
But I am getting the folowing output:
1null
2null
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,436]
Message: parser must be on START_ELEMENT to read next text
What is the issue?
You are using ns for the attributes, but the attributes are in fact in the null ns (they have no namespace). As for the exception, you are calling getElementText twice. This method is not a pure getter, it also advances the reader to the end element (as per its Javadoc).
As Marko suggests, the exception is due to calling getElementText() twice in a row.
If I change this:
String rec_issuer=reader.getElementText();
System.out.println("4"+reader.getElementText());
to this:
String rec_issuer = reader.getElementText();
System.out.println("4" + rec_issuer);
then I get the following output:
urn:oasis:names:tc:SAML:2.0:protocol
1null
2null
4http://localhost:8080/saml/SProvider.jsp
If I also change the getAttributeValue calls to use null instead of ns, like this:
String id = reader.getAttributeValue(null,"ID");
String rec_instant = reader.getAttributeValue(null,"IssueInstant");
I get:
urn:oasis:names:tc:SAML:2.0:protocol
1abc
22012-04-14T11:44:49:796
4http://localhost:8080/saml/SProvider.jsp
That's using your original XML.