I have a handler that serves HTTP requests at a given endpoint. The handler messages a verticle via the event bus that makes some external paginated REST calls, aggregates the results, and returns the results back to the handler. The result of the paginated REST calls is represented as a List of custom objects. If I just try to send the List
itself, Vertx throws an exception complaining that it can't find a codec for java.util.ArrayList
.
I'm trying to find the "best" -- meaning the easiest, most efficient, and most readable/maintainable -- way in Vertx to send a list of these objects back across the event bus to my handler. These are the options I know of and have tried so far, are there better ways to achieve this?
JsonObject
. This requires an explicit serialization/deserialization on either end which seems unnecessary:// Verticle
List<CustomObject> result = method();
JsonObject data = new JsonObject();
data.put("result", Json.encode(result));
msg.reply(data);
// Handler
String serializedList = body.getString("result");
List<CustomObject> list = objectMapper.readValue(serializedList, new TypeReference<List<CustomObject>>(){});
ArrayList<CustomObject>
. In theory I believe this would work, but all the examples I've seen online for message codecs are always about creating a codec for a single object, and I'm not entirely sure if this would work for collections.Is there a simpler method that fits my use case that I'm unaware of? Thanks!
Sorry for a lengthy example, but here you go:
public class EventBusHolder {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.eventBus().registerDefaultCodec(Holder.class, new HolderCodec());
vertx.deployVerticle(new SomeVerticle(), (r) -> {
vertx.eventBus().send("custom", new Holder(new CustomObject("a")));
});
}
}
class HolderCodec implements MessageCodec<Holder, Holder> {
@Override
public void encodeToWire(Buffer buffer, Holder holder) {
}
@Override
public Holder decodeFromWire(int pos, Buffer buffer) {
return null;
}
@Override
public Holder transform(Holder holder) {
return holder;
}
@Override
public String name() {
return "HolderCodec";
}
@Override
public byte systemCodecID() {
return -1;
}
}
class SomeVerticle extends AbstractVerticle {
@Override
public void start() {
vertx.eventBus().consumer("custom", (msg) -> {
System.out.println(msg.body());
});
}
}
class CustomObject {
public String name;
public CustomObject(String name) {
this.name = name;
}
@Override
public String toString() {
return "CustomObject{" +
"name='" + name + '\'' +
'}';
}
}
final class Holder {
@Override
public String toString() {
return "Holder{" +
"data=" + data +
'}';
}
private final List<CustomObject> data;
public Holder(final CustomObject... data) {
this.data = Arrays.asList(data);
}
public List<CustomObject> getData() {
return data;
}
}
Take note that encodeToWire
and decodeFromWire
are not implemented. They aren't invoked for local messages.
Having this Holder
object is an easy way to get around type erasure on the JVM.