Activiti User interface Spring App integration - java

I have the following Activiti 6 applications running from the official provided .WAR files. Have succesfully deployed these to my localhost
activiti-app - http://localhost:8080/activiti-admin/
activiti-admin - http://localhost:8080/activiti-admin/
activiti-rest - http://localhost:8080/activiti-rest/
So far I can use activiti-app to produce BPMN files and start up applications using the interface. So far so good.
However what im looking to do is write my own Spring Apps but be able to view them running using the activiti UI apps.
So looking at the baeldung-activiti tutorial. You can start the application.
#GetMapping("/start-process")
public String startProcess() {
runtimeService.startProcessInstanceByKey("my-process");
return "Process started. Number of currently running process instances = " + runtimeService.createProcessInstanceQuery().count();
}
The above returns an incremented value everytime the endpoint is hit.
My questions is this.
Using the activiti tools (running on localhost:8008) how can view the processes. How do I link the standalone java application . (running on localhost:8081) with the Activiti ui interfaces?

That's pretty easy if you have the activity-rest configured and running. The REST API is documented here.
So you just need to do a Web Service call to the correct API endpoint. For example to list all of the processes you need to do a GET request to the repository/process-definitions endpoint.
Note: The Rest API uses Basic Auth.
public void loadProcesses(){
// the username and password to access the rest API (same as for UI)
String plainCreds = "username:p#ssword";
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = Base64.getEncoder().encode(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<>(headers);
ResponseEntity<String> responseAsJson = restTemplate.exchange("http://localhost:8080/activiti-rest/repository/process-definitions", HttpMethod.GET, request, String.class);
}
The response for the following API call will be JSON like
{
"data": [
{
"id" : "oneTaskProcess:1:4",
"url" : "http://localhost:8182/repository/process-definitions/oneTaskProcess%3A1%3A4",
"version" : 1,
"key" : "oneTaskProcess",
"category" : "Examples",
"suspended" : false,
"name" : "The One Task Process",
"description" : "This is a process for testing purposes",
"deploymentId" : "2",
"deploymentUrl" : "http://localhost:8081/repository/deployments/2",
"graphicalNotationDefined" : true,
"resource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.xml",
"diagramResource" : "http://localhost:8182/repository/deployments/2/resources/testProcess.png",
"startFormDefined" : false
}
],
"total": 1,
"start": 0,
"sort": "name",
"order": "asc",
"size": 1
}

Related

Add new operations to existing jsonpatch file

I'm working on a test suite for some Java code that uses jsonpatch to modify db entries. What I am trying to do is have a template jsonpatch request saved down as a file that individual unit tests could read from, modify some operations, and then call the patch directly.
The rough structure is as follows:
jsonpatch template:
"jsonPatch": [
{
"op": "replace",
"path": "/username",
"value": "johnDoe"
},
{
"op": "replace",
"path": "/number",
"value": 123
}
]
java code:
// Import Template
JsonPatch request;
InputStream is = TestRestTemplate.class.getResourceAsStream("/PatchRequest.json");
request = objectMapper.readValue(is, JsonPatch.class)
// Modify Operations (not working)
Random r = new Random();
int newNumber = r.nextInt(100);
((ObjectNode) request).put("/number", newNumber); // this doesn't even compile due to conversion issues
// Send patch
thingThatTouchesDB.patchDocument(request)
// Validate Results
int finalNumber = [get field from DB]
assertEquals(newNumber, finalNumber);
When I comment out the modify operation section everything works so I'm not having issues with importing or sending the patch. My struggle is with updating the template's operations to fit. The paths are the same across tests but I need to try with different values each time since we're using a persistent database for testing.
Is there a way to modify the value of an existing jsonpatch operation like I'm trying above? Failing that, can I add new operations to the existing jsonpatch?
After a lot of trial and error I got it to work by modifying the inputstream itself instead of the jsonpatch object.
I added some targets to the json template and did stream replacement on a copy of the inputstream to force in my desired values before converting it all into the final jsonpatch.
new template:
"jsonPatch": [
{
"op": "replace",
"path": "/username",
"value": "$username$"
},
{
"op": "replace",
"path": "/number",
"value": "$number$"
}
]
new code:
// Import Template
JsonPatch request;
InputStream is = TestRestTemplate.class.getResourceAsStream("/PatchRequest.json");
byte[] bytes = FileCopyUtils.copyToByteArray(is);
String requestStr= new String(bytes);
// Modify Operations
Random r = new Random();
int newNumber = r.nextInt(100);
requestStr= requestStr.replaceAll("\"\\$number\\$\"", String.valueOf(newNumber));
requestStr= requestStr.replaceAll("\\$username\\$", "NewName");
// Finalize Request
request = objectMapper.readValue(requestStr, JsonPatch.class)
Getting the number value to work was a bit tricky since everything is strings, but I was able to crack it by having the replace operation get rid of its quotes which causes it to get picked up as a number by the jsonpatch.

Ripple Transaction from one local wallet to exchange wallet(example : crex24) gives error code tecDST_TAG_NEEDED using java

i installed ripple wallet on my local server. i created one wallet and activate it with 20 XRP.
Now when i send coin from my active account to account(of crex24.com) then it gives tecDST_TAG_NEEDED error code
Ripple : http://127.0.0.1:5005
Code (using submit method):
RestTemplate template = new RestTemplate();
Map<String,Object> mainMap = new HashMap<>();
mainMap.put("secret", "sxxxxxxxxxxx");
mainMap.put("Fee", "1000"); // in drops
Map<String,String> subMap = new HashMap<>();
subMap.put("Account", "raxxxxxxxxx"); // amount will be deducted from this account
subMap.put("Amount", "1000000"); // in drops
subMap.put("Destination", "rdxxxxxxxxx"); // receiver address
subMap.put("TransactionType", "Payment"); // since we are making a payment request
mainMap.put("tx_json", subMap);
JSONObject json = new JSONObject();
json.put("method", "submit");
json.put("params", new JSONArray(mainMap));
String requestData = json.toString();
System.out.println(requestData);
String response = template.postForObject("http://127.0.0.1:5005", requestData,String.class);
System.out.println(response);
Error
{
"status": 200,
"message": "Transaction achieved successfully.",
"data": {
"result": {
"deprecated": "Signing support in the 'submit' command has been deprecated and will be removed in a future version of the server. Please migrate to a standalone signing tool.",
"engine_result": "tecDST_TAG_NEEDED",
"engine_result_code": 143,
"engine_result_message": "A destination tag is required.",
"status": "success",
"tx_blob": "120000228000000024000000096140000000000F424068400000000000000A7321036CB83FF75DAxxxxxxxxxxxxxxxxxx",
"tx_json": {
"Account": "raxxxxxxxxx",
"Amount": "1000000",
"Destination": "rdxxxxxxxxx",
"Fee": "10",
"Flags": 214482148,
"Sequence": 9,
"SigningPubKey": "036Cxxxxxxxxxxxxxxx6",
"TransactionType": "Payment",
"TxnSignature": "txxxxxxxxx",
"hash": "hxxxxxxxxxx"
}
}
},
"path": "/api/ripple_wallet/makeTransaction"
}
Your account on crex24.com requires a destination tag.
XRPL uses account model similar to ETH. Unlike BTC which uses an UTXO model.
The reason some exchanges require destination tag is that you might be sharing that address with some other person on the exchange. e.g:
Person1's deposit address is: Addr1
Person2's deposit address is also Addr1
Somebody deposits 100XRP to Addr1.
In the case above the exchange wouldn't be able to differentiate if it was Person1's or Person2's.
So the XRPL introduced destination tag which would look something similar to this:
Exchange sets tfRequireDestTag flag of the Addr1 to true using accountSet transaction
Person1's deposit address is: Addr1:1234
Person2's deposit address is also Addr1:1235
Somebody deposits 100XRP to Addr1. XRPL refuses due to tfRequireDestTag being set to true /This is your case/
Someone sends 50XRP to Addr1:1234. <-- this one succeeds!

Receive JSON data from a webservice using REST API

I need to receive JSON data from this Api http://countryapi.gear.host/v1/Country/getCountries using REST API. I need to receive NativeName and Region for the specific country.
My main problem is how to send request for the specific country (for example I print Name Australia) and get the response for NativeName and Region - Australia, Oceania (it should be String).
I have such classes:
public class Client {
public static void main(String[] args) throws ClientProtocolException, IOException {
HttpClient clientGetEntity = new DefaultHttpClient();
HttpGet request = new HttpGet("http://countryapi.gear.host/v1/Country/getCountries?pName=Australia");
request.addHeader("accept", "application/json");
HttpResponse responseGetEntity = clientGetEntity.execute(request);
//String json =EntityUtils.toString((HttpEntity) responseGetEntity);
System.out.println("Request : " + request.toString());
System.out.println("Response : " + responseGetEntity.toString());
}
}
EDITS
As regards getting the specific country's name, you need to make a get request with the country name such as:
http://countryapi.gear.host/v1/Country/getCountries?pName=Australia
The response from this request:
{
"IsSuccess": true,
"UserMessage": null,
"TechnicalMessage": null,
"TotalCount": 1,
"Response": [
{
"Name": "Australia",
"Alpha2Code": "AU",
"Alpha3Code": "AUS",
"NativeName": "Australia",
"Region": "Oceania",
"SubRegion": "Australia and New Zealand",
"Latitude": "-27",
"Longitude": "133",
"Area": 7692024,
"NumericCode": 36,
"NativeLanguage": "eng",
"CurrencyCode": "AUD",
"CurrencyName": "Australian dollar",
"CurrencySymbol": "$",
"Flag": "https://api.backendless.com/2F26DFBF-433C-51CC-FF56-830CEA93BF00/473FB5A9-D20E-8D3E-FF01-E93D9D780A00/files/CountryFlags/aus.svg",
"FlagPng": "https://api.backendless.com/2F26DFBF-433C-51CC-FF56-830CEA93BF00/473FB5A9-D20E-8D3E-FF01-E93D9D780A00/files/CountryFlagsPng/aus.png"
}
]
}
You can access NativeName and region by:
data.Response[0].NativeName and data.Response[0].Region respectively.
Since the data returned from the API is always a JSON string, dont forget to parse the string before use.
----------------------------------------
I am not a java developer but I have dealt with a lot of JSON data, Also C# and TypeScript projects.
First, you should take a look at this line:
request.addHeader("accept", "application/fson");
Am afraid this is not a valid JSON request header and if we where to start debugging your code, it would be difficult to pinpoint where the problem lies if the basis of the whole request is faulty. Please correct to:
request.addHeader("accept", "application/json"); and try again, if you have the same result, we can continue debugging from there.

Create sheet and update data with one request

I want to implement Google sheets api request with one api call.
I managed to implement this code:
List<Request> requests = new ArrayList<>();
List<CellData> values = new ArrayList<>();
values.add(new CellData()
.setUserEnteredValue(new ExtendedValue()
.setStringValue("Hello World!")));
requests.add(new Request().setAddSheet(new AddSheetRequest()
.setProperties(new SheetProperties()
.setTitle("scstc")))
.setUpdateCells(new UpdateCellsRequest()
.setStart(new GridCoordinate()
.setSheetId(0)
.setRowIndex(0)
.setColumnIndex(0))
.setRows(Arrays.asList(
new RowData().setValues(values)))
.setFields("userEnteredValue,userEnteredFormat.backgroundColor"))
);
BatchUpdateSpreadsheetRequest body = new BatchUpdateSpreadsheetRequest().setRequests(requests);
BatchUpdateSpreadsheetResponse response = service.spreadsheets().batchUpdate(spreadsheetId, body).execute();
But I get error:
400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid value at 'requests[0]' (oneof), oneof field 'kind' is already set. Cannot set 'updateCells'",
"reason" : "badRequest"
} ],
"message" : "Invalid value at 'requests[0]' (oneof), oneof field 'kind' is already set. Cannot set 'updateCells'",
"status" : "INVALID_ARGUMENT"
}
at com.google.sheet.impl.GoogleSheetBasicTest1_____1.hello(GoogleSheetBasicTest1_____1.java:133)
Do you how how I can fix this issue?
Each Request object is intended to have just a single value set within it. You are setting two values:
requests.add(new Request()
.setAddSheet(...)
.setUpdateCells(...));
Instead of doing the above, you need to use two request objects:
requests.add(new Request().setAddSheet(...));
requests.add(new Request().setUpdateCells(...));
#Sam is correct, however if you are using the JSON representation make sure that your formatting is set correctly in the dictionaries you are making. I found the following formating helpfull, found in the Google Devs' Formatting cells with the Google Sheets API
blogpost:
reqs = {'requests': [
# frozen row 1, request #1
{'updateSheetProperties': {
'properties': {'gridProperties': {'frozenRowCount': 1}},
'fields': 'gridProperties.frozenRowCount',
}},
# embolden row 1, request #2
{'repeatCell': {
'range': {'endRowIndex': 1},
'cell': {'userEnteredFormat': {'textFormat': {'bold': True}}},
'fields': 'userEnteredFormat.textFormat.bold',
}},
]}
*I am new to adding information to this site. Sorry if this is not he best way to add the information but I just want to help out. I had this problem while using python instead of java and found that it was a simple error of were the brackets where.

