Process instantiation

1
0
-1

Hello,

I have created bpm and bpm on Bonita studio. I am working on .net and able to query data from the database which is H2. The process uses form that is generated from the JSON contract form schema. I have problem posting data HTTP post using web API clients. On the client-side, all went fine and all statuses are Ok and data are serialized . I have created DTO for transfering data and when i insatiate process I go step by step debugging and everything is fine. Does Bonita community have a restriction with external API posting data?

Below you can see protion of the code what i have done so far and on console i have everuthing as it should be

[HttpPost("[action]")]

public async Task Complexi([FromBody]RequestViewModel obj)
{

var id = (string)TempData["id"];

var url = await _bonitaClient.GetData();
using (var handler = new HttpClientHandler { UseCookies = false })
{
using (var client = new HttpClient(handler))
{
var formContent = new Dictionary
{
{"username", "william.jobs"},
{"password", "bpm"},
{"redirect", "false"}

};
client.BaseAddress = new Uri(url);

client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string urls = "API/bpm/process/" + id + "/instantiation";
string urlt = "API/bpm/process/" + id + "/contract";
var setCookie = string.Empty;
var result = client.PostAsync("loginservice", new FormUrlEncodedContent(formContent)).Result;

var message = new HttpRequestMessage(HttpMethod.Get, urlt);
var st = "";
foreach (var header in result.Headers.Where(header => header.Key == "Set-Cookie"))
{
foreach (var value in header.Value)
{
st += value + ";";
}
break; // We only care about the first match.
}

message.Headers.Add("Cookie", st);

var Res = await client.SendAsync(message);

if (Res.IsSuccessStatusCode)
{
var json = JsonConvert.SerializeObject(obj);
var contacts = new StringContent(json, Encoding.UTF8, "application/json");
var t = await client.PostAsync(urls, contacts);

}

}
}

return Ok("Data has been sent");
}

2 answers

1
0
-1

Hi,

I tried to implement the same using Postman, i.e. log in, list processes, start a process and check that it worked.

I was able to do it on Bonita Community 7.10.3 without any trouble.

What I figured out is that I was careful to set the X-Bonita-API-Token header with the value retrieved from the login request. You can have a look to this documentation page for more details: Bonita REST API Authentication

From what I can see of your code snippet, I am not sure you do the same. Maybe you could check this.

Hope this helps,

Captain Bonita

Comments

Submitted by burimameti2001_... on Mon, 03/23/2020 - 20:44

Hello,

First i want to thank you for the responses , I am trying hard to figure out what really happening.

When i go debugging line by line i see that i am able to login and the X-Bonita-API-Token is stored on my code snippet variable st. When i proceed the following code passes and everything is ok

message.Headers.Add("Cookie", st);

var Res = await client.SendAsync(message);

if (Res.IsSuccessStatusCode)
{

}

. Let me explain the whole scenario

I want to send data from html generated from the contract json based on bonita model contract named RequestModel (id, name, comment)).

On my application i Have RequestViewModel that has same attributes like model in bonita RequestModel.

I am able to query process, generate form , get json from contract , but the problem occurs when i post data , instantiation.

It will be more than help, if you can find any code snippet in JavaScript for process instantiation.

Thanks

Burim Ameti

Submitted by nicolas.chabanoles on Tue, 03/24/2020 - 10:40

Hi,

Here is a snippet in Javascript.

var myHeaders = new Headers();
myHeaders.append("X-Bonita-API-Token", "f5145526-22ff-44a2-a1f7-bb296bf14372");
myHeaders.append("Cookie", "bonita.tenant=1; JSESSIONID=AB5D856CBC62BC4AE1AA20139EA11DF2);

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  redirect: 'follow'
};

