Mindaugas Jaraminas
Mindaugas Jaraminas

Reputation: 3447

How to send POJO from java to JS in Vaadin application

How to transfer java object to Java Script in Vaadin

I have a function that has to be called from frontend but it requires a big data set but it is impractical to map data to JSON and then convert it back.

for example I have a POJO

public class EmployeePojo {

public String firstName;
public String lastName;
private LocalDate startDate;

public EmployeePojo(String firstName, String lastName, LocalDate startDate) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.startDate = startDate;
}

public String name() {
    return this.firstName + " " + this.lastName;
}

public LocalDate getStart() {
    return this.startDate;
}

}

And I have to transfer a list of EmployeePojo to a java script

For example:

var list = new ArrayList<EmployeePojo>();
initList(list);
UI.getCurrent().getPage().executeJs("addData($0,$1,$2)",
    getElement(), name, list);

Does some one knows solution?

I am using Vaadin 24.0.11 and Quarkus 3.0.4

One of the solutions is to use JsonObject for example:

 var json = elemental.json.Json.createObject();
 json.put("param", "test name");
 UI.getCurrent().getPage().executeJs("addData($0,$1,$2)",
      getElement(), name, json);

But I am receiving error:

2023-10-03 10:18:50,017 ERROR [com.vaa.flo.ser.DefaultErrorHandler] (executor-thread-2) : java.lang.RuntimeException: java.lang.LinkageError: loader constraint violation: loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @29c1c2d3 wants to load interface elemental.json.JsonObject. A different interface with the same name was previously loaded by io.quarkus.bootstrap.classloading.QuarkusClassLoader @1ffe63b9. (elemental.json.JsonObject is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @1ffe63b9, parent loader 'app')

Upvotes: 0

Views: 159

Answers (1)

mstahv
mstahv

Reputation: 1934

The solution is not use the built-in API to pass the objects to the browser/JS. Instead, use e.g. Jackson (which comes in as transitive dependency), and serialise the objects directly to the JS calls.

For example use this kind of superclass in your POJO:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;

public class AbstractKebabCasedDto {
    static ObjectMapper mapper = new ObjectMapper();
    static {
        mapper.setPropertyNamingStrategy(new PropertyNamingStrategies.KebabCaseStrategy());
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    // JSON representation to be easily used in JS calls
    @Override
    public String toString() {
        try {
            return mapper.writeValueAsString(this);
        } catch (JsonProcessingException e) {
            return "{'value': 'JSON ERROR'}";
        }
    }
}

And then you can pass it to JS:

getElement().executeJs("yourJSLibraryMethod(%s)".formatted(pojo)

Check this recent blog post of mine about this approach for more details: https://vaadin.com/blog/building-java-api-for-javascript-libraries

Depending on situation, you can also use the same approach to pass back data from the browser side.

Upvotes: 1

Related Questions