柔軟なファイル名/複数のファイルの書込み

デフォルトでは、データはバッチ・パラメータで定義されているファイル名に書き込まれます。ファイル名では、「プラグイン主導の抽出テンプレート」バッチ管理(F1-PDBEX)のバッチ・パラメータの詳細な説明で定義されている複数の動的置換変数がサポートされています。ファイル名とマルチスレッド・プロセスの詳細は、「抽出レコード処理」も参照してください。

また、1回のバッチ実行で、より高度なファイルを作成することもサポートされています。次のユース・ケースについて考えてみます

  • 複数のサービス・プロバイダに関連付けられたデータが抽出の対象となり、各サービス・プロバイダが各自のファイルを受け取る必要があります。このユース・ケースでは、作業単位はサービス・プロバイダであるため、作業単位ごとにファイルが生成されます。
  • 実装では、顧客情報サービス部門で表される複数の管轄区域で事業を運営します。特定の抽出で、各部門がその関連データのみを受け取るように、最終的に部門ごとにファイルが生成されるようにする必要があります。
  • パーソン情報の抽出では、個別のパーソン・データとビジネスのパーソン・データを分離する必要があります。また、パーソンごとにコンタクト情報を個別のファイル内に生成する必要もあります。このユース・ケースでは、複数のファイルに書き込まれるデータが1つの作業単位に含まれます。

前述のユース・ケースに対応するために、レコードの処理アルゴリズムでは、出力でファイル名を返すことがサポートされています。

  • ファイル名は出力スキーマ・インスタンス・グループに含められます。特定のスキーマ・エントリのデータをこのファイル名に出力するには、これを指定します。前述のパーソン抽出の例では、コンタクト情報を含むスキーマが特定のコンタクト・ファイルを示します。
  • ファイル名は、スキーマ・リストの外部の出力フィールドです。スキーマごとにファイルが分かれているわけではないが、バッチ・パラメータで定義されているファイル名を上書きする場合は、これを移入します。前述のサービス・プロバイダおよび部門の例では、このパラメータに必要なファイル名が移入されます。パーソン抽出の例では、コンタクト以外のすべての情報についてこのフィールドに移入できます。

バッチ・プロセスでは、レコードの処理アルゴリズムがコールされるたびに出力がチェックされます。各スキーマについて、スキーマに特定のファイル名が関連付けられている場合は、そのスキーマのデータがそのファイルに書き込まれます。そうでない場合は、出力ファイル名を指定すると、そのファイルにデータが書き込まれます。それ以外の場合は、バッチ・パラメータのファイル名が使用されます。

注意: 置換変数。レコードの処理がコールされた後、ファイル名にシステム変数が含まれている場合、これはこの時点で解決されます。

ファイル名の管理

このタイプの要件は、個々のファイルを区別するためのビジネス値を含むファイル名が、レコードの処理アルゴリズムで指定される必要があることを意味します。たとえば、サービス・プロバイダ、部門またはパーソン・タイプの値をファイル名に含める必要があります。ただし、アルゴリズムによりファイル名が完全に決定されるようにすることはお薦めしません。バッチ・ジョブを発行するユーザーが必要なファイル名をバッチ・パラメータとして指定することもできるようにしておくことをお薦めします。このようにすると、システム情報(バッチ実行番号や日時スタンプなど)に対してサポートされている任意の置換変数を含めることができ、ある特定のバッチ実行で各ファイルが確実に一意になるようにできます。アルゴリズムに置換変数を指定し、検索してビジネス値に置換されるようにできます。

たとえば、部門別のユース・ケースで、ユーザーがファイル名EXTRACT_​FILE_​<DIV>_​{BN}_​{RN}_​{TN}.csvを指定したとします。レコードの処理アルゴリズムが、このパラメータを受け取ります。アルゴリズムは"<DIV>"を検索して、それを実際の部門に置き換えます。部門コードがA100であるとすると、出力でファイル名EXTRACT_​FILE_​A100_​{BN}_​{RN}_​{TN}.csvが返され、この作業単位用のそのファイルに書き込むデータも返されます。

