1

ユースケースごとに、これが私たちが行うことです:

  1. 複数のAsyncサービス API を異なる引数 (例: InputObject1、InputObject2 など) で公開します。
  2. クライアントは適切な入力タイプでこれらの API を呼び出し、応答をクライアントに送り返し、JSON 形式 (Gson を使用) で入力オブジェクトをキュー (例: SQS) にプッシュします。
  3. 別のポーラーは、キューをポーリングし続け、キューからメッセージを受信します。メッセージを受信すると、ポーラーは inputObject タイプに従ってタスクを実行する必要があります。

コードが汚れているように見える場所が 2 つあります。

a. How to check the type of object on receiving from the queue? This would be in JSON format and I will have to convert JSON back to object. It will belong to one of the multiple potential objects.

b. Once type is known, how to call class responsible to handle that object?

このユースケースに最適な設計は何でしょうか?

For a), one option is to create a `RequestWrapper` containing all the objects and populating the one this message belongs to.

b) について考えることができるいくつかの方法は次のとおりです。

1. Add another parameter to the object and pass it to queue. Use this parameter to identify API called.
2. Use `instanceof` to get exact requestObject using multiple if-else and do the needful.

ただし、これらは私にはあまりきれいに見えません。より良い提案はありますか?

==Edit==

@A4L

  1. いいえ、共通のインターフェースはありません (少なくとも現時点では)。

  2. はい、最初からこれらのオブジェクトを変更できます (それが「実装」の意味である場合)。これは変更できるので、必要に応じて、共通のインターフェイスを共有できるようにします。

ありがとう、

4

1 に答える 1

1

QueueTaskAble入力オブジェクトによって実装される少なくとも 1 つの新しいインターフェイスを導入することをお勧めjava.lang.Runnablerunますexecute.

これは次のようになります。

interface QueueTaskAble {
    Runnable getQueueTask();
}

class InputObjectFooQueueTask implements Runnable {
    @Override
    public void run() {
        // TODO Auto-generated method stub            
    }
}

class InputObjectFooImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectFooQueueTask();
    }
}

void processQueueInputObject(QueueTaskAble queueObject) {
    queueObject.getQueueTask().run();
}

編集

残念ながら、Gsonを使用してインターフェイスとしてネイティブにデシリアライズすることはできません。これを可能にするには、オブジェクトが適切にシリアライズおよびデシリアライズされるように、GsonBuilder#registerTypeAdapterに渡すことができる型アダプターを実装する必要があります。

これを行う方法は次のとおりです。

型アダプター

public class GenericGsonTypeAdapter<T> implements JsonSerializer<T>, 
        JsonDeserializer<T> {

    @Override
    public JsonElement serialize(T src, Type typeOfSrc, 
                    JsonSerializationContext context) {
        JsonObject jo = new JsonObject();
        jo.addProperty("className", src.getClass().getName());
        jo.add("jsonData", context.serialize(src));
        return jo;
    }

    @Override
    public T deserialize(JsonElement json, Type typeOfT,
        JsonDeserializationContext context) throws JsonParseException {
        T obj = null;
        if(json instanceof JsonObject) {
            JsonObject jo = (JsonObject) json;
            JsonElement jeJson = jo.get("jsonData");
            if(jeJson != null) {
                JsonElement jeClassName = jo.get("className");
                try {
                    obj = context.deserialize(json,
                                Class.forName(jeClassName.getAsString()));
                } catch (ClassNotFoundException e) {
                    throw new JsonParseException(e);
                }
            }
        }
        return obj;
    }   
}

カスタムGsonビルダー (残念ながらGsonBuilderは final であるため、拡張できないため、静的な最終メンバーとして)

public class InputObjectGsonBuilder {
    private final static GsonBuilder gb;
    static {
        gb = new GsonBuilder();
        gb.registerTypeAdapter(QueueTaskAble.class,
                    new GenericGsonTypeAdapter<QueueTaskAble>());
    }

    public Gson create() {
        return gb.create();
    }
}

サンプル キュー

public class InputObjectGsonQueue {

    private Queue<String> queue = new ArrayDeque<>();

    public boolean pushInputObject(String json) {
        return queue.offer(json);
    }

    public void processQueue() {
        InputObjectGsonBuilder gb = new InputObjectGsonBuilder();
        String json;
        while(null != (json = queue.poll())) {
            QueueTaskAble queueTaskAble = gb.create().fromJson(json,
                               QueueTaskAble.class);
            processQueueInputObject(queueTaskAble);
        }
    }

    private void processQueueInputObject(QueueTaskAble queueObject) {
        queueObject.getQueueTask().run();
        // or for asynchronous processing
        // new Thread(queueObject.getQueueTask()).start();
    }
}

いくつかの入力オブジェクトとタスクの実装

public class InputObjectFooImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectFooTaksImpl();
    }
}

public class InputObjectBarImpl implements QueueTaskAble {
    @Override
    public Runnable getQueueTask() {
        return new InputObjectBarTaksImpl();
    }
}

public class InputObjectFooTaksImpl implements Runnable {
    @Override
    public void run() {
        System.out.println("Foo!");
    }
}

public class InputObjectBarTaksImpl implements Runnable {
    @Override
    public void run() {
        System.out.println("Bar!");
    }
}

そして最後にサンプルアプリケーション

public class App {
    public static void main(String... args) {
        InputObjectGsonBuilder gb = new InputObjectGsonBuilder();

        InputObjectGsonQueue gq = new InputObjectGsonQueue();
        gq.pushInputObject(gb.create().toJson(new InputObjectFooImpl(), 
                    QueueTaskAble.class));
        gq.pushInputObject(gb.create().toJson(new InputObjectBarImpl(), 
                    QueueTaskAble.class));

        gq.processQueue();
    }
}

出力

Foo!
Bar!
于 2013-10-28T13:29:01.837 に答える