38.2. XML スキーマプリミティブの Java クラスの指定

概要

デフォルトでは、XML スキーマ型は Java プリミティブ型にマップされます。これは XML スキーマと Java の間の最も論理的なマッピングですが、アプリケーション開発者の要件を常に満たすとは限りません。XML スキーマプリミティブ型を追加情報を保持できる Java クラスにマップしたり、XML プリミティブ型を単純な型置換を可能にするクラスにマップしたりすることができます。

JAXB javaType カスタマイズ要素を使用すると、XML スキーマプリミティブ型と Java プリミティブ型間のマッピングをカスタマイズできます。これを使用して、グローバルレベルと個々のインスタンスレベルの両方でマッピングをカスタマイズできます。javaType 要素は、単純型定義の一部として、または複合型定義の一部として使用できます。

javaType カスタマイズ要素を使用する場合は、プリミティブ型の XML 表現とターゲット Java クラス間の変換方法を指定する必要があります。一部のマッピングには、デフォルトの変換方法があります。デフォルトのマッピングがない場合、Apache CXF は必要なメソッドの開発を容易にする JAXB メソッドを提供します。

構文

javaType カスタマイズ要素は、表38.1「XML スキーマタイプの Java クラスの生成をカスタマイズするための属性」 に記載されている 4 つの属性を取ります。

表38.1 XML スキーマタイプの Java クラスの生成をカスタマイズするための属性

属性必須説明

name

はい

XML スキーマプリミティブ型がマップされる Java クラスの名前を指定します。有効な Java クラス名または Java プリミティブ型の名前のいずれかである必要があります。このクラスが存在し、アプリケーションからアクセスできることを確認する必要があります。コードジェネレータはこのクラスをチェックしません。

xmlType

いいえ

カスタマイズされる XML スキーマプリミティブ型を指定します。この属性は、javaType 要素が globalBindings 要素の子として使用される場合にのみ使用されます。

parseMethod

いいえ

データの文字列ベースの XML 表現を Java クラスのインスタンスに解析するためのメソッドを指定します。詳細は、「コンバーターの指定」 を参照してください。

printMethod

いいえ

Java オブジェクトをデータの文字列ベースの XML 表現に変換するためのメソッドを指定します。詳細は、「コンバーターの指定」 を参照してください。

javaType カスタマイズ要素は、3 つの方法で使用できます。

  • XML スキーマプリミティブ型のインスタンスをすべて変更する場合: globalBindings カスタマイズ要素の子として使用されている場合、javaType 要素はスキーマドキュメントの XML スキーマ型のインスタンスをすべて変更します。この方法で使用する場合、変更中の XML スキーマプリミティブ型を識別する xmlType 属性の値を指定する必要があります。

    例38.7「グローバルプリミティブ型のカスタマイズ」に、スキーマの xsd:short の全インスタンスに java.lang.Integer を使用するようコードジェネレーターに指示する、インラインのグローバルカスタマイズを示します。

    例38.7 グローバルプリミティブ型のカスタマイズ

    <schema targetNamespace="http://widget.com/types/widgetTypes"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            jaxb:version="2.0">
      <annotation>
        <appinfo>
          <jaxb:globalBindings ...>
            <jaxb:javaType name="java.lang.Integer"
                           xmlType="xsd:short" />
          </globalBindings
        </appinfo>
      </annotation>
      ...
    </schema>
  • 単純型定義を変更する場合: 名前付き単純型定義に適用される場合、javaType 要素は XML 単純型のすべてのインスタンスに生成されたクラスを変更します。javaType 要素を使用して単純型定義を変更する場合は、xmlType 属性を使用しないでください。

    例38.8「シンプルタイプをカスタマイズするためのバインディングファイル」 に、zipCode という名前の単純型の生成を変更する外部バインディングファイルを示します。

    例38.8 シンプルタイプをカスタマイズするためのバインディングファイル

    <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   jaxb:version="2.0">
      <jaxb:bindings wsdlLocation="widgets.wsdl">
        <jaxb:bindings node="xsd:simpleType[@name='zipCode']">
            <jaxb:javaType name="com.widgetVendor.widgetTypes.zipCodeType"
                           parseMethod="com.widgetVendor.widgetTypes.support.parseZipCode"
                           printMethod="com.widgetVendor.widgetTypes.support.printZipCode" />
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>
  • 複合型定義の要素または属性を変更する場合: javaType は、JAXB プロパティーのカスタマイズの一部として追加することで、複合型定義の個々の部分に適用できます。javaType 要素は、プロパティーの baseType 要素に子として配置されます。javaType 要素を使用して複合型定義の特定の部分を変更する場合、xmlType 属性を使用しないでください。

    例38.9「複合型の要素をカスタマイズするためのバインディングファイル」 は、複合型の要素を変更するバインディングファイルを示しています。

    例38.9 複合型の要素をカスタマイズするためのバインディングファイル

    <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   jaxb:version="2.0">
      <jaxb:bindings schemaLocation="enumMap.xsd">
        <jaxb:bindings node="xsd:ComplexType[@name='widgetOrderInfo']">
          <jaxb:bindings node="xsd:element[@name='cost']">
            <jaxb:property>
              <jaxb:baseType>
                <jaxb:javaType name="com.widgetVendor.widgetTypes.costType"
                                parseMethod="parseCost"
                                printMethod="printCost" >
              </jaxb:baseType>
            </jaxb:property>
          </jaxb:bindings>
        </jaxb:bindings>
      </jaxb:bindings>
    <jaxb:bindings>

    baseType 要素の使用に関する詳細は、「要素または属性の基本タイプの指定」 を参照してください。

