FIWARE [NGSI] Orion-Cygnus-Hadoop HTTPBadRequestException: 'fiware-servicepath' through an Orion subscription - fiware

I want to persist some historical data from my server. So the documentation says that you must first send a subscription to Orion and then Orion will send the notification to Cygnus.
I made the subscription like this:
Entity payload = Entity.json("{\r\n" +
" \"entities\": [{\r\n" +
" \"type\": \"Usuario\",\r\n" +
" \"isPattern\": \"true\",\r\n" +
" \"id\": \"Usuario*\"\r\n" +
" }],\r\n" +
" \"attributes\": [],\r\n" +
" \"reference\": \"http://192.168.10.3:5050/notify\",\r\n" +
" \"duration\": \"P4Y\",\r\n" +
" \"notifyConditions\": [{\r\n" +
" \"type\": \"ONCHANGE\",\r\n" +
" \"condValues\": [\r\n" +
" \"speed\"\r\n" +
" ]\r\n" +
" }],\r\n" +
" \"throttling\": \"PT0.001S\"\r\n" +
"}");
Response response = client.target("http://192.168.10.3:1026/v1/subscribeContext")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(payload);
And the creation of entities:
Entity payload = Entity.json("{ \"type\": \"Usuario\", \"id\": \"Usuario22\", \"temperature\": { \"value\": \"80.0\" }, \"location\": { \"value\": \""+latitud+", "+altitud+"\", \"type\": \"geo:point\", \"metadata\": { \"crs\": { \"value\": \"WGS84\" } } }}");
Response response = client.target("http://192.168.10.3:1026/v2/entities")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(payload);
Then, Cygnus log tell me:
HTTPBadRequestException: 'fiware-servicepath' header value does not match the number of notified context responses [...]
Do any of you know why this is happening? The creation of the headers should be done by Orion or, failing that, by using the configuration of the Cygnus...
Thank you in advance.
UPDATE:
I have changed the http client of the server to make it easier to incorporate headers.
My subscription:
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://192.168.10.3:1026/v1/subscribeContext");
String json = "{\r\n" +
" \"entities\": [{\r\n" +
" \"type\": \"cargador\",\r\n" +
" \"isPattern\": \"true\",\r\n" +
" \"id\": \"cargador*\"\r\n" +
" }],\r\n" +
" \"attributes\": [\"speed\"],\r\n" +
" \"reference\": \"http://192.168.10.3:5050/notify\",\r\n" +
" \"duration\": \"P4Y\",\r\n" +
" \"notifyConditions\": [{\r\n" +
" \"type\": \"ONCHANGE\",\r\n" +
" \"condValues\": [\r\n" +
" \"speed\"\r\n" +
" ]\r\n" +
" }],\r\n" +
" \"throttling\": \"PT0.001S\"\r\n" +
"}";
StringEntity entity;
try {
entity = new StringEntity(json);
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("fiware-servicepath", "/");
CloseableHttpResponse response;
response = client.execute(httpPost);
System.out.println(response.getStatusLine());
client.close();
} catch (UnsupportedEncodingException e1) {
My update context:
CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build()).build();
HttpPost httpPost = new HttpPost("http://192.168.10.3:1026/v1/updateContext");
String json = "{\r\n" +
" \"contextElements\": \r\n" +
"\r\n" +
" \r\n" +
"\r\n" +
" [\r\n" +
" {\r\n" +
" \"type\": \"cargador\",\r\n" +
" \"isPattern\": \"false\",\r\n" +
" \"id\": \"cargador48\",\r\n" +
" \"attributes\": [\r\n" +
" {\r\n" +
" \"name\": \"speed\",\r\n" +
" \"type\": \"float\",\r\n" +
" \"value\": \"798\"\r\n" +
" }\r\n" +
" ]\r\n" +
" }\r\n" +
" ],\r\n" +
" \"updateAction\": \"APPEND\"\r\n" +
" }";
StringEntity entity;
try {
entity = new StringEntity(json);
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("fiware-servicepath", "/");
CloseableHttpResponse response;
response = client.execute(httpPost);
System.out.println(response.getStatusLine());
client.close();
And the trace I generate is like this:
Thank you again.

The error message you are receiving would seem to indicate that you are attempting to send a subscription to Cygnus using the newer NGSI v2 format however the current Cygnus release only accepts notifications in the older NGSI v1 format- the attrsFormat=legacy attribute is therefore required when setting up the subscription
See this question for more details about how to fix it.

Related

Apex: Get public link of a file uploaded to Google drive service account

I was able to upload an image file to google drive (Service Account) using google drive API. In return of the post, I got a filId from google.
Uploaded file to drive
I then used this fileId to create public read-only permission on the file.
added permission to file
But how do I get the public URL for the file? (I am using V3 of drive API)
I tried using "webContentLink":"https://drive.google.com/uc?id={FileID}&export=download" but the downloaded file is corrupted and not opening.
I also tried using "alternateLink": "https://drive.google.com/file/d/{FileId}/view?usp=drivesdk" but this also not working.
trying to view alternateLink
Here is my method to upload file to drive:
public static String uploadFile(String accesstoken,String FolderId, blob file, String filetype, String filename){
String thumbnailLink;
String fid;
String clink;
try{
if(String.isBlank(accesstoken) || file.size()==0 || String.isBlank(filetype) || String.isBlank(filename)){
throw new applicationException('One or more required parameters are not passed!');
}
}catch(applicationException e){
System.debug(LoggingLevel.ERROR,'Call exception ' + e.getMessage());
}
String boundary = '----------9889464542212';
String delimiter = '\r\n--' + boundary + '\r\n';
String close_delim = '\r\n--' + boundary + '--';
String bodyEncoded = EncodingUtil.base64Encode(file);
String body = '';
if(FolderId !=''){
body = delimiter + 'Content-Type: application/json; charset=UTF-8\r\n\r\n' + '{ "name" : "' + filename + '",' + ' "mimeType" : "' + filetype + '",' + '"parents":[{"id":"'+ FolderId +'"}]}' + delimiter + 'Content-Type: ' + filetype + '\r\n' + '\r\n' + bodyEncoded + close_delim;
}
else{
body = delimiter + 'Content-Type: application/json; charset=UTF-8\r\n\r\n' + '{ "name" : "' + filename + '",' + ' "mimeType" : "' + filetype + '"}'+ delimiter + 'Content-Type: ' + filetype + '\r\n' + '\r\n' + bodyEncoded + close_delim;
}
System.debug('Body: '+body);
try{
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&withLink=true');
req.setHeader('Authorization', 'Bearer ' + accesstoken);
req.setHeader('Content-Type', 'multipart/related; boundary="' + boundary + '"');
req.setHeader('Content-length', String.valueOf(body.length()));
req.setBody(body);
req.setMethod('POST');
req.setTimeout(60 * 1000);
HttpResponse resp = http.send(req);
System.debug(resp.getBody());
system.debug('Test');
Map<String, Object> p = (Map<String, Object>) JSON.deserializeUntyped(resp.getBody());
thumbnailLink= (String) p.get('thumbnailLink');
fid=(String) p.get('id');
System.debug('File Id: '+fid);
clink='https://drive.google.com/uc?export=view&id='+fid;
System.debug('clink: '+clink);
} catch
(Exception e) {
System.debug(LoggingLevel.ERROR,
'Call exception ' + e.getMessage());
}
String body1 = '{"role":"reader","type":"anyone"}';
try{
//Changing file permission to public viewable using link
Http http = new Http();
HttpRequest req1 = new HttpRequest();
req1.setEndpoint('https://www.googleapis.com/drive/v2/files/'+fid+'/permissions');
req1.setHeader('Authorization', 'Bearer ' + accesstoken);
req1.setHeader('Content-Type', 'application/json');
req1.setHeader('Content-length', String.valueOf(body1.length()));
req1.setBody(body1);
req1.setMethod('POST');
req1.setTimeout(60 * 1000);
HttpResponse resp1 = http.send(req1);
System.debug(resp1.getBody());
} catch
(Exception e) {
System.debug(LoggingLevel.ERROR,
'Call exception ' + e.getMessage());
}
return fid;
}

How to get like count value from response?

{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"likecount": 0,
"unlikeCount": 0,
"shareCount": 0,
"i_id": 297,
"p_id": 297,
"name": "Airport runways columbia hon",
"description": "Airport runways columbia hongkong aviation airplanes aeroplanes",
"c_id": 1,
"status_id": 1,
"source_id": 149,
"date_created": null,
"parentinfograph": "Staffing insurance liability ",
"internal_url": "http://167.99.86.81:8000/media/DQ297.jpg",
"external_url": "http://www.aertecsolutions.com/wp-content/uploads/2017/03/Infographic-Runway-ENG.jpg",
"mt_id": 1,
"mtcode": "Business"
}
]
}
First of all, create a POJO class from JSON string using :
http://www.jsonschema2pojo.org/
Then, create an instance of POJO class. Now, using GSON, you can set the values in the instance. Lastly, you can get the value using getter method
For eg.
Usermodel usermodel = new Gson().fromJson(<JSON string>, UserModel.class);
Usermodel is my POJO class here.
Please check below:
#Test
public void getlikecount() {
String JSON = "{\r\n" +
" \"count\": 1,\r\n" +
" \"next\": null,\r\n" +
" \"previous\": null,\r\n" +
" \"results\": [\r\n" +
" {\r\n" +
" \"likecount\": 0,\r\n" +
" \"unlikeCount\": 0,\r\n" +
" \"shareCount\": 0,\r\n" +
" \"i_id\": 297,\r\n" +
" \"p_id\": 297,\r\n" +
" \"name\": \"Airport runways columbia hon\",\r\n" +
" \"description\": \"Airport runways columbia hongkong aviation airplanes aeroplanes\",\r\n" +
" \"c_id\": 1,\r\n" +
" \"status_id\": 1,\r\n" +
" \"source_id\": 149,\r\n" +
" \"date_created\": null,\r\n" +
" \"parentinfograph\": \"Staffing insurance liability \",\r\n" +
" \"internal_url\": \"http://167.99.86.81:8000/media/DQ297.jpg\",\r\n" +
" \"external_url\": \"http://www.aertecsolutions.com/wp-content/uploads/2017/03/Infographic-Runway-ENG.jpg\",\r\n" +
" \"mt_id\": 1,\r\n" +
" \"mtcode\": \"Business\"\r\n" +
" }\r\n" +
" ]\r\n" +
"}";
JsonPath jsonpath = new JsonPath(JSON);
System.out.println("value of key->likecount: "+jsonpath.getString("results.likecount[0]"));
}
Output: value of key->likecount: 0

