ストリームデータ・レスポンス

*Curl ORB for Java version 0.6 がリリースされました。リリースノートはこちら

ストリームを利用した使用メモリ量削減

サイズの大きなデータをクライアントへ返す際、オブジェクトを生成してから結果を返すと多くのメモリを必要とてしまうため、順次ストリームに書き込む機能が用意されています。このコードは自動生成されないため、以下にサンプルを用いてコーディング方法を説明します。ここで使用するAPIは、SerializableStreamWriterクラス (com.curlap.orb.ioパッケージ)です。

サンプルと利用方法

この機能を利用するには、Javaサービスクラスのメソッドの戻り値をvoidにし、引数の最後にSerializableStreamWriterクラスを指定します。サーバサイドの開発者はこのSerializableStreamWriterクラスのwriteメソッドを用いて、クライアントに返すデータをストリームに書き込みます。ストリームの終了にはcloseを実行します。 

// Java
import com.curlap.orb.io.SerializableStreamWriter;
import com.curlap.orb.io.SerializerException;

public class StreamTest implements java.io.Serializable {
    public StreamTest() {
        // do nothing
    }

    // 結果にString, int, 日付オブジェクト書き込む。
    public void method1(String str, int i, SerializableStreamWriter writer) {
        try {
            writer.write(str);
            writer.write(i);
            writer.write(new java.util.Date());
            writer.close();
        } catch (SerializerException e) {
            e.printStackTrace();
        }
    }

    // 結果にFooの配列を書き込む
    public void method2(SerializableStreamWriter writer) {
        try {
            for (int i = 0; i < 10000; i++)
            writer.write(new Foo());
            writer.close();
        } catch (SerializerException e) {
            e.printStackTrace();
        }
    }
}

Curl側では、引数のSerializableStreamWriterを省いて、戻り値をvoidの代わりにArray ({Array-of any}と同じ)を指定します。これによりJava側でSerializableStreamWriterに書き込んだオブジェクトを、Curl側でArrayの戻り値として受け取ることが可能となります。また、当機能を利用する場合は、self.invokeのキーワード引数として、is-stream-response?trueにする必要があります。(実際には、Javaサービスクラスを作成し、コード生成ツールでCurlコードを生成した後、Curlコードを修正する方法が良いとおもいます。)

|| Curl
{define-class public StreamTest {inherits ORBClientForContext}

  {constructor public {default}
    {construct-super.ORBClientForContext “stream1”}
  }

  || method1
  {method public {method1 str:String, i:int}:Array
    {return
        {self.invoke
            “method1”,
            arguments = {{FastArray-of any} str, i},
            is-stream-response? = true
        }
    }
  }

  || method2
  {method public {method2}:Array
    {return
        {self.invoke
            “method2”,
            is-stream-response? = true
        }
    }
  }
}

クライアントの利用方法は以下の通りです。

def stream-test = {StreamTest}
def return-value = {stream-test.method1 “ABC”, 123}
def s = return-value[0] asa String
def I = return-value[1] asa int
def d = return-value[2] asa DateTime

{for f in {Stream-test.method2} do
    def foo = f asa Foo
    || 業務ロジック …………
}

もちろんレコードのようなデータを一行づつ書き込むことができ、大量データをデータベースからクライアントで取得することもできます。