コンバーターの指定

Apache CXF は、XML スキーマのプリミティブ型をランダムな Java クラスに変換できません。javaType 要素を使用して XML スキーマプリミティブ型のマッピングをカスタマイズする場合、コードジェネレーターは、カスタマイズされた XML スキーマプリミティブ型をマーシャリングおよびアンマーシャリングするために使用されるアダプタークラスを作成します。サンプルのアダプタークラスを 例38.10「JAXB アダプタークラス」 に示します。

例38.10 JAXB アダプタークラス

public class Adapter1 extends XmlAdapter<String, javaType>
{
  public javaType unmarshal(String value)
  {
    return(parseMethod(value));
  }

  public String marshal(javaType value)
  {
    return(printMethod(value));
  }
}

parseMethod および printMethod は、対応する parseMethod 属性および printMethod 属性の値に置き換えてください。値は、有効な Java メソッドを識別する必要があります。メソッドの名前は、次の 2 つの方法のいずれかで指定できます。

  • packagename.ClassName.methodName の形式の完全修飾 Java メソッド名。
  • methodName の形式の単純なメソッド名

    簡単なメソッド名のみを指定すると、コードジェネレーターは、javaType 要素の name 属性で指定されたクラスにメソッドが存在すると想定します。

重要

コードジェネレーターは、解析メソッドまたは印刷メソッドを生成 しません。あなたはそれらを供給する責任があります。解析メソッドと印刷メソッドの開発については、「コンバーターの実装」 を参照してください。

parseMethod 属性の値が指定されていない場合、コードジェネレーターは、name 属性で指定された Java クラスに最初のパラメーターが Java String オブジェクトのコンストラクターがあると想定します。生成されたアダプターの unmarshal() メソッドは、想定されたコンストラクターを使用して Java オブジェクトに XML データを設定します。

printMethod 属性の値が指定されていない場合、コードジェネレーターは、name 属性で指定された Java クラスに toString() メソッドがあると想定します。生成されたアダプターの marshal() メソッドは、想定された toString() メソッドを使用して Java オブジェクトを XML データに変換します。

javaType 要素の name 属性が Java プリミティブ型または Java プリミティブのラッパー型のいずれかを指定する場合、コードジェネレーターはデフォルトのコンバーターを使用します。デフォルトのコンバーターの詳細については、「デフォルトのプリミティブ型コンバーター」 を参照してください。

生成されるもの

「コンバーターの指定」 に記載のとおり、javaType カスタマイズ要素を使用すると、XML スキーマプリミティブ型の各カスタマイズに対してアダプタークラスの生成が 1 つトリガーされます。このアダプターの名前は、AdapterN のパターンを使用して順番に付けられます。2 つのプリミティブタイプのカスタマイズを指定する場合、コードジェネレーターは Adapter1Adapter2 の 2 つのアダプタークラスを作成します。

XML スキーマ構造用に生成されたコードは、影響を受ける XML スキーマ構造がグローバルに定義された要素であるか、複合型の一部として定義されているかによって異なります。

