Calling APIs from External Applications

Hi,

I was trying to initiate a task through the API calls from another application. As per to the documentation I was trying to login to /bonita/loginservice programmatically using URLConnection to obtain X-Bonita-API-Token so that I can make use of the token in the subsequent calls. But I'm unable to obtain X-Bonita-API-Token in the response header or cookies and seeing following error in the server log:

org.bonitasoft.console.common.server.login.credentials.LoginDatastore Error while logging in the engine API.

I had further referenced https://www.bonitasoft.com/videos/bonita-rest-api and tried to stimulate via SoapUI still not seeing the X-Bonita-API-Token . Can anyone advice me on this?

I was annoyed to refill a form everytime to test a process so I've built something quick in Excel VBA 

Calling PostOfferta() you can login and instantiate a process  adapting the code to you process definition.

 

Hope this helps :

Ciao Alberto

 

Public Const BonitaSession = "X-Bonita-API-Token"
Public Const urlServerPath = "http://localhost:8080/bonita"
Public Type JsonData
    KeyName As String
    KeyValue As String
End Type

Sub PostOfferta()
    Dim xmlhttp As New MSXML2.xmlhttp, myurl As String
    JS = GetLoginSession()
    DoEvents
    ProcessId = GetProcessId("Richiesta utilizzo macchine") 'GetProcessId("Gestione Offerte di Vendita")
    myurl = urlServerPath + "/API/bpm/process/" + ProcessId + "/instantiation"
    xmlhttp.Open "POST", myurl, False
    xmlhttp.setRequestHeader "Content-type", "application/json"
    xmlhttp.setRequestHeader BonitaSession, JS
    URL = "www.google.it" 'https://radar-test.celadagroup.com/wp-admin/admin-ajax.php?lang=it&action=b4y_crm_ws_get_pdf_quotation_v002&quotationId=2a0f45bb-dda3-49e6-ac67-08d7f110e6d0&rnd=nTc8UHUWr6YnyQdaRobmzU34wZongTuD
    json = "{  'quotationEntityInput' : {    'QuotationId' : 'QUO-0001-2020',    'CustomerId' : '1003713',    'CustomerName' : 'LUXOTTICA S.R.L.',    'HasSpecialItem' : true,    'GrossAmount' : 1000000,    'NetAmount' : 975000,    'Discount' : 25000,    'SalesmanId' : '201244',    'SalesmanName' : 'MURADOR DAVIDE',    'Version' : '2000647'  , 'URLQuotation' : '" + URL + "' }}"
    json = Replace(json, "'", Chr(34))
    xmlhttp.send (json)
    DoEvents
    result = xmlhttp.responseText
    MsgBox (result)
End Sub


Public Sub httpclient()
    Dim xmlhttp As New MSXML2.xmlhttp, myurl As String
    myurl = urlServerPath + "/loginservice"
    xmlhttp.Open "POST", myurl, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send "username=alberto.bernasconi@celadagroup.com&redirect=false&password=bpm"
    strCookie = xmlhttp.getAllResponseHeaders()
    jsessionidCookie = GetJsessionIdCookie(strCookie)
'    MsgBox (xmlhttp.responseText)
    myHeader = xmlhttp.getResponseHeader("X-Bonita-API-Token")
    MsgBox (jsessionidCookie)
End Sub

Public Function GetLoginSession()
    Dim xmlhttp As New MSXML2.xmlhttp, myurl As String
    myurl = urlServerPath + "/loginservice"
    xmlhttp.Open "POST", myurl, False
    xmlhttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    xmlhttp.send "username=alberto.bernasconi&redirect=false&password=bpm"
    strCookie = xmlhttp.getAllResponseHeaders()
    SessionId = Split(strCookie, Chr(13))(2)
    jsessionidCookie = Split(Mid(SessionId, InStr(SessionId, BonitaSession) + Len(BonitaSession) + 1), ";")(0)
    GetLoginSession = jsessionidCookie