Extract some value without key from a json object

I am using java to extract a list of node ids from an elastic search running tasks response.
The response looks like this
{
"nodes": {
"ZKUuxQZpRCCcJ0njBM1P0A": {
"name": "ZKUuxQZ",
"transport_address": "127.0.0.1:9300",
"host": "127.0.0.1",
"ip": "127.0.0.1:9300",
"roles": [
"master",
"data",
"ingest"
],
"tasks": {
"ZKUuxQZpRCCcJ0njBM1P0A:118": {
"node": "ZKUuxQZpRCCcJ0njBM1P0A",
"id": 118,
"type": "transport",
"action": "indices:data/write/delete/byquery",
"start_time_in_millis": 1527808643421,
"running_time_in_nanos": 154234724059,
"cancellable": true,
"headers": {}
}
}
}
}
}
In this example, I want to exact ZKUuxQZpRCCcJ0njBM1P0A:118. Can someone give me an example how to extract this information?
Option 1, java json parser. I wanted to write a response class and parse the json string, but ZKUuxQZpRCCcJ0njBM1P0A:118 is not in the key:value format. I am not sure how to extract it.
Option 2, using regex. The node id part may also have - or _. Can someone provide a neat java regex solution? So far my regex is [a-zA-Z0-9\-\_]+\:[0-9]+, I am not sure if this is safe enough.
Thanks.
One way you can do this is by using org.json library and create JSONObject and using keys() you can get all the keys and use this to achieve your task
Add the following dependency in your pom.xml
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
Then you can do something like below:
String jsonString = "{\n" +
" \"nodes\": {\n" +
" \"ZKUuxQZpRCCcJ0njBM1P0A\": {\n" +
" \"name\": \"ZKUuxQZ\",\n" +
" \"transport_address\": \"127.0.0.1:9300\",\n" +
" \"host\": \"127.0.0.1\",\n" +
" \"ip\": \"127.0.0.1:9300\",\n" +
" \"roles\": [\n" +
" \"master\",\n" +
" \"data\",\n" +
" \"ingest\"\n" +
" ],\n" +
" \"tasks\": {\n" +
" \"ZKUuxQZpRCCcJ0njBM1P0A:118\": {\n" +
" \"node\": \"ZKUuxQZpRCCcJ0njBM1P0A\",\n" +
" \"id\": 118,\n" +
" \"type\": \"transport\",\n" +
" \"action\": \"indices:data/write/delete/byquery\",\n" +
" \"start_time_in_millis\": 1527808643421,\n" +
" \"running_time_in_nanos\": 154234724059,\n" +
" \"cancellable\": true,\n" +
" \"headers\": {}\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
JSONObject jsonObject = new JSONObject(jsonString);
Set<String> topLevelKeys = jsonObject.keySet();
for (String key : topLevelKeys) {
Object value = jsonObject.get(key);
if (value instanceof JSONObject) {
JSONObject valueObject = jsonObject.getJSONObject(key);
System.out.println(valueObject.toString());
}
}
Extend this as per your requirement.
So regex is too hacky and I figured it out using gson. I wish ElasticSearch can offer us some standard library to extract all kinds of responses. Here is my solution using gson.
import com.google.gson.*;
import org.json.JSONObject;
public class test {
public static void main(String[] args) throws Exception {
String jsonString = "json_format elasticsearch reponse for listing running tasks"
JsonParser parser = new JsonParser();
JsonObject jsonObject = parser.parse(content).getAsJsonObject();
jsonObject.getAsJsonObject("nodes").entrySet().forEach(
s -> {
s.getValue().getAsJsonObject().getAsJsonObject("tasks").entrySet().forEach( s2 -> {
System.out.println(s2.getKey());
});
});
}
It prints all the running task ids like the following. It's technically nodeId:taskId, but ES has a very vague description in their task API docs(It says you can use TASK_ID to check a status of a task, well that TASK_ID is nodeId:taskId).
Mw-3i39gTHGxu5c8z9viQQ:503209021
DZ29LMsWR0aW9guWZTYe2Q:482931604
6CAbDZSWR8SfwZgnRT0qNg:494351185
Use the following regex:
[a-zA-Z0-9-_]*[0-9]+[a-zA-Z]+:[0-9]*
You can find the test result here:
https://regexr.com/3qdug

Deserialize json into complex Map object using jackson

Consider the following json example
{
"key1" : {
"k11":["vala","valb","valc"],
"k12":["vald"],
"k13":["vale","valf"]
},
"key2" : {
"key21":["valg","valh","vali"],
"key22":["valj"],
"key23":["valk","vall"]
}
}
This translates into a Map<String,Map<String,List<String>>>.
Could anyone please let me know how i can convert this in this into this complex Map object. I do a a method called constructMapType, but not sure if it handles complex Map type.
Seems to work fine with .constructMapType(Map.class, String.class, Map.class)
public static void main(String[] args) throws Exception {
final String json
= "{\n"
+ " \"key1\" : {\n"
+ " \"k11\":[\"vala\",\"valb\",\"valc\"],\n"
+ " \"k12\":[\"vald\"],\n"
+ " \"k13\":[\"vale\",\"valf\"]\n"
+ " },\n"
+ " \"key2\" : {\n"
+ " \"key21\":[\"valg\",\"valh\",\"vali\"],\n"
+ " \"key22\":[\"valj\"],\n"
+ " \"key23\":[\"valk\",\"vall\"]\n"
+ " }\n"
+ "}";
ObjectMapper mapper = new ObjectMapper();
Map<String, Map<String, List<String>>> map
= mapper.readValue(json,TypeFactory.defaultInstance()
.constructMapType(Map.class, String.class, Map.class));
for (String outerKey: map.keySet()) {
System.out.println(outerKey + ": " + map.get(outerKey));
for (String innerKey: map.get(outerKey).keySet()) {
System.out.print(innerKey + ": [");
for (String listValue: map.get(outerKey).get(innerKey)) {
System.out.print(listValue + ",");
}
System.out.println("]");
}
}
}
You could go all the way down listing all the generics down to the List<String>, but as seen above it isn't necessary. But just to show what I mean
TypeFactory factory = TypeFactory.defaultInstance();
Map<String, Map<String, List<String>>> map
= mapper.readValue(json, factory.constructMapType(
Map.class,
factory.constructType(String.class),
factory.constructMapType(
Map.class,
factory.constructType(String.class),
factory.constructCollectionType(
List.class,
String.class))));

How to read from openTSDB with a JSON POST?

I am running my openTSDB on a virtual maschine and want to read data with a JSON POST request from a client.
Baseurl is the URL to my VM.
Whenever i send this request, i get an error "Unable to pass the given JSON" in my openTSDB. So what's wrong with my request?
Thanks in advance.
EDIT: The Json-Request is supposed to represent this GET Request (which works):
baseurl+"/api/query?start=1356994800000&m=sum:Leistung";
String url = baseurl;
URL obj = new URL(url + "/api/query");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("Content-type", "application/json; charset=utf-8");
con.setRequestProperty("Accept", "application/json; charset=utf-8");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeChars("{\n" +
" \"start\": 1356994800000,\n" +
" \"queries\": [\n" +
" {\n" +
" \"aggregator\": \"sum\",\n" +
" \"metric\": \"Leistung\"\n" +
" }\n" +
" ]\n" +
"}");
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
con.disconnect();
in.close();
System.out.println(response.toString());