前述のパーソン情報のユース・ケース(2つのファイルが書き込まれる)では、一方のファイル(パーソン情報ファイルなど)に対してファイル名パラメータを使用することをお薦めします。2つ目のファイル、コンタクト情報ファイルを定義するには、追加のパラメータを使用する必要があります。そのため、バッチ・ジョブを発行するユーザーは、次のパラメータを定義します。

パラメータ名 摘要 コメント
fileName ファイル名 persons_​<personType>_​{BN}.txt これは、抽出で提供されるファイル名パラメータです。
contactFileName コンタクト・ファイル名 contacts_​{BN}.txt これは、CM抽出バッチ管理で定義されている特別なパラメータです。

レコードの処理アルゴリズムは、入力として提供されたファイル名パラメータを検索し、テキスト"<personType>"を見つけてパーソン・タイプ値に置き換え、出力でそのファイル名を返します。出力で返すスキーマのリストを作成するとき、パーソン・コンタクト情報を含むスキーマには、入力として提供されたコンタクト・ファイル名パラメータで見つかったファイル名が含められます。

複数スレッド

この機能は、複数のスレッドで想定どおり動作します。レコードの選択アルゴリズムのユース・ケースおよび実装に基づいて、各スレッドで同じビジネス値に対するファイルを生成できます。部門のユース・ケースを使用しましょう。実装で、3つの部門(A100、B200、C300)があるとします。ここでは、アカウントの財務情報を抽出する処理を想定します。レコードの選択アルゴリズムは、データが複数のスレッドに均等に配分されるように、アカウントIDでスレッド化する必要があります。ただし、各スレッド内のアカウントは、実装の3つの部門のいずれのものである可能性もあります。そのため、各スレッドで3部門それぞれに対する3つのファイルが生成される可能性があります。

「マルチスレッド抽出」で説明されているように、システムでは連結のオプションがサポートされているため、3つの部門に対して3つの完全なファイルが存在するようにファイルを集約できます。このユース・ケースには、そのトピックで説明されている同じ機能および制限が適用されます。

ファイルのクローズ

この機能を使用する際の重要な考慮事項は、バッチ・プロセス中にオープンしているファイルの数に注意する必要があるということです。オープンしているそれぞれのファイルには、それを管理するためのメモリーが必要になります。そのため、バッチ・ジョブ実行中にオープンするファイルの数は(スレッド当たり) 10ファイルに制限されています。複数のファイルに書き込むバッチを設計するときには、可能な場合は常に、1つのファイルにすべてのデータを書き込んだら、次のファイルに移動する前にそのファイルをクローズできるようなプロセスを設計することを強くお薦めします。

例を見てみましょう。

  • サービス・プロバイダの例では、バッチ・プロセスの作業単位はサービス・プロバイダです。この場合は、レコードの処理がコールされるたびにデータをファイルに書き込み、その後、そのファイルをクローズできます。
  • 部門の例では、選択したデータを、抽出の目的に関連する適切な作業単位(アカウントや資産など)でスレッド化することが適切です。ただし、部門ごとにすべてのデータが次の部門のデータよりも前に処理されるように、データを部門順に並べることが適切です。各部門のファイルは、次の部門のデータの処理が開始されたらクローズできます。
  • パーソン抽出の例では、すべてのデータにコンタクト・ファイルが使用されるため、ジョブの実行中はファイルをオープンしておく必要があります。ただし、パーソン情報はパーソン・タイプ別に分類されます。レコードの選択では、パーソン・タイプ別にデータに順序を付けることができます。これにより、あるタイプに対するすべてのデータを書き込んでから、他のタイプに対するすべてのデータを書き込むことができます。ただし、いずれの実行でもオープンしているファイルが3ファイルを超えることがない場合、このユース・ケースではプロセス中に積極的にファイルをクローズするよう管理する必要はありません。

バッチ・プログラムはファイルをいつクローズするかをどのようにして判断するのでしょうか。バッチ・プログラムは、処理対象のデータのタイプやファイルをいつクローズするかを判断する情報を持たないため、レコードの処理アルゴリズムがこの情報を提供する必要があります。

注意: 書込み先ファイルがすでにクローズしたファイルであることがレコードの処理によって示されると、バッチ・プロセスでエラーが発生します。クローズしたファイルを再度オープンすることはできません。このエラーが発生した場合は、プロセスの設計を確認する必要があります。

