API (Java) for message throw event

Hi. I experienced (with success) throw and catch of BPMN message event in Camunda 7 by means of the Java API. Testing Camunda 8.8 (self-managed), a job worker for a throw message event is required. I get the control at runtime but I don’t how I may concretely send the message in the job worker body?

@io.camunda.client.annotation.JobWorker(type = "i_want_to_send_a_message")
    public void run_jw(final io.camunda.client.api.worker.JobClient client, final io.camunda.client.api.response.ActivatedJob job) {

From client and job parameters, there is no dedicated methods? In Camunda 7, I got an execution object (DelegateExecution mechanism) to deal with correlation stuff and effectively send something… I feel I missed something somewhere, but wasn’t able to find trivial/simple code snippets on the Web. BTW, I migrate my C7 models to C8 and observed that throw message events in my models kept “headers”. Is it the way? Thanks for any help.

Here is a handler (Camunda 8.8) I built to try out this same concept. It may be helpful to you.

public class SendMessageTaskServiceHandler implements JobHandler {
	
	private CamundaClient cclient;
	
	public SendMessageTaskServiceHandler(CamundaClient cclient) {
		this.cclient = cclient;
	}

	@Override
	public void handle(JobClient client, ActivatedJob job) throws Exception {
		
		final Map<String, Object> inputVariables = job.getVariablesAsMap();
		
		if(cclient == null) {
			System.out.println("Camunda Client is null");
			throw new NullPointerException();
		}
		
		String correlationKey = (String) inputVariables.get("CorrelationKey");
		String messageName = (String) inputVariables.get("MessageName");
						
		if (correlationKey == null) {
			
			cclient.newPublishMessageCommand().messageName(messageName).withoutCorrelationKey().send().join();
			
		} else {
			
			cclient.newPublishMessageCommand().messageName(messageName).correlationKey(correlationKey).send().join();
			
		}
		
		client.newCompleteCommand(job.getKey()).send().join();
		
	}
}

To use the handler, something like this:

CamundaClient client = CamundaClient
		.newClientBuilder()
		.grpcAddress(URI.create(ZEEBE_GRPC_ADDRESS))
		.restAddress(URI.create(ZEEBE_REST_ADDRESS))
		.preferRestOverGrpc(false)
		.build()) {
											
JobWorker sendMessageTaskWorker = client.newWorker().jobType("sendMessageTask").handler(new SendMessageTaskServiceHandler(client)).open();

“sendMessageTask” is the Job you configure to process your message throw in your model.

Note: this is a code for test only :slight_smile:

1 Like

Hello @claudio_rio ,

thank you for this code snippet. This is really helpful.

I would like to add that if the Spring Boot starter is used, the CamundaClient is already available as a bean, so there is no need to create one in that case.

Jonathan

1 Like

Thank you Claudio, but it doesn’t respond to my problem at all. I don’t have an access to newPublishMessageCommand() from the client parameter.

.
What is also “strange” for me in your code is the fact that you get the message features (eg, "MessageName") from the process variables, ie, job.getVariablesAsMap(). Why not, but I believed that process variables are business variables only? Moreover, I don’t API access from the job paramater either:

Sum up: I’m probably missing something but still need help!

@claudio_rio: your solution works well (just tested), but, to be honnest, C8.8 API is a bit “inelegant” if there is no other more “tailored” solution? Indeed, I must push the message features (as inputs in the model) to get them in the code (as your code perfectly shows this) . So, many thanks again Claudio…
@Jonathan: I suppose that the CamundaClient object may be injected by Spring? Appreciate if you may tell me what Spring annotation allows such an injection? Thanks in advance

Hello @Bab64 ,

there is nothing required, just inject the bean to your bean.

Jonathan

For any forthcoming reader, based on Claudio impl. and Jonathan remark, the idea is just to push message TECHNICAL features through Headers field in model instead of Inputs field in model that, in my opinion, must be reserved for BPMN business data. Hybrid solution is to push content as input since it is actual business data.

@org.springframework.stereotype.Component
public class MY_THROWN_MESSAGE implements io.camunda.client.api.worker.JobHandler {

    @org.springframework.beans.factory.annotation.Autowired
    private io.camunda.client.CamundaClient _c;

    @io.camunda.client.annotation.JobWorker(type = "MY_THROWN_MESSAGE")
    @Override
    public void handle(final io.camunda.client.api.worker.JobClient client, final io.camunda.client.api.response.ActivatedJob job) {
        String messageName = job.getCustomHeaders().get("messageName");
        String correlationKey = job.getCustomHeaders().get("correlationKey");
        String content = job.getCustomHeaders().get("content");
        System.out.println(messageName + " " + correlationKey + " " + content);
        _c.newPublishMessageCommand()
                .messageName(messageName)
                .correlationKey(correlationKey)
                .variable("content", content).send().join();
    }
}

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.