Как лучше всего отправить коллекцию объектов по шине событий в Vertx?

У меня есть обработчик, который обслуживает HTTP-запросы в заданной конечной точке. Обработчик отправляет сообщение о вершине через шину событий, которая выполняет некоторые внешние вызовы REST с разбивкой на страницы, агрегирует результаты и возвращает результаты обратно обработчику. Результат постраничных вызовов REST представлен в виде списка настраиваемых объектов. Если я просто попытаюсь отправитьList сам Vertx выдает исключение, жалуясь, что не может найти кодек для java.util.ArrayList.

Я пытаюсь найти "лучший" - то есть самый простой, наиболее эффективный и наиболее читаемый / обслуживаемый - способ в Vertx отправить список этих объектов обратно по шине событий моему обработчику. Это варианты, о которых я знаю и пробовал до сих пор, есть ли лучшие способы добиться этого?

  1. Сериализовать список в JSON и сохранить в JsonObject. Это требует явной сериализации / десериализации на обоих концах, что кажется ненужным:
// 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>>(){});

  1. Определите кодек сообщения для ArrayList<CustomObject>. Теоретически я считаю, что это сработает, но все примеры, которые я видел в Интернете для кодеков сообщений, всегда касаются создания кодека для одного объекта, и я не совсем уверен, сработает ли это для коллекций.

Есть ли более простой метод, который подходит для моего случая использования, о котором я не знаю? Спасибо!

1 ответ

Решение

Извините за длинный пример, но вот:

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;
    }
}

Обратите внимание, что encodeToWire а также decodeFromWireне реализованы. Они не вызываются для локальных сообщений.

Имея это Holder object - простой способ обойти стирание типа в JVM.

Другие вопросы по тегам