Reputation: 3447
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
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