将对象编组为枚举类型时不调用 JAXB XmlJavaTypeAdapter
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
页面 使用 JAX-WS 和 JAXB 注释服务和类型的标准说
该页面创建于 2011 年 3 月 3 日,最后更新于 2011 年 5 月 16 日,因此在 JAXB 中使用带有枚举的 XmlJavaAdapter 似乎仍然无法正常工作。
The page Standards for Annotating Services and Types with JAX-WS and JAXB says
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.