fetch("http://localhost:8080/bonita/API/bpm/process/6108774665660467324/instantiation", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

See that the X-Bonita-API-Token is given as a dedicated header (not through cookies). You have to retrieve it from the cookies after login and make sure it is sent on all "write" API request calls (i.e. POST, PUT, DELETE). (This is a CSRF security check mechanism.)

Can you make sure that both the Cookie and the X-Bonita-API-Token header are sent and with a valid value? From what I can read from your code example you only send the Cookie, but not the X-Bonita-API-Token header.

I hope this helps,

Captain Bonita

Submitted by burimameti2001_... on Tue, 03/24/2020 - 15:43
Hello Captain, 
I see you  have added as hard coded but how to I cast dynamic those values. Which url are responsible for getting the Cockie and X-Bonita-API-Token, is it post or get method ,  please give me idea which url you are retrieving this token and session. Bellow i will provide snippet and please check if i am doing wrong something , always tokens are null in this code snippet

Please check this where I am doing wrong

$(document).ready(function () {
var formData = {
username: "walter.bates",
password: "bpm",
redirect: false
};

var url = (window.location).href;
var id = url.substring(url.lastIndexOf('/') + 1);
console.log(id);

var instantiation = "http:/localhost:8080/bonita/API/" + id + "/instantiation";
var contract = "http:/localhost:8080/bonita/API/system/session/1";

$("#form1").on('submit', function (e) {
e.preventDefault();
$.ajax({
url: "http:/localhost:8080/bonita/loginservice",
type: "POST",
data: formData,
xhrFields: { withCredentials: true },

success: function (data, textStatus, jqXHR) {
console.log(data),
$.ajax({
url: "http://localhost:8080/API/bpm/process/" + id + "/contract",
type: "GET",
xhrFields: { withCredentials: true },
success: function (data, textStatus, jqXHR) {
console.log('success getting session' + jqXHR);
var apiToken = jqXHR.getResponseHeader('X-Bonita-API-Token');
console.log('X-Bonita-API-Token: ' + apiToken);
var formDatas = $('#form1').serialize();
$.ajax({
url: "http://localhost:8080/API/bpm/process/" + id + "/instantiation",

type: "POST",
contentType: "application/x-www-form-urlencoded",
/*passing the X-Bonita-API-Token for the CSRF security filter*/
headers: { 'X-Bonita-API-Token': apiToken },

data: JSON.stringify(formDatas),
xhrFields: { withCredentials: true },
success: function (data, textStatus, jqXHR) {
console.log('tokennnnn', +apiToken);
console.log('success inserting data');
console.log(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('error updating user info');
}
});
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('error getting session');
}
});
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('error login');
}
});
});
});

Submitted by nicolas.chabanoles on Tue, 03/24/2020 - 16:07

Hi,

When calling the login API, the server adds a cookie with the X-Bonita-API-Token in it. You are supposed to extract it from the cookie and add it as a dedicated header on all other future call.

Here is an example on how to do it:

var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

var urlencoded = new URLSearchParams();
urlencoded.append("password", "install");
urlencoded.append("username", "install");
urlencoded.append("redirect", "false");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: urlencoded,
  redirect: 'follow'
};

function getCookie(cname) {
  var name = cname + "=";
  var decodedCookie = decodeURIComponent(document.cookie);
  var ca = decodedCookie.split(';');
  for(var i = 0; i!=ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}
fetch("http://localhost:8080/bonita/loginservice", requestOptions)
  .then(result => console.log(getCookie('X-Bonita-API-Token')))
  .catch(error => console.log('error', error));


In this example after logging in, I print on the console the value of the token, of course what you want is to store it and use it on all queries done on the REST API.

Let me know if it helped,
Captain Bonita

Submitted by burimameti2001_... on Thu, 03/26/2020 - 15:18

Hello, are you able to provide complet code snipet that gets the tokens and sends data let data be hardcoded in javascript. I tried but i have undefined send . i have this code snippet does not work

$(document).ready(function () {
$("#form1").on('submit', function (e) {
e.preventDefault();
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("username", "walter.bates");
urlencoded.append("password", "bpm");
urlencoded.append("redirect", "false");
var formData = $('#form1').serialize();
//console.log(formData);
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i++;) {
console.log(getCookie('X-Bonita-API-Token'));

//catch(error => console.log('error', error));
};
};
$.ajax({
url: '/Contract/Complexi',
headers: myHeaders,
type: "POST",
data: formData,
redirect: 'follow',
success: function (data) {
alert(data.message);
console.log(data);
},
error: function (xhr, resp, text) {
console.log(xhr, resp, text);
}
});
});

});

