将对象编组为枚举类型时不调用 JAXB XmlJavaTypeAdapter

发布于 2024-10-24 02:47:19 字数 8821 浏览 2 评论 0原文

我正在使用 CXF 将我的 Web 应用程序转换为 Web 服务。我的 Web 应用程序构建了作为枚举工作的类。示例:

package test.javabean;
import java.util.HashMap;
import java.util.Map;

public class GlassType {

private static Map<String, GlassType> glasses = new HashMap<String, GlassType>();

private final String id;

private final String desc;

private GlassType(String id, String desc) {
    this.id = id;
    this.desc = desc;
    glasses.put(id, this);
}

public static final GlassType RED = new GlassType("R", "Bloody Red");

public static final GlassType BLACK = new GlassType("B", "Pitch Black");

public static final GlassType WHITE = new GlassType("W", "Blind White");

public static GlassType valueOf(final String id) {
    return glasses.get(id);
}

public String getDesc() {
    return desc;
}

public String getId() {
    return id;
}
}

由于我不想将 GlasssType 类更改为枚举类型,因此我创建了一个适配器以使此类在 WSDL 中显示为枚举。适配器类:

package test.adapters;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import test.javabean.GlassType;

public class GlassTypeEnumAdapter extends XmlAdapter<GlassEnum, GlassType> {

@Override
public GlassEnum marshal(GlassType arg0) throws Exception {
    System.out.println("MARSHALLING");
    return GlassEnum.valueOf(arg0.getId());
}

@Override
public GlassType unmarshal(GlassEnum arg0) throws Exception {
    System.out.println("UNMARSHALLING");
    return GlassType.valueOf(arg0.getId());
}

}

适配器使用 package-info.java 中提到的 XmlJavaTypeAdapter 与类 GlassType 进行映射:

@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters( { 
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(
        value = test.adapters.GlassTypeEnumAdapter.class, 
        type = test.javabean.GlassType.class) })
package test.javabean;

GlassEnum 类:

package test.adapters;

import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;

@XmlEnum(String.class)
@XmlType(name = "myEnum")
public enum GlassEnum {

RED("R"), BLACK("B"), WHITE("W");

private final String id;

private GlassEnum(String id) {
    this.id = id;
}

private GlassEnum() {
    this.id = "RED";
}

public String getId() {
    return id;
}
}

无论我在何处使用 GlassType,都会使用正确的类型 ="myEnum" 生成 WSDL。

问题:

当我的 Web 服务客户端发送 GlassType 的值时,适配器将调用 Marshall myEnum to GlassType。但是当我的 Web 服务使用 GlassType 回复客户端时,会抛出以下错误:

[3/20/11 20:43:48:078 CDT] 00000023 PhaseIntercep W org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging {http://webservices.test/}TestWebServiceImplService#{http:// webservices.test/}getTestResult 抛出异常,现在展开 org.apache.cxf.interceptor.Fault:编组错误:类 test.javabean.GlassType 或其任何超类在此上下文中都是已知的。 在 org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall (JAXBEncoderDecoder.java:256) 在 org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:169) 在 org.apache.cxf.interceptor.AbstractOutDataboundingInterceptor.writeParts(AbstractOutDataboundingInterceptor.java:110) 在org.apache.cxf.interceptor.BareOutInterceptor.handleMessage(BareOutInterceptor.java:68) 在org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255) 在org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77) 在org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255) 在 org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:113) 在 org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:97) 在 org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:461) 在 org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:188) 在org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:148) 在 org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:179) 在 org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:763) 在 org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:159) 在 com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1143) 在 com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:591) 在 com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:481) 在 com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3453) 在 com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:267) 在 com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:815) 在 com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1466) 在 com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:119) 在 com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458) 在 com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387) 在 com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267) 在 com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214) 在 com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113) 在 com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165) 在 com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217) 在 com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161) 在 com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136) 在 com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196) 在 com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751) 在 com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881) 在 com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1473) 引起原因:javax.xml.bind.MarshalException - 带有链接异常: [javax.xml.bind.JAXBException:此上下文已知类 test.javabean.GlassType 及其任何超类。] 在 com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:318) 在 com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244) 在 javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:74) 在 org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:540) 在org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:231) ... 36 更多 引起原因:javax.xml.bind.JAXBException:此上下文已知类 test.javabean.GlassType 及其任何超类。 在 com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:246) 在 com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:261) 在 com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:653) 在 com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:115) 在 com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340) 在 com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696) 在com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152) 在 com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340) 在 com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696) 在 com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:152) 在 com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:189) 在 com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:316) 在 com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:323) 在 com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:72) 在com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494) 在 com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315) ... 40 更多 引起原因:javax.xml.bind.JAXBException:此上下文已知类 test.javabean.GlassType 及其任何超类。 在 com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:594) 在 com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:648) ... 53 更多

我已经运行了几次测试,并注意到 Adapter 类没有被调用以进行 Unmarshalling GlassType。我在这里遗漏了什么吗?

替代解决方案也会有所帮助。

I am converting my web application to web servcies using CXF. My web application has classes build to work as enum. Example:

package test.javabean;
import java.util.HashMap;
import java.util.Map;

public class GlassType {

private static Map<String, GlassType> glasses = new HashMap<String, GlassType>();

private final String id;

private final String desc;

private GlassType(String id, String desc) {
    this.id = id;
    this.desc = desc;
    glasses.put(id, this);
}

public static final GlassType RED = new GlassType("R", "Bloody Red");

public static final GlassType BLACK = new GlassType("B", "Pitch Black");

public static final GlassType WHITE = new GlassType("W", "Blind White");

public static GlassType valueOf(final String id) {
    return glasses.get(id);
}

public String getDesc() {
    return desc;
}

public String getId() {
    return id;
}
}

As I don't want to change my GlasssType class to enum type, I made an adapter to make this class appear as enum in WSDL. Adapter Class:

package test.adapters;

import javax.xml.bind.annotation.adapters.XmlAdapter;
import test.javabean.GlassType;

public class GlassTypeEnumAdapter extends XmlAdapter<GlassEnum, GlassType> {

@Override
public GlassEnum marshal(GlassType arg0) throws Exception {
    System.out.println("MARSHALLING");
    return GlassEnum.valueOf(arg0.getId());
}

@Override
public GlassType unmarshal(GlassEnum arg0) throws Exception {
    System.out.println("UNMARSHALLING");
    return GlassType.valueOf(arg0.getId());
}

}

The adapter is mapped with class GlassType using XmlJavaTypeAdapter mentioned in package-info.java:

@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters( { 
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(
        value = test.adapters.GlassTypeEnumAdapter.class, 
        type = test.javabean.GlassType.class) })
package test.javabean;

The GlassEnum class:

package test.adapters;

import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;

@XmlEnum(String.class)
@XmlType(name = "myEnum")
public enum GlassEnum {

RED("R"), BLACK("B"), WHITE("W");

private final String id;

private GlassEnum(String id) {
    this.id = id;
}

private GlassEnum() {
    this.id = "RED";
}

public String getId() {
    return id;
}
}

The WSDL generated with correct type ="myEnum" whereever I have used GlassType.

PROBLEM:

When my web service client send the value for GlassType, the adapter is called to Marshall myEnum to GlassType. BUT when my web service replies back to client with GlassType following error is thrown:

[3/20/11 20:43:48:078 CDT] 00000023 PhaseIntercep W org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging Interceptor for {http://webservices.test/}TestWebServiceImplService#{http://webservices.test/}getTestResult has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Marshalling Error: class test.javabean.GlassType nor any of its super class is known to this context.
at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:256)
at org.apache.cxf.jaxb.io.DataWriterImpl.write(DataWriterImpl.java:169)
at org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor.writeParts(AbstractOutDatabindingInterceptor.java:110)
at org.apache.cxf.interceptor.BareOutInterceptor.handleMessage(BareOutInterceptor.java:68)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255)
at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:113)
at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:97)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:461)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:188)
at org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:148)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:179)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:159)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1143)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:591)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:481)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3453)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:267)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:815)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1466)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:119)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1473)
Caused by: javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class test.javabean.GlassType nor any of its super class is known to this context.]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:318)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:74)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:540)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:231)
... 36 more
Caused by: javax.xml.bind.JAXBException: class test.javabean.GlassType nor any of its super class is known to this context.
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:246)
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:261)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:653)
at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:115)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:152)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:189)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:316)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:323)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:72)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
... 40 more
Caused by: javax.xml.bind.JAXBException: class test.javabean.GlassType nor any of its super class is known to this context.
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:594)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:648)
... 53 more

I have run several tests and noticed that Adapter class is not getting called for Unmarshalling GlassType. Am I missing something in here?

An alternate solution would also be helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

扶醉桌前 2024-10-31 02:47:19

页面 使用 JAX-WS 和 JAXB 注释服务和类型的标准

这里显而易见的选择是 XML
适配器。然而,此时
编写 JAXB 似乎并不
正确处理 XML 适配器
用于枚举(无论你做什么
这样做,它仍然使用 xs:enumeration
生成模式中的方法)。所以
为了解决这个问题,我们必须治疗
这些值作为简单的字符串。

该页面创建于 2011 年 3 月 3 日,最后更新于 2011 年 5 月 16 日,因此在 JAXB 中使用带有枚举的 XmlJavaAdapter 似乎仍然无法正常工作。

The page Standards for Annotating Services and Types with JAX-WS and JAXB says

The obvious choice here is an XML
adapter. However, at the time of this
writing JAXB does not appear to
properly handle XML adapters that are
used on enums (regardless of what you
do, it still uses the xs:enumeration
approach in the generated schema). So
to get around this, we must treat
these values as simple strings.

The page was created on 03-Mar-2011 and last updated 16-May-2011, so it seems using XmlJavaAdapter with enums in JAXB is still not working correctly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文