I am trying to pass json payload in variables as value to start a process definition using engine-rest api as below:-
API:
http://localhost:8080/engine-rest/process-definition/processService:1:9459dbe9-6b2c-11e8-b9e8-28d2447c697a/start
Body :
{
"variables": {
"payload": {
"value": {
"mode": "email",
"meta": [{
"key": "topic",
"value": "weather"
}, {
"key": "qos",
"value": "2"
}]
},
"type": "Json"
}
}
}
but it is giving 400 BAD REQUEST with below error:-
Must provide 'null' or String value for value of SerializableValue type 'Json'.
Also i have used a expression in my BPMN process to fetch a key-value pair like below, it also throwing me error :-
${S(payload).prop("mode").stringValue() == 'email'}
Now working steps:-
when i try to send body json payload in string format then it works fine.
API:
http://localhost:8080/engine-rest/process-definition/processService:1:9459dbe9-6b2c-11e8-b9e8-28d2447c697a/start
Body:
{
"variables": {
"payload": {
"value": "{\"mode\": \"email\",\"meta\": [{\"key\": \"topic\",\"value\": \"weather\"},{\"key\": \"qos\",\"value\": \"2\"}]}",
"type": "String"
}
}
}
same java code i am using here to fetch json payload-
public void notify(DelegateExecution delegateProcessExecution) throws Exception {
Object notificationPayload =
delegateProcessExecution.getVariable("payload");
if (null != notificationPayload) {
String notifyPayload = notificationPayload.toString();
JSONObject inputJson = new JSONObject(notifyPayload);
}
// ...
}
So i want this payload as json for whole process so that i don't need to convert it to string as above working example.
You should only change the type to "json", example:
{
"variables": {
"broker": {
"value": "{\"name\":\"Broker Name\"}",
"type": "json"
}
}
}
This is by design in the rest engine API, they support other data formats, too, so it has to be an escaped JSON String, see https://app.camunda.com/jira/browse/CAM-9617.
The solution is to pass an escaped JSON String as value, as you have pointed out above. One can also use "type": "Object" if the engine has a Jackson Java Bean on the classpath that matches the given value. You supply the bean type name in a valueInfo object:
https://docs.camunda.org/manual/7.10/reference/rest/process-definition/post-start-process-instance/#request-body
For example:
{
"variables": {
"payload": {
"value": "{\"mode\": \"email\",\"meta\": [{\"key\": \"topic\",\"value\": \"weather\"},{\"key\": \"qos\",\"value\": \"2\"}]}",
"type": "String",
"valueInfo": {
"objectTypeName": "my.own.BeanWithModeAndMetaProps",
"serializationDataFormat": "application/json"
}
}
}
}
Related
I'm using Azure functions with javascript, and i would like to modify the out binding of path in my functions. For example this is my function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "outputBlob",
"path": "container/{variableCreatedInFunction}-{rand-guid}",
"connection": "storagename_STORAGE",
"direction": "out",
"type": "blob"
}
]
I Would like to set {variableCreatedInFunction} in index.js, for example:
module.exports = async function (context, req) {
const data = req.body
const date = new Date().toISOString().slice(0, 10)
const variableCreatedInFunction = `dir/path/${date}`
if (data) {
var responseMessage = `Good`
var statusCode = 200
context.bindings.outputBlob = data
} else {
var responseMessage = `Bad`
var statusCode = 500
}
context.res = {
status: statusCode,
body: responseMessage
};
}
Couldn't find any way to this, is it possible?
Bindings are resolved before the function executes. You can use {DateTime} as a binding expression. It will by default be yyyy-MM-ddTHH-mm-ssZ. You can use {DateTime:yyyy} as well (and other formatting patterns, as needed).
Imperative bindings (which is what you want to achieve) is only available in C# and other .NET languages, the docs says:
Binding at runtime In C# and other .NET languages, you can use an
imperative binding pattern, as opposed to the declarative bindings in
function.json and attributes. Imperative binding is useful when
binding parameters need to be computed at runtime rather than design
time. To learn more, see the C# developer reference or the C# script developer reference.
MS might've added it to JS as well by now, since I'm pretty sure I read that exact section more than a year ago, but I can't find anything related to it. Maybe you can do some digging yourself.
If your request content is JSON, the alternative is to include the path in the request, e.g.:
{
"mypath":"a-path",
"data":"yourdata"
}
You'd then be able to do declarative binding like this:
{
"name": "outputBlob",
"path": "container/{mypath}-{rand-guid}",
"connection": "storagename_STORAGE",
"direction": "out",
"type": "blob"
}
In case you need the name/path to your Blob, you'd probably have to chain two functions together, where one acts as the entry point and path generator, while the other is handling the Blob (and of course the binding).
It would go something like this:
Declare 1st function with HttpTrigger and Queue (output).
Have the 1st function create your "random" path containing {date}-{guid}.
Insert a message into the Queue output with the content {"mypath":"2020-10-15-3f3ecf20-1177-4da9-8802-c7ad9ada9a33", "data":"some-data"} (replacing the date and guid with your own generated values, of course...)
Declare 2nd function with QueueTrigger and your Blob-needs, still binding the Blob path as before, but without {rand-guid}, just {mypath}.
The mypath is now used both for the blob output (declarative) and you have the information available from the queue message.
It is not possiable to set dynamic variable in .js and let the binding know.
The value need to be given in advance, but this way may achieve your requirement:
index.js
module.exports = async function (context, req) {
context.bindings.outputBlob = "This is a test.";
context.done();
context.res = {
body: 'Success.'
};
}
function.json
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "outputBlob",
"path": "test/{test}",
"connection": "str",
"direction": "out",
"type": "blob"
}
]
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"str":"DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net"
}
}
Or you can just put the output logic in the body of function. Just use the javascript sdk.
I'm newbie to json. I'm learning more things in Json schema but I stood helpless in testing my user.json file against json-schema.json file. Please note I need to test with a javascript variable which should return either true or false to process further. Hereby I pasted my files.
json-schema.json
{
"description": "Any validation failures are shown in the right-hand Messages pane.",
"type": "object",
"properties": {
"foo": {
"type": "number"
},
"bar": {
"type": "string",
"enum": [
"a",
"b",
"c"
]
}
}
}
user.json
{
"foo": 12345,
"bar": "a"
}
When I tested the above code in http://jsonschemalint.com/#/version/draft-05/markup/json IT say's user.json is in right format. But I need to test locally
Thanks in advance.
You can use one of JSON schema validators.
Example of using one of these libraries, ajv:
import Ajv from 'ajv';
import schema from 'schema.json';
import data from 'data.json';
function isValid(schema, data) {
const ajv = new Ajv();
const valid = ajv.validate(schema, data);
if (!valid) {
console.log(ajv.errors);
return false;
}
return true;
}
As simple as it may seem, I cannot seem to figure out how to set recipients of a draft with Google's Gmail API. The documentation says that a users.messages Resource object contains a payload object that contains a headers object, and that headers object contains name-value pairs.
// example from google's gmail API documentation
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
It is within these headers I presume you set the "To" part of a draft, since the documentation says
List of headers on this message part. For the top-level message part, representing the entire message payload, it will contain the standard RFC 2822 email headers such as To, From, and Subject.
however, when I make a request that looks something like this
"payload" : {
"headers" : [
{
"name" : "To",
"value" : "me"
// "me" should direct the draft to myself
}
]
}
the To part of the draft is still left empty. Any solution or advice?
In your request you have this:
"headers" : [ "name" : "To", "value" : "me" ]
"headers" is supposed to be an array of objects but your array contains none.
Instead, it should look like this:
"headers": [ { "name": "To", "value": "me" } ]
Just like their example:
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": "To",
"value": "me"
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
So, it appears that I was misinterpreting documentation on the Gmail API. When you send a request to drafts.create, you do need to supply is a users.messages Resource, however, not all of it is writable. Only threadId, labelIds, and raw are writable objects. As it turns out, you aren't supposed to use the payload at all to set the To, From, etc. You are supposed to include them in your raw.
My new code looks something like this
let create = (toAddress, subject, content, callback) => {
gmail.users.drafts.create(
{
'userId' : 'me',
'resource' : {
'message' : {
'raw' : base64.encodeURI(
`To:${toAddress}\r\n` + // Who were are sending to
`Subject:${subject}\r\n` + // Subject
`Date:\r\n` + // Removing timestamp
`Message-Id:\r\n` + // Removing message id
`From:\r\n` + // Removing from
`${content}` // Adding our actual message
)
}
}
},
(err, response) => {
// Do stuff with response
callback(err, response);
}
)
}
I'm trying to add users to a Custom Audience in Facebook, and I believe I have bungled the payload piece of the request below.
The error returned is:
(#100) Missing required parameter: payload
For reference, I'm generating the hash using Crypto-JS. Here's the code I tried:
var payload = { "payload": [{ "schema": "EMAIL_SHA256", "data": [hash] }]};
FB.api('/000000000/users', 'post', payload, function (response) {
if (response && !response.error) {
alert("This worked");
} else {
alert(response.error.message);
}});
The FB.api documentation shows that it expects 'payload' as a JSON object (https://developers.facebook.com/docs/marketing-api/custom-audience-targeting/v2.3#add). I just haven't been able to figure out the correct syntax yet. The example in the Facebook API documentation shows the following:
payload = {"schema":"EMAIL_SHA256","data":["HASH", "HASH", "HASH" ]}
Here's what I have so far (not working):
var payload = { "payload": [{ "schema": "EMAIL_SHA256", "data": [hash] }]};
Can anyone assist with the syntax? I've found plenty of examples of JSON objects and arrays, but I haven't seen anything that matches this format:
payload = {"schema":"EMAIL_SHA256","data":["HASH", "HASH", "HASH" ]}
For the benefit of any other JS/JSON novices, I finally figured it out after more experimentation:
var payload = { "payload": { "schema": "EMAIL_SHA256", "data": [hash] } };
For some reason I can't get [object Object] out of the form. I'm using hte method found here:
http://badwing.com/multipart-form-data-ajax-uploads-with-angularjs/#comment-431
The JSON i'm sending is pretty complicated (sample):
{
"challenge_id": 262,
"priority": "0",
"cause_id": "29",
"timestamp": "2013-11-29 12:06:01",
"translations": {
"en": {
"name": "asdfgsfd",
"description": "sdfghfs"
}
},
"actions": {
"1": {
"type": "chek",
"step": "1",
"translations": {
"en": {
"description": "adsfas"
}
}
},
"2": {
"type": "chek",
"step": "2",
"translations": {
"en": {
"description": "fsdgsd"
}
}
}
}
}
My response looks like this:
Content-Disposition: form-data; name="challenge_json"
[object Object]
My request looks like this:
return $http.post( REQUEST_URL + '/ENDPOINT', {challenge_json:data}, {
transformRequest: function(data) {
console.log(data);
var fd = new FormData();
angular.forEach(data, function(value, key) {
fd.append(key, value);
});
console.log(fd);
return fd;
}
Im modifying the headers with a httpProvider configuration change. But have tried doing it in line and am getting the same result.
any help would be appreciated.
It seems you were close to the solution, but needed to unset the 'content-type' header in the options passed to $http, so that the xmlhttprequest object can add it automatically when it gets a formdata on its send method.
https://groups.google.com/d/topic/angular/MBf8qvBpuVE/discussion
see a playground here http://jsfiddle.net/Lv1n55db/1/
(providing FormData object directly and a no-op transform, or your way of providing a normal data object and transforming it to FormData in transformRequest is no significant difference, the key is in the headers option)
headers:{'Content-Type':undefined},
It may vary with differnt browsers and different angularjs versions too.
A more certain and stable approach, at least if you do not need file fields and such, could be to not use native FormData but implement the serialization to string yourself, as FormData polyfills do it.