これを管理するために、バッチ・プロセスは、レコードの処理アルゴリズムに対して、(システム置換変数が未解決の)オープンしているファイルのリストと、ファイルをクローズするかどうかを示すブール値を提供します。例を使用してさらに説明します。

部門別のファイルの例

このユース・ケースでは、NORTH、EAST、SOUTH、WESTという4つの部門があり、データ(アカウント・データ)を部門ごとに別々のファイルにグループ化する必要があります。

レコードの選択アルゴリズムで、部門順に並べられたデータが選択されるようにすることをお薦めします。

バッチ・プロセスは、オープンしているファイル(0個または1個である必要があります)のリストをレコードの処理アルゴリズムに渡します。この場合、ある部門に対するデータが完了していると判断できるのは、レコードの処理アルゴリズムによって、データの部門とリストされたオープン・ファイルの部門が異なっていると認識された場合のみです。コールのたびに、そのファイル名を準備する必要があります。次に、オープンしているファイルのリストにそのファイル名があるかどうかを確認する必要があります。ない場合は、オープンしている他のファイルをクローズすることを指定します。('オープン・リスト'にそれ自体を追加する必要はありません。バッチ・プログラムは、クローズ済としてマークされたエントリのみを探します。クローズ済としてマークされていないエントリは無視されます)。

バッチ・パラメータのファイル名が、myFile_​<DIV>_​{BN}.txtであるとします

データはソートされ、EAST部門のアカウントが最初に処理されるようになっています。ここで、これがEAST部門にも存在する作業単位であると想定してみましょう。ファイル名とオープンしているファイルのリストを受け取ります。

...
<hard>
<batchParms>
  <BatchParm>
    <name>fileName</name>
    <value>myFile_<DIV>_{BN}.txt</value>
  </BatchParm>
  ...
</batchParms>
<openFiles>
  <OpenFile>
    <closeFile></closeFile>
    <fileName>myFile_EAST_{BN}.txt</fileName>
  </OpenFile>
</openFiles>
...
</hard>

アルゴリズムは、ファイルの<DIV>部分をその部門に置換し、それを出力に移入します。次に、そのファイル名と、現在オープンしているファイルのリストを比較します。そのファイルが見つかったので、他の処理を行う必要はありません。


<hard>
...
<fileName>myFile_EAST_{BN}.txt</fileName>
...
<openFiles>
  <OpenFile>
    <closeFile></closeFile>
    <fileName>myFile_EAST_{BN}.txt</fileName>
  </OpenFile>
</openFiles>
...
</hard>

次に、部門がNORTHで、その部門の最初のエントリについてレコードの処理アルゴリズムをコールするとします。この場合、次の内容が受け取られます。


<hard>
<batchParms>
  <BatchParm>
    <name>fileName</name>
    <value>myFile_<DIV>_{BN}.txt</value>
  </BatchParm>
  ...
</batchParms>
<openFiles>
  <OpenFile>
    <closeFile>true</closeFile>
    <fileName>myFile_EAST_{BN}.txt</fileName>
  </OpenFile>
</openFiles>
...
</hard>

アルゴリズムは、ファイルの<DIV>部分をその部門に置換し、それを出力に移入します。次に、そのファイル名と現在オープンしているファイルのリストを比較しますが、そのファイル名が見つかりません。そのため、既存のオープンしているファイルをクローズすることを指定します。


<hard>
...
<fileName>myFile_NORTH_{BN}.txt</fileName>
...
<openFiles>
  <OpenFile>
    <closeFile>true</closeFile>
    <fileName>myFile_EAST_{BN}.txt</fileName>
  </OpenFile>
</openFiles>
...
</hard>

サービス・プロバイダ別のファイルの例

このユース・ケースでは、作業単位はサービス・プロバイダで、各サービス・プロバイダに独自のファイルが必要です。この場合、レコードの処理アルゴリズムは、そのサービス・プロバイダに固有のデータとファイル名を準備するため、ファイルをクローズできると指定することもできます。前のファイルをクローズできると示すために、レコードの処理の次のコールを待機する必要はありません。ここで、ファイル名がMYFILE_​<serviceProvder>_​{BN}_​{TN}.txtであるとします。レコードの処理がコールされるたびに、バッチ・パラメータ・ファイル名が渡されます。オープンしているファイルはありません。


