cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Help us improve the PTC Community by taking this short Community Survey! X

Create a Thing that accepts XML

grahamall
1-Newbie

Create a Thing that accepts XML

To work with a third party system I'd like to implement a Thing that allow XML to be POSTed to a service that I define

For example id like the URL to be .../Thingworx/Things/workGateway/Services/workOrder

And to be able to call the service using  the content loader


var request = <request>

    <workorder>

      <WOEXTID>123</WOEXTID>

    </workorder>

</request>;

   

var params = {

    url: '.../Thingworx/Things/workGateway/Services/workOrder' /* STRING */,

  content: request /* XML */

};

var responce = Resources["ContentLoaderFunctions"].PostXML(params);

result = responce..*::status;

Now I could implement this as:


.../Thingworx/Things/workGateway/Services/workOrder?method=POST&value= <request><workorder><WOEXTID>123</WOEXTID></workorder></request>

And this superficially works for the trivial case above if I use the actual XML from the third party system then I get a 400 Bad Request error when creating a URL in chrome or the PostMan REST plugin for chrome.

XML Request2.PNG

If does work however if I use the Thingworks built in test function.  I have tried Linarizing the XML and appling HTML escaping the XML

XML Request.PNG

Does anyone have any suggestions on how the call the method using a non-trivial amount of XML (the actual XML is >6kloc) or how to accept a XML content.

Message was edited by: Graham Allan  Changed 400 Bad Gateway to 400 Bad Request - The correct message

17 REPLIES 17
paic
1-Newbie
(To:grahamall)

Set the Input parameter to String first and see what Thingworx thinks it is receiving.

grahamall
1-Newbie
(To:paic)

I'm still getting the same Bad Request (400) error for the non trivial case and the simple case still works provided I remove the internal processing from the method.

With the internal processing intact the code fails as I'm using XMLPath to process the data and I can find a function to parse/convert XML into a string

grahamall
1-Newbie
(To:paic)

Ive also tried the SaveXML method in a FileRepository thing and get the same problem, it works for the simple case but not the actual XML

grahamall
1-Newbie
(To:paic)

Looks like the problem is the namespace if I remove the xlms and remove the hj: prefix it works OK but this is not really useful as I can't ask the third part to remove their namespace.

Did you add all required namespace declaration in the xml that you construct in your javascript snippet? You may have to include it multiple times if you add snippets to your xml dynamically (e.g. using '+=' or append() ). Here is an example that worked for me:

var reqXML = <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">

<s:Body>

<GetFilteredGboList xmlns="www.mywhatever.com">

<businessObjectSchemaUri>urn:mywhatever:sib:schemas:gbo:enquiry:2:0</businessObjectSchemaUri>

<customFilter xmlns:a="http://schemas.datacontract.org/2004/07/mywhatever.SIB.GBO.QueryServiceEntities.ServiceEntities"

                            xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

<a:ComplexExpression>....</a:ComplexExpression>

</customFilter>

</GetFilteredGboList>

</s:Body>

</s:Envelope>


From your XML example below it seems to be included but I'd double-check.


Did you include 'SOAPAction' in the header fields? I had to learn this one the hard way...


For debugging you can use Fiddler: if you want to check the outgoing traffic from a ContentLoader service you can intercept it with Fiddler by switching the 'useProxy' param to 'true', setting 'proxyhost' to 'localhost' and 'proxyport' to '8888' (assuming Fiddler runs on localhost and uses his std port 8888).

Yes I did use the correct namespace.  I think th at the problem may have move to do with length as short examples with a name space work and a long example without one works its only when I combine the two I get an error

mhollenbach
5-Regular Member
(To:grahamall)

I am using the exact XML you have supplied within this post, sending it to a service in ThingWorx via Postman, and I can verify that it is working properly.

That's fantastic, the long XML (below) or the short one and which version of Thingworx?

Can you upload a copy of the thing you are using please.

mhollenbach
5-Regular Member
(To:grahamall)

