在执行 JAXB 解组时处理无效的枚举值 [英] Handling invalid enum values while doing JAXB Unmarshalling

查看:20
本文介绍了在执行 JAXB 解组时处理无效的枚举值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Jaxb 基于 XML 模式设置创建了一个 Enum 类.

My Jaxb has created a Enum class based on the XML schema set up.

**enum Fruit {
    APPLE,ORANGE;
}**

我正在使用 SOAP UI 来检查我的 Web 服务.因为它是一个自由形式的条目,如果我给一个错误的水果说 "Guva" 那么它不会抛出异常,而是在执行 UnMarshalling 后将其返回为 null.

I am using a SOAP UI to check my web service. Since it is a free form entry, if i give a wrong fruit say "Guva" then instead of throwing an exception it is returning it as null after doing the UnMarshalling.

我怎样才能避免这种情况?我应该使用自定义枚举类而不是 JAXB 生成的.请举一些例子.即

How can i avoid this? Should i use custom enum class instead of JAXB generated one. Please give some example. i.e.

问候sri

推荐答案

注意:我是EclipseLink JAXB (MOXy) 领导者和 JAXB (JSR-222) 专家组.

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

默认情况下,您的 JAXB (JSR-222) 实现不会因任何转换异常而失败.如果您使用 JAXB API 进行解组,那么您可以设置一个 ValidationEventHandler 来捕获任何问题.下面是一个例子.

By default your JAXB (JSR-222) implementation will not fail on any conversion exceptions. If you are using the JAXB APIs to do the unmarshalling then you can set a ValidationEventHandler to catch any problems. Below is an example.

package forum12147306;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    private int number;
    private Fruit fruit;

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public Fruit getFruit() {
        return fruit;
    }

    public void setFruit(Fruit fruit) {
        this.fruit = fruit;
    }

}

水果

package forum12147306;

public enum Fruit {

    APPLE, 
    ORANGE;

}

演示

package forum12147306;

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

public class Demo {

    private static final String XML = "<root><number>ABC</number><fruit>Guva</fruit></root>";
    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

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

            @Override
            public boolean handleEvent(ValidationEvent validationEvent) {
                 System.out.println(validationEvent.getMessage());
                 //validationEvent.getLinkedException().printStackTrace();
                 return true;
            }

        });

        Root root = (Root) unmarshaller.unmarshal(new StringReader(XML));
    }

}


JAXB 参考实现

不幸的是,JAXB RI 中似乎存在错误,因为无效枚举值的验证事件未通过.

Unfortunately there appears to be a bug in the JAXB RI as a validation event is not being through for the invalid enum value.

Not a number: ABC

解决方法

编写您自己的 XmlAdapter 来处理与 Fruit 枚举之间的转换:

Write your own XmlAdapter to handle to conversion to/from the Fruit enum:

水果适配器

package forum12147306;

import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class FruitAdapter extends XmlAdapter<String, Fruit> {

    @Override
    public String marshal(Fruit fruit) throws Exception {
        return fruit.name();
    }

    @Override
    public Fruit unmarshal(String string) throws Exception {
        try {
            return Fruit.valueOf(string);
        } catch(Exception e) {
            throw new JAXBException(e);
        }
    }

}

水果

使用 @XmlJavaTypeAdapter 注释将 XmlAdapterFruit 枚举关联.

Use the @XmlJavaTypeAdapter annotation to associate the XmlAdapter with the Fruit enumb.

package forum12147306;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(FruitAdapter.class)
public enum Fruit {

    APPLE, 
    ORANGE;

}

新输出

Not a number: ABC
javax.xml.bind.JAXBException
 - with linked exception:
[java.lang.IllegalArgumentException: No enum const class forum12147306.Fruit.Guva]


EclipseLink JAXB (MOXy)

使用 MOXy 会引发两个验证事件.要将 MOXy 指定为您的 JAXB 提供程序,请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html.

Using MOXy both validation events are thrown. To specify MOXy as your JAXB provider see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html.

Exception Description: The object [ABC], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[number-->number/text()]] with descriptor [XMLDescriptor(forum12147306.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "ABC"

Exception Description: No conversion value provided for the value [Guva] in field [fruit/text()].
Mapping: org.eclipse.persistence.oxm.mappings.XMLDirectMapping[fruit-->fruit/text()]
Descriptor: XMLDescriptor(forum12147306.Root --> [DatabaseTable(root)])

这篇关于在执行 JAXB 解组时处理无效的枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