ActiveMQとQuarkus、Apache Camelで、画像アップロード処理をしたい。 その1 Producer 編

承前

  • ブラウザ->ウェブアプリ->ActiveMQ->ApacheCamel->AWS S3 と言うルートを考えてみましょう。
    • ウェブアプリでEXIF情報を消去したり、画像縮小を行ってS3にアップロードするには、少々重たい処理ですね。
      • 非同期で、イベント駆動で処理したいですよね。
    • ウェブアプリはDockerで建てているのだから、ActiveMQ1 も Consumerである Apache Camel2 もDockerでインスタンス作って、メッセージ送信/受信したらいいよね。
    • …と、思ったら、意外と大変だった、と言う感じです。

JMS(Java Message Service) と Producer と Consumer

  • JMSは歴史的経緯から、とにかく複雑な仕様で、正直に向き合うと、げんなりしてしまうのですけどね…。
  • まぁ、シンプルにProducer->ActiveMQ->Consumerで、送信元Producerが、受信元Consumerに向けて、オブジェクトをメッセージとして送る、オブジェクトのエンコード/デコードを簡単に(?)やってくれる、と、考えたら良いと思います。
    • 今回はウェブアプリProducerの役割ですね。

ウェブアプリケーションに画像アップロード

画像データをActiveMQに送信する

  • JMSの使用 - Quarkus
    • 依存関係に Quarkus Artemis JMS Runtimeを忘れずに。
    • application.propertiesquarkus.artemis.***=を記述することを忘れないように。
    • そうすると、ConnectionFactoryもDI対象になりますよ。
  public void uploadImage(String fileName, InputStream file) {
    try (JMSContext context = this.connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE);
        ByteArrayOutputStream out = new ByteArrayOutputStream()) {
      // ファイル読み込み
      file.transferTo(out);
      out.flush();

      // メッセージ作成
      BytesMessage message = context.createBytesMessage();
      message.setStringProperty("fileName", fileName);
      message.writeBytes(out.toByteArray());
      
      // トピックを送信
      context.createProducer().send(context.createTopic("upload.image"), message);
    } catch (IOException | JMSException e) {
      throw new RuntimeException(e);
    }
  }