プロジェクトをJAXB1.0からJAXB2.1に移行していますが、データ型のマッピングに問題があります。
Ant xjcバインディングコンパイラを使用しており、(たとえば)xs:dateがJavaにマップされるようにグローバルバインディングを正常に構成しました。 util.Calendar。
ただし、Boolean
が必要なのに対し、boolean
を返す生成されたメソッドを取得しています。
複合型は次のとおりです。
<xs:element name="usage-auth-rate-charge">
<xs:complexType>
<xs:sequence>
<xs:element name="service-id" type="xs:string"/>
<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
そして、生成されたクラスは次のようになります。
public class UsageAuthRateCharge {
........
public Boolean isPricepointCustomFieldsRequired() {
return pricepointCustomFieldsRequired;
}
問題は、ボクシングは機能しますが、提供されたXMLにpricepoint_custom_fields_required
の値が含まれていない場合、クラスのブールフィールドがfalseではなくnullになることです。したがって、次のようなことをするとNullPointerExceptions
methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());
nullを除いて、渡されたブール値をボックス化解除しようとするためです。
スキーマを変更できず、すべてのクライアントコードを調整してnullチェックを実行できません。
binding.xmlにoptionalProperty属性を次のように設定しました。
<globalBindings optionalProperty="primitive">
仕様では、「属性の値が「プリミティブ」の場合、JAXB1.0の場合と同じようにバインドされます」と記載されています。
しかし、これは明らかに起こっていません。
どうすればこの問題を解決できますか?
更新:
これはjaxb2.2.9で修正されました: https://Java.net/jira/browse/JAXB/fixforversion/1685
開発チームからの修正を待つのに飽きてしまったので、袖をまくり上げて自分でやりました。
これも問題となる人々を助けるために、以下のコードを含めています。
免責事項:私のコードはおそらく問題を解決するための最良の方法ではありませんが、それは私にとってはうまくいきます。
生成されたコードは次のようになります。
public boolean isPricepointCustomFieldsRequired() {
if (pricepointCustomFieldsRequired == null) {
return false;
} else {
return pricepointCustomFieldsRequired;
}
}
そして、変更は次のとおりです。
com.Sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty:createElementProperty、行〜358
行の後
types.addTo(prop);
次のコードを挿入します。
if (prop.isOptionalPrimitive() && getOptionalPropertyMode() == OptionalPropertyMode.PRIMITIVE &&
!prop.getTypes().isEmpty() && "boolean".equals(prop.getTypes().get(0).getTypeName().getLocalPart()) ) {
prop.defaultValue= CDefaultValue.create(CBuiltinLeafInfo.BOOLEAN, new XmlString("false"));
}
Boolean
の代わりにboolean
を取得する理由は、要素定義にminOccurs="0"
があるためです。存在しない要素にはnull
値が格納されます。
<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
解決策は、プリミティブ型をオプションの値に使用する必要があることを示す外部バインディングファイルである必要があります(JAXB 2.2仕様のセクション7.5.1を参照)。
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://Java.Sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings optionalProperty="primitive"/>
</jaxb:bindings>
外部バインディングファイルは、XJCで-b
オプションを使用して指定されます。
xjc -b binding.xml my-schema.xsd
optionalProperty="primitive"
の問題を追跡するために、次のバグが開かれています。
JAXBでクラスが生成される方法が気に入らない場合は、自分でクラスを作成し、それをスキーマの一部としてクラス生成に引き込むことができます。
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://Java.Sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="my-schema.xsd">
<jxb:bindings node="//xs:element[@name='usage-auth-rate-charge']/complexType">
<jxb:class ref="com.example.foo.UsageAuthRateCharge"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
UsageAuthRateCharge
必要に応じてメソッドを使用してこのクラスを作成します。
XJC呼び出し
XJC呼び出しで-b
フラグを使用して、binding.xml
ファイルを指定します
xjc -b binding.xml my-schema.xsd
私が本当に望んでいたのは、読者の1人がjaxbで簡単に変更を行えるjaxb開発チームのメンバーである可能性があるということでした。ユーザーarchenrootは、jaxb問題927(926の複製)に関するコメントで可能な解決策を提供しました。これにより、適切な人にとって、jaxbを修正するのは簡単な仕事になると思います。
私は EclipseLink JAXB(MOXy) リードです。 JAXBリファレンス実装を行っている同僚に連絡しました(彼らはOracleでも機能します)。以下は私が彼らから得た返事です:
トランクでテストしましたが、問題があります。コードをチェックして、修正がいかに簡単かを確認します。
うまくいけば、この問題の実際の修正を取得できるようになります。
これを試して...
<xs:element name="usage-auth-rate-charge">
<xs:complexType>
<xs:sequence>
<xs:element name="service-id" type="xs:string"/>
</xs:sequence>
<xs:attribute name="chosen" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
あなたがやっていたのとは正反対のことをする方法を探していたときに、あなたの質問を見つけました。プリミティブブール値として属性を持つコードのみを生成するブール属性がありました。 jaxbにこの属性をブールプリミティブではなくブールオブジェクトとして生成させるために、xsdの属性定義のuse = "required"部分を削除しました。
完成させるためだけに
type="xs:boolean" minOccurs="0" maxOccurs="1" == Boolean value (object)
type="xs:boolean" minOccurs="0" maxOccurs="1" nillable="true" == JAXBElement<Boolean> value (object)
type="xs:boolean" minOccurs="1" maxOccurs="1" == boolean value (primitive)
type="xs:boolean" minOccurs="1" maxOccurs="1" nillable="true" == Boolean value (object)