XML スキーマ構造がグローバルに定義された要素である場合、その型に対して生成されたオブジェクトファクトリーメソッドは、デフォルトのメソッドから次のように変更されます。

  • メソッドには @XmlJavaTypeAdapter アノテーションが付けられます。

    アノテーションは、この要素のインスタンスを処理するときに使用するアダプタークラスをランタイムに指示します。アダプタークラスはクラスオブジェクトとして指定されます。

  • デフォルトの型は、javaType 要素の name 属性で指定されたクラスに置き換えられます。

例38.11「グローバル要素のカスタマイズされたオブジェクトファクトリーメソッド」 は、例38.7「グローバルプリミティブ型のカスタマイズ」 に示すカスタマイズの影響を受ける要素のオブジェクトファクトリーメソッドを示します。

例38.11 グローバル要素のカスタマイズされたオブジェクトファクトリーメソッド

 @XmlElementDecl(namespace = "http://widgetVendor.com/types/widgetTypes", name = "shorty")
 @XmlJavaTypeAdapter(org.w3._2001.xmlschema.Adapter1.class)
 public JAXBElement<Integer> createShorty(Integer value) {
     return new JAXBElement<Integer>(_Shorty_QNAME, Integer.class, null, value);
 }

XML スキーマ構造が複合型の一部として定義されている場合、生成された Java プロパティーは次のように変更されます。

  • プロパティーには @XmlJavaTypeAdapter アノテーションが付けられます。

    アノテーションは、この要素のインスタンスを処理するときに使用するアダプタークラスをランタイムに指示します。アダプタークラスはクラスオブジェクトとして指定されます。

  • プロパティーの @XmlElement には、type プロパティーが含まれています。

    type プロパティーの値は、生成されるオブジェクトのデフォルトベース型を表すクラスオブジェクトです。XML スキーマプリミティブ型の場合、クラスは String になります。

  • プロパティーには @XmlSchemaType アノテーションが付けられます。

    注釈は、設定の XML スキーマプリミティブ型を識別します。

  • デフォルトの型は、javaType 要素の name 属性で指定されたクラスに置き換えられます。

例38.12「カスタマイズされた複合タイプ」 は、例38.7「グローバルプリミティブ型のカスタマイズ」 に示すカスタマイズの影響を受ける要素のオブジェクトファクトリーメソッドを示します。

例38.12 カスタマイズされた複合タイプ

public class NumInventory {

    @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1.class) @XmlSchemaType(name = "short") protected Integer numLeft;
    @XmlElement(required = true)
    protected String size;

    public Integer getNumLeft() {
        return numLeft;
    }

    public void setNumLeft(Integer value) {
        this.numLeft = value;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String value) {
        this.size = value;
    }

}

コンバーターの実装

parseMethod 属性と printMethod 属性で指定されたメソッドを呼び出す必要があることを除き、Apache CXF ランタイムは、XML プリミティブ型と javaType 要素によって指定された Java クラス間の変換方法を認識しません。ランタイムが呼び出すメソッドの実装を提供するのはあなたの責任です。実装されたメソッドは、XML プリミティブ型の字句構造を処理できる必要があります。

データ変換メソッドの実装を簡素化するために、Apache CXF は javax.xml.bind.DatatypeConverter クラスを提供します。このクラスは、すべての XML スキーマプリミティブ型を解析および出力するためのメソッドを提供します。解析メソッドは XML データの文字列表現を取り、表34.1「XML スキーマのプリミティブ型から Java ネイティブ型へのマッピング」 で定義されたデフォルトタイプのインスタンスを返します。print メソッドはデフォルトタイプのインスタンスを取り、XML データの文字列表現を返します。

DatatypeConverter クラスの Java ドキュメントは、https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/DatatypeConverter.html にあります。

デフォルトのプリミティブ型コンバーター

Java プリミティブ型、または Java プリミティブ型のラッパークラスのいずれかを javaType 要素の name 属性で指定する場合には、parseMethod 属性または printMethod 属性の値を指定する必要はありません。値が指定されていない場合、Apache CXF ランタイムはデフォルトのコンバーターを置き換えます。

デフォルトのデータコンバーターは JAXB DatatypeConverter クラスを使用して XML データを解析します。デフォルトのコンバーターは、変換を機能させるために必要な型キャストも提供します。