I'm using 6.0.3 and the long version is what I have tested. Just put the below code inside of a custom service on your Thing with input parameter content of baseType XML.

var params = {

       url: "http://localhost/Thingworx/Things/TestingPostingXML/Services/TestingXml?postParameter=content" /* STRING */,

       content: content /* XML */,

       password: "admin" /* STRING */,

       username: "Administrator" /* STRING */

};

var result= Resources["ContentLoaderFunctions"].PostXML(params);

Thank you for all your help with this, either I'm doing something wrong or version 4 is working differentially


var content = me.IOW_WO_SampleSoapEnvelope();



var params = {


      url: "https://<server>/Thingworx/Things/IOWWorkOrderGateway/Services/workOrder?value=content"  /* STRING */,


      content: content /* XML */,


      password: "name" /* STRING */,


      username: "password" /* STRING */


};



result = Resources["ContentLoaderFunctions"].PostXML(params);




The XML parameter is called value although I've also tried postParameter and I always get the error:

Wrapped org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1092; The element type "HR" must be terminated by the matching end-tag "". Cause: The element type "HR" must be terminated by the matching end-tag "".


Regardless of the XML I use.


mhollenbach
5-Regular Member
(To:grahamall)

Hold on, what version of ThingWorx are you using? I'm using 6.0.3 presently.

Here is an anonymised example of the XML that I need to pass as a parameter (with SOAP envelope removed):


