Java and JavaScript Communication

One of the main features of the Equo SDK is its capability to create an application combining web UIs with the Java programming environment. To do this, we need a bidirectional communication between Java and JavaScript code.

To handle the communication between the frontend and the backend we provide the comm API. This API is based on events: you register an event listener somewhere (JavaScript or Java code) and then you can call it from somewhere else. It’s that easy.

Below we will show some simple use cases, but you can refer to Communication js API and Communication Java API to read the full APIs documentation.

Handling an Event in Java

Any method defined in this class will be added as an event listener, the methods may declare 0 or 1 parameters.

Example:

import org.osgi.service.component.annotations.Component;

import com.equo.comm.api.actions.IActionHandler;

@Component
public class MyEventManager implements IActionHandler {

	public void printPayload(String payload) {
		System.out.println(payload);
	}

	...
}

By default, the event name will be the method name. This can be changed by adding the @EventName annotation to the method with the desired event name as the value.

As described above, you can have any number of action handlers defined in this class.

Example:

import org.osgi.service.component.annotations.Component;

import com.equo.comm.api.annotations.EventName;
import com.equo.comm.api.actions.IActionHandler;

@Component
public class MyEventName implements IActionHandler {

	@EventName("firstCustomEvent")
	public String myFirstEvent(String payload) {
		System.out.println("First event: " + payload);
		return payload;
	}

	@EventName("secondCustomEvent")
	public SomeObject mySecondEvent(String payload) {
		System.out.println("Second event: " + payload);
		return new SomeObject(payload);
	}

	public void myThirdEvent(String payload) {
		System.out.println("Third event: " + payload);
	}

	...
}

You can also get an ICommService reference and register handlers on the fly using the on methods.

Example:

import com.equo.comm.api.ICommService;

public class SomeCustomClass {
	private ICommService commService = ICommService.findServiceReference();


	...

	void someFunction(){
		commService.on("myeventname", (payload) -> {
			return payload + "some more data";
		}));
	}

	...
}

Triggering an Event from Java

To send an event you can use ICommSendService or ICommService. Get a reference of either service. Then, send an event.

Example:

import com.equo.comm.api.ICommService;

public class SomeCustomClass {
	private ICommService commService = ICommService.findServiceReference();

	...

	void someFunction(){
		commService.send("myeventname", "Message from Java code");
	}

	...
}

You can also send an event that expects a response from JavaScript, in this case the API will return a Future that will be completed with the serialized response from JavaScript.

Example:

import com.equo.comm.api.ICommService;

public class SomeCustomClass {
	private ICommService commService = ICommService.findServiceReference();

	...

	void someFunction(){
		Future<SomePojo> fResponse = commService.send("some_event_with_response",
				SomePojo.class);

		...

		if (fResponse.isDone()) {
			SomePojo response = fResponse.get();
			System.out.println(response);
		}
	}

	...
}

Send Binary Payloads from Java

It is also possible to send binary payloads as an array of bytes with the same commService reference seen above.

Example:

byte[] bytes = [84, 101, 115, 116, 32, 67, 111, 100, 101];
void someFunction(){
	commService.send("myEventName", bytes);
}

Handling an Event in JavaScript

The JavaScript API is the same as in java, you can use on to listen for an event:

EquoCommService.on("myeventname", function(payload) {
	console.log("Received payload: " + payload);
});

Triggering an Event from JavaScript

Once you have some action handlers registered, you can call them from a JS script using the Equo Communication API like this:

EquoCommService.send("myThirdEvent", "String printed from JavaScript");

send returns a Promise, when the appropriate action handler is called in Java, the Promise will be resolved with its return value.

Send Binary Payload from JavaScript

It is also possible to send binary payloads as an array of bytes with the same EquoCommService reference seen above.

Example:

byte[] bytes = [84, 101, 115, 116, 32, 67, 111, 100, 101];
void someFunction(){
	EquoCommService.send("myEventName", bytes);
}
In the Java side, you will get an array like [84.0,101.0,115.0,116.0,32.0,67.0,111.0,100.0,101.0].

Handling the Case when there is no Handler for the Event

When an event is sent with the send method and there is no handler for it, an exception will be thrown with a 255 error code and an error message like the following:

An event handler does not exist for the user event 'name_of_the_event'

You can register handlers for specific events using the on method.

Example: In the following example, we want to send an event using the send method from JavaScript, but there is no handler (on method) on the the Java side. Detecting that there is no handler for this event can be done through the Promise catch method.

void someFunction(){
	EquoCommService.send("myEventName", payload)
		.then(msg => /* should not enter here */ )
		.catch(error => console.log(error));
}

And the error message could be the following Json object:

error = {
	"code": 255,
	"message": "An event handler does not exist for the user event myEventName"
}

On the other hand, if we want to send an event using the send method from Java, but there is no handler (on method) on the JavaScript side, the future Future returned by send will be completed exceptionally, for example:

void someFunction(){
	commService.send("myEventName", payload)
		.exceptionally(throwable -> {
			System.out.println("Error code: " + ((CommMessageException) throwable).getErrorCode() +
				", Error message: " + throwable.getMessage());
		});
}

In this example, the future returns an exception with the same error code and message that we saw previously.