<hard>
<batchParms>
  <BatchParm>
    <name>fileName</name>
    <value>MYFILE_<serviceProvider>_{BC}_{TN}.txt</value>
  </BatchParm>
  ...
</batchParms>
<openFiles>
  <OpenFile>
    <fileName></fileName>
    <closeFile></closeFile>
  </OpenFile>
</openFiles>
...
</hard>

アルゴリズムはサービス・プロバイダA100のデータを処理しています。ファイル名に関連する情報(単一のファイル名)を、このサービス・プロバイダに関連する出力で返し、そのファイルをオープン・ファイルのリストに追加します。また、そのファイルをクローズする必要があることを指定します。(作業単位別のファイルは、それがファイルの最後のエントリであることをアルゴリズムが判断してそれ自体をクローズする、唯一の既知のユース・ケースです。)

<hard>
...
<fileName>MYFILE_A100_{BC}_{TN}.txt</fileName>
...
<openFiles>
  <OpenFile>
    <closeFile>true</closeFile>
    <fileName>MYFILE_A100_{BC}_{TN}.txt</fileName>
  </OpenFile>
</openFiles>
...
</hard>

複数のファイルをオープンする例

この例では、前述の「ファイル名の管理」の項に従ってファイル名が定義されていることを前提としています。オープンするファイルが3つを超えることがないため、アルゴリズム設計者がパーソン情報ファイルを事前にクローズしないことを選択したとします。同様に、パーソン・タイプの順にデータを並べないことを選択したとします。実行中に次のものが渡されます。

<hard>
<batchParms>
  <BatchParm>
    <name>fileName</name>
    <value>persons_<personType>_{BN}.txt</value>
  </BatchParm>
  <BatchParm>
    <name>contactFileName</name>
    <value>contacts_{BN}.txt</value>
   </BatchParm>
  ...
</batchParms>
<openFiles>
  <OpenFile>
    <fileName>persons_P_{BN}.txt</fileName>
    <closeFile></closeFile>
  </OpenFile>
   <OpenFile>
    <fileName>persons_B_{BN}.txt</fileName>
    <closeFile></closeFile>
  </OpenFile>
  <OpenFile>
    <fileName>contacts_{BN}.txt</fileName>
    <closeFile></closeFile>
  </OpenFile>
</openFiles>
...
</hard>

個人("P"パーソン・タイプ)の詳細を含む、レコードの処理アルゴリズムの1回のコールのインスタンス。


<fileName>persons_P_{BN}.txt</fileName> 
<fileOutput>
  <listValue>
    <SchemaInstance>
      <recordXMLNode>person</recordXMLNode>
      <schemaName>CM-PersonDetail</schemaName>
      <schemaType>F1SS</schemaType>
      <fileName></fileName>
      <data>LotsOfData</data>
    </SchemaInstance>
  </listValue>
  <listValue>
    <SchemaInstance>
      <recordXMLNode>person</recordXMLNode>
      <schemaName>CM-AddressDetail</schemaName>
      <schemaType>F1SS</schemaType>
      <fileName></fileName>
      <data>LotsOfData</data>
    </SchemaInstance>
  </listValue>
  <listValue>
    <SchemaInstance>
      <recordXMLNode></recordXMLNode>
      <schemaName>CM-ContactDetail</schemaName>
      <schemaType>F1SS</schemaType>
      <fileName>contacts_{BN}.txt</fileName>
      <data>LotsOfData</data>
    </SchemaInstance>
  </listValue>
</fileOutput>

このXMLの例では、次のポイントを示します。

  • fileName要素には上書きファイル名があります。
  • 1つ目と2つ目のスキーマは、fileOutput\listValue\SchemaInstance\fileNameに値がないため、ファイルのfileNameに書き込まれる必要があります。この2つのスキーマには、レコードXMLノードも含まれています。これにより、出力がXML書式の場合、この両方のスキーマのデータが'person' XMLノードでラップされます。これは、このトピックに関連する機能ではありません。単に、複数の機能を示す目的で記載しています。
  • 3つ目のスキーマは、fileOutput\listValue\SchemaInstance\fileNameにエントリがあります。このため、そのデータは別のファイルに書き込まれます。