'    Set xmlhttp = Null
End Function

Function GetProcessId(ProcessName)
    Dim xmlhttp As New MSXML2.xmlhttp, myurl As String
    myurl = urlServerPath + "/API/bpm/process?f=name=" + ProcessName
    xmlhttp.Open "GET", myurl, False
    xmlhttp.setRequestHeader "Content-type", "application/json"
    xmlhttp.send
    result = xmlhttp.responseText
    GetProcessId = getKeyValue(result, "id")
   
End Function

Function getKeyValue(result, Search)
    If Left(result, 2) = "{[" Then result = Left(Mid(result, 3), Len(result) - 4)
    varLines = Split(result, ",")
    ReDim ResultJson(0) As JsonData
    For i = 0 To UBound(varLines)
        If (varLines(i) <> "") Then
            ReDim Preserve ResultJson(i)
            ResultJson(i).KeyName = Split(Replace(varLines(i), Chr(34), ""), ":")(0)
            ResultJson(i).KeyValue = Split(Replace(varLines(i), Chr(34), ""), ":")(1)
        End If
    Next
    For i = 0 To UBound(ResultJson)
        If ResultJson(i).KeyName = Search Then
            getKeyValue = ResultJson(i).KeyValue
            Exit Function
        End If
    Next i
End Function
 

Here is a snippet of a Java client using HTTP Client API:

import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors;

import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HTTPClientExample {

private static final String API_TOKEN_HEADER = "X-Bonita-API-Token";

public static void main(String[] args) {
    HttpClientContext context = HttpClientContext.create();
    context.setCookieStore(new BasicCookieStore());
    CloseableHttpClient client =   HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.DEFAULT).build())
            .setDefaultCookieStore(context.getCookieStore()).build();
    
    HttpHost host = HttpHost.create("http://localhost:8080");
    try {
        HttpPost loginRequest = new HttpPost("/bonita/loginservice");
        Map<String, String> body = new HashMap<>();
        body.put("username", "walter.bates");
        body.put("password", "bpm");
        List<NameValuePair> parameters = body.entrySet()
                .stream()
                .map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
        loginRequest.setEntity(new UrlEncodedFormEntity(parameters));
        loginRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");
        client.execute(host, loginRequest);
        
        HttpGet bdmRequest = new HttpGet("/bonita/API/bdm/businessData/com.company.model.Request/1");
        bdmRequest.addHeader("Content-Type", "application/json");
        bdmRequest.addHeader(API_TOKEN_HEADER,getAPITokenFromCookie(context));
        CloseableHttpResponse response = client.execute(host, bdmRequest);
        System.out.println(EntityUtils.toString(response.getEntity()));
    } catch ( IOException e) {
        e.printStackTrace();
    }
}

private static String getAPITokenFromCookie(HttpClientContext context) {
    final CookieStore cookieStore = context.getCookieStore();
    return cookieStore.getCookies().stream().filter( c -> Objects.equals(c.getName(), API_TOKEN_HEADER))
            .map(Cookie::getValue)
            .findFirst()
            .orElseThrow(() -> new RuntimeException(String.format("%s not found",API_TOKEN_HEADER)));
}

}

HTH
Romain

mistake

What request are you doing when using the /bonita/loginservice ?

Note that the Content-Type header of the request must be application/x-www-form-urlencoded. Check the documentation for all the details.

HTH
Romain

I'm currently in need to retrieve a bonita BDM data from an external site and the URL is

http://localhost:8080/bonita/API/bdm/businessData/com.company.MyModel/6 but as per to the documentation I first need to obtain X-Bonita-API-Token by logging into the login service ( /bonita/loginservice) programmatically with HttpURLConnection (java). All the steps in the documentation are followed, still I'm not getting  X-Bonita-API-Token cookie value for me to proceed with other APIs ahead.