Prepare JSON object in JAVA client to post into Camunda DMN REST API

Hi,
I am writing a java client that invoke the camunda DMN REST and preparing the JSON object as for below link format by using below piece of code.but its not working as expected.

https://docs.camunda.org/manual/7.4/reference/rest/decision-definition/post-evaluate/

ObjectValue customerDataValue = Variables.objectValue(request)
.serializationDataFormat(Variables.SerializationDataFormats.JAVA)
.create();

Here the request is Map object which contains values key and value format.

Result:
JSON: ObjectValue [value={city=NY, name=Mars, age=32}, isDeserialized=true, serializationDataFormat=application/json, objectTypeName=null, serializedValue=null, isTransient=false]

But camunda Rest API expected the JSON format as below.

{
  "variables" : {
    "amount" : { "value" : 600, "type" : "Double" },
    "invoiceCategory" : { "value" : "Misc", "type" : "String" }
  }
}

Kindly help to provide the sample java client to prepare the JSON object as like above.

Thanks
Vemula

Create a classes like this:

 public class StringType {
    String type = "String";
     String value;
 }

public class DoubleType {
   String type = "Double";
   double value;
}

public class Variables{
  DoubleType amount;
  StringType invoiceCategory;
}

public class Payload{
  Variables variables;
}

Use Lombok dependency, if you want to autogenerate getters & setters

Hi Dear,

May i know how does it help to prepare the input JSON object for camunda Rest API?.

Please possible can we get the sample client java program?

After setting all the values to those objects, finally convert it to json string using Jackson library,

objectMapper.writeValueAsString(payload);

payload is instance if this class:

public class Payload{
  Variables variables;
}

And annotate these classes with below annotation at class level to handle null/empty values.

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(content = Include.NON_NULL, value = Include.NON_EMPTY)

Thanks,

But my request MAP having multiple values and i need to pass completed object to camunda to evaluate the decision.

As for above your code snippet example it will allow only one value convert to JSON object.

It will convert all the objects to JSON string. You can add any number of variables of different type to Variables Object as mentioned in above post.

If you are using Map , then try storing objects as ,

Map<“SomeVariable”,“ObjectValue”> variables;

Dear ,

Below is the REST client to invoke the Camunda DMN API.

@RequestMapping(value = “/testRest” , method = RequestMethod.POST)
public String testRest(@RequestBody Map<String, Object> request) {
try {
System.out.println( "request "+request);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);

		ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
		String requestJson = ow.writeValueAsString(request);

		HttpEntity<String> entity = new HttpEntity<>(requestJson, headers);
		System.out.println( "entity  "+entity);
		final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
		requestFactory.setTaskExecutor(new SimpleAsyncTaskExecutor());
		requestFactory.setConnectTimeout(30000);
		requestFactory.setReadTimeout(30000);

		Class<Object> objectClass = Object.class;
		final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
		asyncRestTemplate.setAsyncRequestFactory(requestFactory);
		ListenableFuture<ResponseEntity<Object>> response = asyncRestTemplate.exchange("http://localhost:8080/rest/engine/default/decision-definition/key/declaration/evaluate", HttpMethod.POST, entity, objectClass);
		System.out.println( "response  "+response);
		return response.toString();
	} catch (JsonProcessingException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return null;
}

and input from Post man is below.

{
“regime”: “import”,
“declarationType”: “import”,
“partyType”: “commercial”,
“totalcharge”: “1000”,
“itemRequestDTOs”: [
{
“hscode”:“10101010”,
“description”:“test1”,
“hscodeCOO” :“UAE”
},
{
“hscode”:“20202020”,
“description”:“test2”,
“hscodeCOO” :“IND”
}
],
“invoiceDTOs”: [
{
“invoiceNumber”:“12345”,
“invoiceType”:“CIP”
},
{
“invoiceNumber”:“123456”,
“invoiceType”:“CIF”
}
]

}

But i m getting below Error,

Caused by: org.camunda.bpm.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier ‘regime’
at org.camunda.bpm.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:83)
at org.camunda.bpm.engine.impl.juel.AstEval.eval(AstEval.java:50)
at org.camunda.bpm.engine.impl.juel.AstNode.getValue(AstNode.java:26)
at org.camunda.bpm.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)
at org.camunda.bpm.engine.impl.dmn.el.ProcessEngineElExpression.getValue(ProcessEngineElExpression.java:46)
at org.camunda.bpm.dmn.engine.impl.evaluation.ExpressionEvaluationHandler.evaluateElExpression(ExpressionEvaluationHandler.java:120)
… 97 common frames omitted

But in the DMN file having this property.

Thanks
Vemula

“regime” this variable where are you using it? It seems the variable not persisted in database.

Can you upload your model?

declaration.dmn (4.4 KB)

Please find the attached file.

Variable is missing.

image

For all the fields update “Input Variable” cell, which in turn will create xml element as below:

<input id="input1" label="regime" camunda:inputVariable="regime">

It should be configured like below:

image

Dear,

Even i have tried this also and not working.Its because of JSON format issue.

Basically we need to prepare the JSON object as like below by using from above input Map<String,Object> object.

