Community Tip - Your Friends List is a way to easily have access to the community members that you interact with the most! X
I had just finished writing an integration test that needed to update a Thing on a ThingWorx server using only classes in the Java JDK with as few dependencies as possible and before I moved on, I though I would blog about this example since it makes a great starting point for posting data to ThingWorx. ThingWorx has a Java SDK which uses the HTTP Websockets protocol and you can download it from our online at the ThingWorx IoT Marketplace that offers great performance and far more capabilities than this example. If you are looking, however for the simplest, minimum dependency example of delivering data to ThingWorx, this is it.
This examples uses the REST interface to your ThingWorx server. It requires only classes already found in your JDK (JDK 7) and optionally includes the JSON Simple jar. References to this jar can be removed if you want to create your property update JSON object yourself. Below is the Java Class.
package com.thingworx.rest;
import org.json.simple.JSONObject;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Author: bill.reichardt@thingworx.com
* Date: 4/22/16
*/
public class SimpleThingworxRestPropertyUpdater {
static {
//Disable All SSL Security Testing (Not for production!)
try {
disableSSLCertificateChecking();
} catch (Exception e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){
public boolean verify(String hostname, SSLSession session) {return true;}
});
}
public static void main(String[] args) {
// like http://localhost:8080 or https://localhost:443
String serverUrl = args[0];
// Generate one of these from the composer under Application Keys
String appKey = args[1];
String thingName = args[2];
// You don't have to use the Simple JSON class, just pass a JSON string to restUpdateProperties()
// This Thing has three properties, a (NUMBER), b (STRING) and c (BOOLEAN)
JSONObject properties = new JSONObject();
properties.put("a", new Integer(100));
properties.put("b", "My New String Value");
properties.put("c", true);
String payload= properties.toJSONString();
try {
int response = restUpdateProperties(serverUrl, appKey, thingName, payload);
System.out.println("Response Status="+response);
} catch (Exception e) {
e.printStackTrace();
}
}
public static int restUpdateProperties(String serverUrl, String appKey, String thingName, String payload) throws IOException {
String httpUrlString = serverUrl + "/Thingworx/Things/"+thingName+"/Properties/*";
System.out.println("Performing HTTP PUT request to "+httpUrlString);
System.out.println("Payload is "+payload);
URL url = new URL(httpUrlString);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setUseCaches(false);
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("PUT");
httpURLConnection.setRequestProperty ("Content-Type", "application/json");
httpURLConnection.setRequestProperty ("appKey",appKey);
OutputStreamWriter out = new OutputStreamWriter(httpURLConnection.getOutputStream());
out.write(payload);
out.close();
httpURLConnection.getInputStream();
return httpURLConnection.getResponseCode();
}
/**
* Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
* aid testing on a local box, not for use on production.
*/
private static void disableSSLCertificateChecking() throws KeyManagementException, NoSuchAlgorithmException {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
} };
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
}
When run, it prints out what the request body should look like in JSON:
Performing HTTP PUT request to https://localhost:443/Thingworx/Things/SimpleThing/Properties/*
Payload is {"a":100,"b":"My New String Value","c":true}
Response Status=200
I have attached the full Gradle project that builds and runs this example class as a zip file to this article.
When you download it, if you have Java JDK 7 already installed an on your path, you can run the example with the command:
On Linux or OSX
./gradlew simplerest
Windows
gradlew.bat simplerest
Don't forget to edit the build.gradle file to use your server's URL and application key. You will also find the Thing used in this example in the entities folder of this project and you can import it on your server to test it out. It is a Thing that is based on GenericThing and has three properties, a (NUMBER), b (STRING) and c (BOOLEAN).
Example is really helpful..Thanks for sharing it.
Awsome . It works
i am able to update single property using the rest calls but when i am trying to update all the properties , i am getting following error :
Server returned HTTP response code: 500 for URL: http://localhost:8085/Thingworx/Things/Employee1/Properties/*
Here is what i am doing :
URL url = new URL("http://localhost:8085/Thingworx/Things/Employee1/Properties/*");
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setUseCaches(false);
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("PUT");
httpURLConnection.setRequestProperty ("Content-Type", "application/json");
httpURLConnection.setRequestProperty ("appKey",appKey);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date currentDate = new Date();
JSONObject params = new JSONObject();
params.put("InTime", df.format(currentDate));
params.put("EmpId", empId);
params.put("EmpName", "himesh");
params.put("Role","TSE");
String payload = params.toString();
System.out.println(payload);
OutputStreamWriter out = new OutputStreamWriter(httpURLConnection.getOutputStream());
out.write(payload);
System.out.println(out);
out.close();
httpURLConnection.getInputStream();
return httpURLConnection.getResponseCode();
Use the service, setPropertyValues() instead. It will allow you to update multiple properties in a single request, similar to what you are trying to do with your put.
Here is some information how how to make this request.
Body:
{"values":{"created":1513608545510,"description":"","name":"Infotable","dataShape":{"fieldDefinitions":{"name":{"name":"name","aspects":{"isPrimaryKey":true},"description":"Property name","baseType":"STRING","ordinal":0},"time":{"name":"time","aspects":{},"description":"time","baseType":"DATETIME","ordinal":0},"value":{"name":"value","aspects":{},"description":"value","baseType":"VARIANT","ordinal":0},"quality":{"name":"quality","aspects":{},"description":"quality","baseType":"STRING","ordinal":0}},"name":"NamedVTQ","description":"Property name, value, time, quality, state"},"rows":[{"name":"property0","value":"5","quality":"GOOD"},{"name":"property1","value":"10","quality":"BAD"}]}}
When in doubt, try something in composer with Chrome developer tools turned on and you can see how to form a rest request for anything.