2

私は jaxb テクノロジの金融セクター プロジェクトに取り組んでいます。Web サービス消費部分を開発し、クライアント エンドから報告された問題に行き詰まりました。次のように、日付型の Bean クラスに 2 つのフィールドがあります。

 @XmlElement(name = "abc")
    @XmlSchemaType(name = "date")
    private Date abc;

    @XmlElement(name = "qwe")
    @XmlSchemaType(name = "date")
    private Date qwe;

これらのフィールドにデータがない場合、例外が発生します。また、これらのフィールドは必須ではなく、注釈タグに従ってグレゴリオ暦に従って yyyy-mm-dd で日付を取得します。SOAP UI を使用してローカル エンドでテストを行ったときの要求

            </data>
               <!--Optional:-->
               <abc></qwe>
               <!--Optional:-->
               <qwe></qwe>
            </data>


Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[abc-->abc/text()]] with descriptor [XMLDescriptor(fully qualified package name --> [])], could not be converted to [class java.util.Calendar].

これらのフィールドの両方に同じことが当てはまり、日付が期待される形式でのみ入力されている場合にうまく機能します。

Bean クラス自体で例外が発生し、サービス層にさえ到達しないため、タグまたはその他の手段を使用してこの問題を適切に処理する方法がわかりません。

問題を解決するための提案は非常に重要です。

ありがとう。

4

1 に答える 1

0

基本問題

Stringはその型の有効な値ではありませんxsd:date。XML スキーマで有効にするには、オプションの要素を存在しないノードとして表す必要があります。


根本的な問題があなたに影響を与えている理由

すべての JAXB 実装は、空Stringが の有効な値ではないことを認識しますxsd:date。のインスタンスに報告することでこれを行いますValidationEventHandler。これは、次のようにして自分で確認できます。

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setEventHandler(new ValidationEventHandler() {

        @Override
        public boolean handleEvent(ValidationEvent event) {
            System.out.println(event);
            return true;
        }
    });

使用している JAX-WS の実装は、EclipseLink MOXyを JAXB プロバイダーとして活用します。また、MOXy を使用しているバージョンでは、参照実装のようValidationEventに重大度ERRORが検出されると、デフォルトで例外がスローされます。FATAL_ERRORこれは、次のバグで修正されています。


回避策

JAXB API を直接使用している場合は、単純にデフォルトをオーバーライドできますValidationEventHandler。JAX-WS 環境では、XmlAdapterを使用してカスタム変換ロジックを提供できます。を活用して、XmlAdapterとの間の変換の処理方法をオーバーライドしますDate

XmlAdapter (日付アダプター)

import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date>{

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date unmarshal(String v) throws Exception {
        if(v.length() == 0) {
            return null;
        }
        return dateFormat.parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        if(null == v) {
            return null;
        }
        return dateFormat.format(v);
    }

}

Java モデル (ルート)

は注釈XmlAdapterを使用して参照されます。@XmlJavaTypeAdapterこれXmlAdapterを のすべてのインスタンスに適用する場合はDate、パッケージ レベルで登録できます ( http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.htmlを参照)。

import java.util.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlSchemaType(name = "date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date abc;

    @XmlSchemaType(name="date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date qwe;

}

デモコード

以下は、すべてが機能することを確認するために実行できるスタンドアロンの例です。

jaxb.properties

jaxb.propetiesMOXy を JAXB プロバイダーとして使用するスタンドアロンの例では、次のエントリを使用して、ドメイン モデルと同じパッケージで 呼び出されるファイルを含める必要があります( http://blog.bdoughan.com/2011/05/specifying-eclipselinkを参照)。 -moxy-as-your.html )。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

入力.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <abc></abc>
    <qwe>2013-09-05</qwe>
</root>

デモ

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum18617998/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

出力

マーシャリングされた XML では、Datenull だったフィールドが存在しない要素としてマーシャリングされていることに注意してください ( http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.htmlを参照)。

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <qwe>2013-09-05</qwe>
</root>
于 2013-09-05T14:24:50.480 に答える