{
“variables” : {
“regime”: {“value” :“import”},
“declarationType”:{“value”: “import”},
“partyType”: {“value”:“commercial”},
“declarationLines”:{“value”: [
{
“hscode”:“10101010”,
“description”:“test1”,
“hscodeCOO” :“UAE”
},
{
“hscode”:“20202020”,
“description”:“test2”,
“hscodeCOO” :“IND”
}
]},
“declarationInvoiceDocuments”:{“value”: [
{
“invoiceNumber”:“12345”,
“invoiceType”:“CIP”
},
{
“invoiceNumber”:“123456”,
“invoiceType”:“CIF”
}
]}
}
}

Can you help to provide the sample java client to prepare the Above format JSON?

Thanks
Vemula

Hey,

you might want to write your own java classes to represent the given JSON. Using a top-down approach, you can then start with the outer object and then dig deeper following the nested objects.

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Variables {

    @SerializedName("regime")
    @Expose
    private Regime regime;
    @SerializedName("declarationType")
    @Expose
    private DeclarationType declarationType;
    @SerializedName("partyType")
    @Expose
    private PartyType partyType;
    @SerializedName("declarationLines")
    @Expose
    private DeclarationLines declarationLines;
    @SerializedName("declarationInvoiceDocuments")
    @Expose
    private DeclarationInvoiceDocuments declarationInvoiceDocuments;

    public Regime getRegime() {
        return regime;
    }

    public void setRegime(Regime regime) {
        this.regime = regime;
    }

    public DeclarationType getDeclarationType() {
        return declarationType;
    }

    public void setDeclarationType(DeclarationType declarationType) {
        this.declarationType = declarationType;
    }

    public PartyType getPartyType() {
        return partyType;
    }

    public void setPartyType(PartyType partyType) {
        this.partyType = partyType;
    }

    public DeclarationLines getDeclarationLines() {
        return declarationLines;
    }

    public void setDeclarationLines(DeclarationLines declarationLines) {
        this.declarationLines = declarationLines;
    }

    public DeclarationInvoiceDocuments getDeclarationInvoiceDocuments() {
        return declarationInvoiceDocuments;
    }

    public void setDeclarationInvoiceDocuments(DeclarationInvoiceDocuments declarationInvoiceDocuments) {
        this.declarationInvoiceDocuments = declarationInvoiceDocuments;
    }

}

After that you you go one step further and create classes to resolve your custom objects, e.g. declarationInvoiceDocuments.

import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class DeclarationInvoiceDocuments {

    @SerializedName("value")
    @Expose
    private List<Value_> value = null;

    public List<Value_> getValue() {
        return value;
    }

    public void setValue(List<Value_> value) {
        this.value = value;
    }

}

As Value_ again is a custom object (you might wanna rename your objects, so you don’t have to use _), this has to be created as well to hold your needed fields.

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Value_ {

    @SerializedName("invoiceNumber")
    @Expose
    private String invoiceNumber;
    @SerializedName("invoiceType")
    @Expose
    private String invoiceType;

    public String getInvoiceNumber() {
        return invoiceNumber;
    }

    public void setInvoiceNumber(String invoiceNumber) {
        this.invoiceNumber = invoiceNumber;
    }

    public String getInvoiceType() {
        return invoiceType;
    }

    public void setInvoiceType(String invoiceType) {
        this.invoiceType = invoiceType;
    }

}

This now has to be done for all your custom objects in order to be serialized properly.
Hope this helps :slight_smile:

Cheers,
Sascha

Dear ,

I have tried as for above design ,it will print below output and getting the same exception.

{
“regime”: “import”,
“declarationType”: “import”,
“partyType”: “commercial”,
“totalcharge”: “1000”,
“itemRequestDTOs”: [
{
“hscode”:“10101010”,
“description”:“test1”,
“hscodeCOO” :“UAE”
},
{
“hscode”:“20202020”,
“description”:“test2”,
“hscodeCOO” :“IND”
}
],
“invoiceDTOs”: [
{
“invoiceNumber”:“12345”,
“invoiceType”:“CIP”
},
{
“invoiceNumber”:“123456”,
“invoiceType”:“CIF”
}
]

}

Dear,

Basically i need sample example to prepare the JSON format by using the above Map variables as below.Then only camunda standalone accept the JSON format to run the evaluate of Decision

{
“variables” : {
“regime”: {“value” :“import”},
“declarationType”:{“value”: “import”},
“partyType”: {“value”:“commercial”},
“declarationLines”:{“value”: [
{
“hscode”:“10101010”,
“description”:“test1”,
“hscodeCOO” :“UAE”
},
{
“hscode”:“20202020”,
“description”:“test2”,
“hscodeCOO” :“IND”
}
]},
“declarationInvoiceDocuments”:{“value”: [
{
“invoiceNumber”:“12345”,
“invoiceType”:“CIP”
},
{
“invoiceNumber”:“123456”,
“invoiceType”:“CIF”
}
]}
}
}

Thanks
Vemula

Hi Vemula
I’m new to using Camunda in this case my first question is: Can you send a complex object, as already mentioned, that Camunda DMN will solve?

I used this way https://docs.camunda.org/get-started/dmn11/deploy/

Hi @mrclalves,

yes, you can. Reference the attributes with dot notation the input expression of the DMN table.

Hope this helps, Ingo

1 Like

Hi Vemula,

When sending a complex object like yours, I send the object as a single variable and manipulate the object within that DMN as in this example. diagram_2.dmn (7.4 KB)

In this case the sending will go like this:

Hi Ingo_Richtsmeier

Thanks for knowing.
You can give us a snipped for this case?

Thanks
Marcelo