trying to build a Response object for a Java RESTful service

I am trying to build a Response object with a information I am getting back from a database. The information I am getting back is in a Change object:
The change.getDocument() coming back is:
{"testSolution":false,"solutionId":333,"clientId":4018593,"firewall":false,"pod":"pod3.dmy3","networkPolicy":{"speed":"1","subnets":{"nat":{"vlan":3004,"cidr":["110.168.0.0/24"]},"private":{"vlan":3004,"cidr":["15.10.1.128/25"]}}}}
So I am creating a Response like this:
return Response.status(422).location(location).entity(changeRequest).build();
In the unit test I do this:
String responseJson = response.readEntity(String.class);
System.out.println("The response is: " + responseJson);
For testing, but I get this result:
The response is: {"object_id" : 333,"object_type" : "class com.entities.Solution", "operation" : "", "revision" : 0, "remote_user" : "", "remote_host" : "", "created" : "", "published" : "", "comment" : "HTTP Status Code 422", "error" : "HTTP Status Code 422, there is a pending change request for this Solution. Replying with pending ChangeRequest", "document" : {} }
Everything is as expected, but the document node contains no information. Am I building the Response object correctly?
Try to return it in this way:
Response.status(Status.OK).type(MediaType.APPLICATION_JSON)
.entity(changeRequest).build();

Categories