<hj:operations xmlns:hj="http://example.com/hjrkOrdersType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example.com/hjrkOrdersType EXM-XXX-IN-hj-Core_1.7.xsd ">


  <hj:request type="INSERT">


  <hj:hjrkorder>


  <hj:hjEXTID>123</hj:hjEXTID>


  <hj:MODEL_ID>XXX_WERF</hj:MODEL_ID>


  <hj:SUBJECT>Short description of the hjrk order</hj:SUBJECT>


  <hj:DESCRIPTION>Long description of the hjrk order</hj:DESCRIPTION>


  <hj:DOMAIN>PLANT</hj:DOMAIN>


  <hj:CATEGORY>Custom category</hj:CATEGORY>


  <hj:hjRKORDERTYPE>Custom type</hj:hjRKORDERTYPE>


  <hj:hjRKTYPE>Custom hjrk type</hj:hjRKTYPE>


  <hj:SUBTYPE>Custom hjrk subtype</hj:SUBTYPE>


  <hj:FAILURE>Custom failure code</hj:FAILURE>


  <hj:PRIORITY>Custom priority level</hj:PRIORITY>


  <hj:STATUS>APPR</hj:STATUS>


  <hj:JOBPLAN>Custom job plan code</hj:JOBPLAN>


  <hj:CREATIONDATE>2001-12-31T12:00:00</hj:CREATIONDATE>


  <hj:CREATIONTYPE>USER</hj:CREATIONTYPE>


  <hj:CREATEDBY>qsiraut</hj:CREATEDBY>


  <hj:TARGETSTARTDATE>2001-12-31T12:00:00</hj:TARGETSTARTDATE>


  <hj:TARGETENDDATE>2001-12-31T12:00:00</hj:TARGETENDDATE>


  <hj:ACTSTARTDATE>2001-12-31T12:00:00</hj:ACTSTARTDATE>


  <hj:ACTENDDATE>2001-12-31T12:00:00</hj:ACTENDDATE>


  <hj:LASTUPDATEDTS>2001-12-31T12:00:00</hj:LASTUPDATEDTS>


  <hj:ZONE>Zone identifier (will be filled by MOR)</hj:ZONE>


  <hj:LOCATION>POINT(4.836371863811936 45.76751923066087)</hj:LOCATION>


  <hj:EXThjRKEQUIPMENTID>2333 (WERF ID)</hj:EXThjRKEQUIPMENTID>


  <hj:EXThjRKEQUIPMENTTYPE>wWashout (MOR type)</hj:EXThjRKEQUIPMENTTYPE>


  <hj:UPDATEDBY>qsiraut</hj:UPDATEDBY>


  <hj:LEAD>qsiraut</hj:LEAD>


  <hj:NEThjRK>WATER</hj:NEThjRK>


  <hj:ADDRESS>Address</hj:ADDRESS>


  <hj:PERFORMEDBY>qsiraut</hj:PERFORMEDBY>


  <hj:LOCOWNERID>qsiraut</hj:LOCOWNERID>


  <hj:LOCOWNERDETAILS>Phone, email details</hj:LOCOWNERDETAILS>


  <hj:LOCCONTACTID>qsiraut</hj:LOCCONTACTID>


  <hj:LOCCONTACTDETAILS>Phone, email details</hj:LOCCONTACTDETAILS>


  <hj:REPORT>The result of the hjrk order</hj:REPORT>


  <hj:SRCEVENTLIST>


  <hj:SRCEVENT>


  <hj:SRCEVTCATEGORY>ALERT</hj:SRCEVTCATEGORY>


  <hj:SRCEVTTYPE>BACKFLOW (MOR alert/event type)</hj:SRCEVTTYPE>


  <hj:SRCEVTID>BF001 (WERF ID)</hj:SRCEVTID>


  <hj:SRCEVTDATE>2001-12-31T12:00:00</hj:SRCEVTDATE>


  <hj:SRCEVTCURRVALUE/>


  <hj:SRCEVTORIGVALUE/>


  <hj:SRCEVTCOMMENT/>


  <hj:SOPREFERENCE/>


  </hj:SRCEVENT>


  </hj:SRCEVENTLIST>


  </hj:hjrkorder>


  <hj:hjrkorder>


  <hj:hjEXTID>124</hj:hjEXTID>


  <hj:MODEL_ID>XXX_WERF</hj:MODEL_ID>


  <hj:SUBJECT>Short description of another hjrk order</hj:SUBJECT>


  <hj:DESCRIPTION>Long description of another hjrk order</hj:DESCRIPTION>


  <hj:DOMAIN>CUSTOMER</hj:DOMAIN>


  <hj:CATEGORY>Custom category</hj:CATEGORY>


  <hj:hjRKORDERTYPE>Custom type</hj:hjRKORDERTYPE>


  <hj:hjRKTYPE>Custom hjrk type</hj:hjRKTYPE>


  <hj:SUBTYPE>Custom hjrk subtype</hj:SUBTYPE>


  <hj:FAILURE>Custom failure code</hj:FAILURE>


  <hj:PRIORITY>Custom priority level</hj:PRIORITY>


  <hj:STATUS>APPR</hj:STATUS>


  <hj:JOBPLAN>Custom job plan code</hj:JOBPLAN>


  <hj:CREATIONDATE>2001-12-31T12:00:00</hj:CREATIONDATE>


  <hj:CREATIONTYPE>USER</hj:CREATIONTYPE>


  <hj:CREATEDBY>qsiraut</hj:CREATEDBY>


  <hj:TARGETSTARTDATE>2001-12-31T12:00:00</hj:TARGETSTARTDATE>


  <hj:TARGETENDDATE>2001-12-31T12:00:00</hj:TARGETENDDATE>


  <hj:ACTSTARTDATE>2001-12-31T12:00:00</hj:ACTSTARTDATE>


  <hj:ACTENDDATE>2001-12-31T12:00:00</hj:ACTENDDATE>


  <hj:LASTUPDATEDTS>2001-12-31T12:00:00</hj:LASTUPDATEDTS>


  <hj:ZONE>Zone identifier (will be filled by MOR)</hj:ZONE>


  <hj:LOCATION>POINT(4.836371863811936 45.76751923066087)</hj:LOCATION>


  <hj:EXThjRKEQUIPMENTID>2333 (WERF ID)</hj:EXThjRKEQUIPMENTID>


  <hj:EXThjRKEQUIPMENTTYPE>wWashout (MOR type)</hj:EXThjRKEQUIPMENTTYPE>


  <hj:UPDATEDBY>qsiraut</hj:UPDATEDBY>


  <hj:LEAD>qsiraut</hj:LEAD>


  <hj:NEThjRK>WATER</hj:NEThjRK>


  <hj:ADDRESS>Address</hj:ADDRESS>


  <hj:PERFORMEDBY>qsiraut</hj:PERFORMEDBY>


  <hj:LOCOWNERID>qsiraut</hj:LOCOWNERID>


  <hj:LOCOWNERDETAILS>Phone, email details</hj:LOCOWNERDETAILS>


  <hj:LOCCONTACTID>qsiraut</hj:LOCCONTACTID>


  <hj:LOCCONTACTDETAILS>Phone, email details</hj:LOCCONTACTDETAILS>


  <hj:REPORT>The result of the hjrk order</hj:REPORT>


  <hj:SRCEVENTLIST>


  <hj:SRCEVENT>


  <hj:SRCEVTCATEGORY>READINGTHRESHOLD</hj:SRCEVTCATEGORY>


  <hj:SRCEVTTYPE>FLOW</hj:SRCEVTTYPE>


  <hj:SRCEVTID/>


  <hj:SRCEVTDATE>2001-12-31T12:00:00</hj:SRCEVTDATE>


  <hj:SRCEVTCURRVALUE>34.0</hj:SRCEVTCURRVALUE>


  <hj:SRCEVTORIGVALUE>32.0</hj:SRCEVTORIGVALUE>


  <hj:SRCEVTCOMMENT>Threshold is set to 30.0</hj:SRCEVTCOMMENT>


  <hj:SOPREFERENCE/>


  </hj:SRCEVENT>


  </hj:SRCEVENTLIST>


  </hj:hjrkorder>


  </hj:request>


  <hj:request type="UPDATE">


  <hj:hjrkorder>


  <hj:hjEXTID>125</hj:hjEXTID>


  <hj:MODEL_ID>XXX_WERF</hj:MODEL_ID>


  <hj:SUBJECT>New Short description of the hjrk order</hj:SUBJECT>


  <hj:DESCRIPTION>New Long description of the hjrk order</hj:DESCRIPTION>


  <hj:DOMAIN>PLANT</hj:DOMAIN>


  <hj:CATEGORY>Custom category</hj:CATEGORY>


  <hj:hjRKORDERTYPE>Custom type</hj:hjRKORDERTYPE>


  <hj:hjRKTYPE>Custom hjrk type</hj:hjRKTYPE>


  <hj:SUBTYPE>Custom hjrk subtype</hj:SUBTYPE>


  <hj:FAILURE>Custom failure code</hj:FAILURE>


  <hj:PRIORITY>Custom priority level</hj:PRIORITY>


  <hj:STATUS>APPR</hj:STATUS>


  <hj:JOBPLAN>Custom job plan code</hj:JOBPLAN>


  <hj:CREATIONDATE>2001-12-31T12:00:00</hj:CREATIONDATE>


  <hj:CREATIONTYPE>USER</hj:CREATIONTYPE>


  <hj:CREATEDBY>qsiraut</hj:CREATEDBY>


  <hj:TARGETSTARTDATE>2001-12-31T12:00:00</hj:TARGETSTARTDATE>


  <hj:TARGETENDDATE>2001-12-31T12:00:00</hj:TARGETENDDATE>


  <hj:ACTSTARTDATE>2001-12-31T12:00:00</hj:ACTSTARTDATE>


  <hj:ACTENDDATE>2001-12-31T12:00:00</hj:ACTENDDATE>


  <hj:LASTUPDATEDTS>2001-12-31T12:00:00</hj:LASTUPDATEDTS>


  <hj:ZONE>Zone identifier (will be filled by MOR)</hj:ZONE>


  <hj:LOCATION>POINT(4.836371863811936 45.76751923066087)</hj:LOCATION>


  <hj:EXThjRKEQUIPMENTID>2333 (WERF ID)</hj:EXThjRKEQUIPMENTID>


  <hj:EXThjRKEQUIPMENTTYPE>wWashout (MOR type)</hj:EXThjRKEQUIPMENTTYPE>


  <hj:UPDATEDBY>qsiraut</hj:UPDATEDBY>


  <hj:LEAD>qsiraut</hj:LEAD>


  <hj:NEThjRK>WATER</hj:NEThjRK>


  <hj:ADDRESS>Address</hj:ADDRESS>


  <hj:PERFORMEDBY>qsiraut</hj:PERFORMEDBY>


  <hj:LOCOWNERID>qsiraut</hj:LOCOWNERID>


  <hj:LOCOWNERDETAILS>Phone, email details</hj:LOCOWNERDETAILS>


  <hj:LOCCONTACTID>qsiraut</hj:LOCCONTACTID>


  <hj:LOCCONTACTDETAILS>Phone, email details</hj:LOCCONTACTDETAILS>


  <hj:REPORT>The result of the hjrk order</hj:REPORT>


  <hj:SRCEVENTLIST>


  <hj:SRCEVENT>


  <hj:SRCEVTCATEGORY>ALERT</hj:SRCEVTCATEGORY>


  <hj:SRCEVTTYPE>BACKFLOW (MOR alert/event type)</hj:SRCEVTTYPE>


  <hj:SRCEVTID>BF001 (WERF ID)</hj:SRCEVTID>


  <hj:SRCEVTDATE>2001-12-31T12:00:00</hj:SRCEVTDATE>


  <hj:SRCEVTCURRVALUE/>


  <hj:SRCEVTORIGVALUE/>


  <hj:SRCEVTCOMMENT/>


  <hj:SOPREFERENCE/>


  </hj:SRCEVENT>


  </hj:SRCEVENTLIST>


  </hj:hjrkorder>


  </hj:request>


