19

プロジェクトを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/16850

4

4 に答える 4

29

問題

Boolean代わりに取得している理由はbooleanminOccurs="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>

外部バインディング ファイルは-b、XJC のオプションを使用して指定されます。

xjc -b binding.xml my-schema.xsd

そのソリューションが機能しない理由

の問題を追跡するために、次のバグが開かれていoptionalProperty="primitive"ます。

回避策

JAXB でクラスを生成する方法が気に入らない場合は、自分でクラスを作成し、スキーマからクラス生成の一部として 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コール

-bXJC 呼び出しでフラグを使用して、binding.xmlファイルを指定します。

xjc -b binding.xml my-schema.xsd

アップデート

私が本当に望んでいたのは、読者の 1 人が jaxb で簡単に変更を行うことができる jaxb 開発チームのメンバーである可能性があるということでした。ユーザー archenroot は、jaxb issue 927 (926 の複製) に関するコメントで可能な解決策を提供しました。これにより、適切な人にとっては、jaxb を修正するのは簡単な仕事になると思います。

私はEclipseLink JAXB (MOXy)のリーダーです。私は、JAXB 参照実装を行っている同僚 (彼らは Oracle でも働いています) に連絡を取りました。以下は私が彼らから得た返事です:

トランクでテストしましたが、問題が存在します。コードを修正するのがどれほど簡単かを確認します。

うまくいけば、この問題の本当の修正を得ることができるでしょう.

于 2013-12-13T15:21:04.570 に答える
3

これを試して...

<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" 部分を削除しました。

于 2012-10-25T22:02:53.077 に答える
2

完成させるだけで

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)
于 2018-09-24T08:14:09.593 に答える
0

開発チームからの修正を待つのに飽きたので、袖をまくって自分でやりました。

これも問題である人々を助けるために、以下のコードを含めています。

免責事項:私のコードはおそらく問題を解決する最良の方法ではありませんが、私にとってはうまくいきます。

生成されたコードは次のようになります。

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"));
    }
于 2014-01-10T12:36:39.520 に答える