Submitted by burimameti2001_... on Thu, 03/26/2020 - 15:19

Hello, are you able to provide complete code snippet that gets the tokens and sends data to let data be hardcoded in JavaScript. I tried but I have undefined send. i have this code snippet does not work

$(document).ready(function () {
$("#form1").on('submit', function (e) {
e.preventDefault();
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("username", "walter.bates");
urlencoded.append("password", "bpm");
urlencoded.append("redirect", "false");
var formData = $('#form1').serialize();
//console.log(formData);
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i++;) {
console.log(getCookie('X-Bonita-API-Token'));

//catch(error => console.log('error', error));
};
};
$.ajax({
url: '/Contract/Complexi',
headers: myHeaders,
type: "POST",
data: formData,
redirect: 'follow',
success: function (data) {
alert(data.message);
console.log(data);
},
error: function (xhr, resp, text) {
console.log(xhr, resp, text);
}
});
});

});

Submitted by nicolas.chabanoles on Thu, 03/26/2020 - 17:34

Hi,

By combining my 2 code snippets I have the following code working when executed in my browser (Google Chrome DevTool):

var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

var urlencoded = new URLSearchParams();
urlencoded.append("password", "install");
urlencoded.append("redirect", "false");
urlencoded.append("username", "install");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: urlencoded,
  redirect: 'follow'
};

function getCookie(cname) {
  var name = cname + "=";
  var decodedCookie = decodeURIComponent(document.cookie);
  var ca = decodedCookie.split(';');
  for(var i = 0; i!=ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

fetch("http://localhost:8080/bonita/loginservice", requestOptions)
 .then(
  result => {
    var myHeaders = new Headers();
    myHeaders.append("X-Bonita-API-Token", getCookie('X-Bonita-API-Token'));
    
    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      redirect: 'follow'
    };

    fetch("http://localhost:8080/bonita/API/bpm/process/6108774665660467324/instantiation", requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
 })
  .catch(error => console.log('error', error));

The console then displays something like:

{"caseId":4002}

Where the caseId is the id of the newly started process instances. Which I can see when I access the Bonita Portal.

I hope this helps,

Captain Bonita

Submitted by burimameti2001_... on Thu, 03/26/2020 - 18:52

this seems good solution. but i have dynamic data forms div , where do you cast those data. I see uou use new headers .What kind of data you post ? name ?

Submitted by burimameti2001_... on Thu, 03/26/2020 - 20:12

When I instantiate I don't see data on a database, tried still not see data on database data I post is JSON in this format and that is generated from the button. I am able to post from the postman . This is my contract

{
"requestMemebershipInput" : {
"name": "test",
"reason": "111"
}
}

1
0
-1

Hi,

There is no restriction on Bonita Community regarding external client using REST APIs.

You say that everything is fine and works as expected, so what is the problem you are facing actually?

Captain Bonita

Comments

Submitted by burimameti2001_... on Fri, 03/20/2020 - 16:43

* I don't see data on database . If i run the process from Bonita studio everything is fine. On my application. I use the url

string urls = "API/bpm/process/" + id + "/instantiation";

* then i login with the code below where everything is fine

var result = client.PostAsync("loginservice", new FormUrlEncodedContent(formContent)).Result;

var message = new HttpRequestMessage(HttpMethod.Get, urlt);
var st = "";
foreach (var header in result.Headers.Where(header => header.Key == "Set-Cookie"))
{
foreach (var value in header.Value)
{
st += value + ";";
}
break; // We only care about the first match.
}

message.Headers.Add("Cookie", st);

var Res = await client.SendAsync(message);

after this i make check like this and send data

if (Res.IsSuccessStatusCode)
{
var json = JsonConvert.SerializeObject(obj);
var contacts = new StringContent(json, Encoding.UTF8, "application/json");
var t = await client.PostAsync(urls, contacts);

}

Everything goes fine but no data on database . On chrome i have status 200

Notifications