</hj:operations>


Have you tried your same method with just passing a regular string first? ie try passing in "This is my test string" and seeing if you get the same error? If you do, then maybe you have a permission issue, with the system not having permissions to call your function. You may have to set up a user who can run the function, and possible create an appkey for that user that gets passed in with your request call in order to have the proper permissions. Just a thought.

I have tried all the above bar using a string but as the simple XML works without and the complex form doesn't I don't thing that its an auth problem - It seems to be caused by the use of a namespace e.g. <ab:tag> rather than <tag>

mhollenbach
5-Regular Member
(To:grahamall)

So the big thing you are missing here is the "postParameter" parameter that you need to specify on the end of the URL. This is how the content will know where it needs to go. For example,

var request = <request>

    <workorder>

      <WOEXTID>123</WOEXTID>

    </workorder>

</request>;


if you are trying to post that var request xml above, you can keep content:request but you will need to modify the url to url:'../Thingworx/Things/workGateway/Services/workOrder?postParameter=parameter_name_in_service'

var params = {

    url: '.../Thingworx/Things/workGateway/Services/workOrder?postParameter=parameter_name_in_service' /* STRING */,

  content: request /* XML */

};

var responce = Resources["ContentLoaderFunctions"].PostXML(params);

result = responce..*::status;


Where it says parameter_name_in_service you will want to change that to the XML parameter name you have defined in that workOrder service.

Hopefully this helps.

Sorry, I was not clear in my original question, I'm using this URL

server/Thingworx/Things/IOWWorkOrderGateway/Services/workOrder?method=post&value=<xml>...  ...</xml>

And it works fine provided that the xml is not to long

What I'd like to do is the equivalent of this

2015-08-07_09-08-21.png

Where the XML is submitted as the body of the request rather than as a parameter as I thing that Thingworx is struggling with the length of the XML I'm using.

mhollenbach
5-Regular Member
(To:grahamall)

For you to pass the body defined in Postman to your service you need to provide the postParameter=name_of_input_parameter_to_service segment to the URL; this will tell the REST call that you want the body you are providing to be posted to the input parameter of the service you are calling.

What you have in that screen shot is fine, just add that segment I bolded above (where name_of_input_parameter_to_service is your predefined input parameter)

Do you have an input parameter to your service of base type XML? If not you need to add one to accept the XML content.

Top Tags