大きなファイルを読込、行毎にイベントを生成する方法。
Jay Lessik氏による案:
この例は以下のESB Muleコンポーネントを利用します:
その上、以下のJavaクラスも使います(ソースコードを例題の後にあります。):
ステップ 1: ファイル・プロバイダを設定
受信(inbound)トランスフォーマーにNoActionTransformerを指定して、 autoDelete プロパティを「false」に設定します。 moveToDirectory プロパティをファイルを複写するディレクトリ(入力ディレクトリ以外のディレクトリ)に設定します。設定しない場合は、手動でファイルの削除と移動を行う必要があります。以上の設定で、ファイル・プロバイダ(File Provider)はコンポーネントにFileオブジェクトを引き渡します(ファイルの全内容をStringで引き渡す代わりに)。
<connector name="myFileConnector" className="org.mule.providers.file.FileConnector">
<properties>
<property name="autoDelete" value="false"/>
<property name="moveToDirectory" value="file:///myOutputDir"/>
<map name="serviceOverrides">
<property name="inbound.transformer" value="org.mule.transformers.NoActionTransformer"/>
</map>
</properties>
</connector>
 |
注: ファイル・プロバイダ(File Provider)は処理後にファイルを削除しません。削除する必要がある場合は、削除する処理を別途に設ける必要があります。 |
ステップ 2: エンドポイントを設定
ステップ1で設定してファイル・プロバイダ(File Provider)と結果を出力するためのSystem.outエンドポイントを指定したファイル・エンドポイントを設定します。
<global-endpoints>
<endpoint name="myFileEndpoint" address="file:///myInputDir?connector=myFileConnector"/>
<endpoint name="myOutputEndpoint" address="stream://System.out"/>
</global-endpoints>
 |
注: 送信(outbound)エンドポイントをSystem.outエンドポイント以外に設定することも可能です。本当に大きなファイルを処理する場合は、画面に出力するのではなく、ファイル等のようなものに出力した方がよいと思います。 |
ステップ 3: ファイル分割ESB Muleコンポーネントを設定
ESB Muleの設定ファイルで、ファイルを分割するファイル分割(file splitter)コンポーネントを設定します。ファイル分割コンポーネントは、ステップ2で設定したファイル(File)・エンドポイントからファイル・メッセージを受信して、FileMessageSplitter送信(outbound)ルータに(ESB MuleのBridgeComponent)を使って)転送します。FileMessageSplitter送信ルータ(outbound-router)は、ファイルを分割して送信(outbound)エンドポイントに送信します。
<mule-descriptor name="myBigFileSplitter" implementation="org.mule.components.simple.BridgeComponent">
<inbound-router>
<global-endpoint name="myFileEndpoint"/>
</inbound-router>
<outbound-router>
<router className="test.FileMessageSplitter">
<global-endpoint name="myOutputEndpoint"/>
</router>
</outbound-router>
<interceptor name="default"/>
</mule-descriptor>
Javaのソース・コード
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public interface FileSplitter {
public void setFile(File file) throws FileNotFoundException;
public File getFile();
public String getNextRecord() throws IOException;
public void close();
}
package test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class BufferedFileSplitter implements FileSplitter
{
private File file;
private BufferedReader bufferedReader;
private final Log logger = LogFactory.getLog(getClass());
public BufferedFileSplitter() {
}
/**
* コンストラクタ
* @param File ファイル
* @throws FileNotFoundException ファイルがnull又は無い場合
*/
public BufferedFileSplitter(File file) throws FileNotFoundException {
if (file == null) {
throw new FileNotFoundException("ファイルがnullです。");
}
this.file = file;
this.bufferedReader = new BufferedReader(new FileReader(file));
}
/**
* ファイルから次のレコードを取得する。
*
* @return 次のレコードの内容を文字列として返します。改行コードやファイルの最後のnullは含まれません。
* @throws IOException I/Oエラー
*/
public String getNextRecord() throws IOException {
if (file == null) {
throw new IOException("ファイルはnullです。ファイルを読み込む前に設定してください。");
}
if (bufferedReader == null) {
throw new IOException("BufferedReaderがnullです。");
}
return bufferedReader.readLine();
}
/**
* BufferedFileSplitterをcloseする。
*/
public void close() {
try {
bufferedReader.close();
} catch (IOException e) {
logger.error("BufferedReaderのcloseに失敗しました。", e);
}
}
/**
* 分割するファイルを取得する。
*
* @return File ファイル
*/
public File getFile() {
return file;
}
/**
* 分割するファイルを設定する。
* @param file ファイル
* @throws FileNotFoundException ファイルがnull又は無い場合。
*/
public void setFile(File file) throws FileNotFoundException {
if (file == null) {
throw new FileNotFoundException("ファイルがnullです。");
}
this.file = file;
this.bufferedReader = new BufferedReader(new FileReader(file));
}
}
package test;
import org.mule.impl.MuleMessage;
import org.mule.routing.outbound.AbstractMessageSplitter;
import org.mule.umo.UMOMessage;
import org.mule.umo.endpoint.UMOEndpoint;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class FileMessageSplitter extends AbstractMessageSplitter
{
private FileSplitter fileSplitter;
private static final ThreadLocal propertiesContext = new ThreadLocal();
protected void initialise(UMOMessage message) {
super.initialise(message);
File payloadFile;
Object payload = message.getPayload();
if (payload instanceof File)
{
payloadFile = (File) payload;
}
else
{
throw new IllegalArgumentException("このルータ(router)のペイロードはjava.io.Fileでなければなりません。");
}
try
{
fileSplitter = new BufferedFileSplitter(payloadFile);
}
catch (FileNotFoundException e)
{
throw new IllegalArgumentException("ファイルが見つかりません。ファイル: " + payloadFile.getAbsolutePath());
}
Map props = new HashMap();
for (Iterator iterator = message.getPropertyNames().iterator(); iterator.hasNext();)
{
String propertyKey = (String) iterator.next();
props.put(propertyKey, message.getProperty(propertyKey));
}
propertiesContext.set(props);
}
protected UMOMessage getMessagePart(UMOMessage message, UMOEndpoint endpoint)
{
String record = null;
try
{
record = fileSplitter.getNextRecord();
}
catch (IOException e)
{
logger.fatal("致命的エラー: " + e.getMessage(), e);
}
if (record != null)
{
return new MuleMessage(record, (Map) propertiesContext.get());
}
else
{
return null;
}
}
}