JAX-WS、@XmlJavaTypeAdapter和自定义枚举
我正在使用一个基于IDL定义生成代码的库。能够在各种语言(Java、C和C++)中使用公共枚举非常好,但是这些生成的枚举似乎不能很好地与JAX-WS配合使用 基本上,主枚举“super”类有两个成员:ordinal和name。它看起来与此类似(注意:这是在第三方库中,不支持JavaBean): 因此,在基于IDL定义生成的代码中,看起来与此类似(以Day为例——但实际上,我有大约50个扩展CustomEnum的“enum”,因此我希望有一个解决方案,防止我周围有多个enum副本,例如IDL生成的类型和java.lang.enum): 注意,我也不想弄乱/重新排列/注释这个类,因为它是由代码生成的 所以,现在我想做的是能够在JAX-WS@WebMethod中将这个“Day”枚举用作@WebParam。下面是一个非常简单的示例,说明了我希望能够做什么:JAX-WS、@XmlJavaTypeAdapter和自定义枚举,java,soap,enums,jaxb,jax-ws,Java,Soap,Enums,Jaxb,Jax Ws,我正在使用一个基于IDL定义生成代码的库。能够在各种语言(Java、C和C++)中使用公共枚举非常好,但是这些生成的枚举似乎不能很好地与JAX-WS配合使用 基本上,主枚举“super”类有两个成员:ordinal和name。它看起来与此类似(注意:这是在第三方库中,不支持JavaBean): 因此,在基于IDL定义生成的代码中,看起来与此类似(以Day为例——但实际上,我有大约50个扩展CustomEnum的“enum”,因此我希望有一个解决方案,防止我周围有多个enum副本,例如IDL生成的
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@WebService
public class EnumEndpoint {
@WebMethod
public boolean callEndpoint(
@XmlJavaTypeAdapter(CustomEnumAdapter.class) Day day) {
System.out.println(day.ordinal() + " " + day.name());
return false;
}
}
我希望通过这样编写一个XmlJavaTypeAdapter:
import java.lang.reflect.Type;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CustomEnumAdapter extends XmlAdapter<CustomEnum, EnumBean>
implements Type {
@Override
public EnumBean unmarshal(CustomEnum v) throws Exception {
EnumBean mine = new EnumBean(v.ordinal(), v.name());
return mine;
}
@Override
public CustomEnum marshal(EnumBean v) throws Exception {
CustomEnum customEnum = new CustomEnum(v.getOrdinal(),v.getName());
return customEnum;
}
}
但当我像这样声明服务器端点时:
import javax.xml.ws.Endpoint;
public class Server {
/**
* @param args
*/
public static void main(String[] args) {
Endpoint.publish("http://0.0.0.0:7979/enum", new EnumEndpoint());
}
}
我得到这个错误:
Jun 10, 2012 3:29:21 PM com.sun.xml.internal.ws.model.RuntimeModeler getRequestWrapperClass
INFO: Dynamically creating request wrapper Class test.jaxws.CallEndpoint
Exception in thread "main" javax.xml.ws.WebServiceException: java.lang.IllegalArgumentException: value class test.CustomEnumAdapter
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createRequestWrapperBean(WrapperBeanGenerator.java:249)
at com.sun.xml.internal.ws.model.RuntimeModeler.getRequestWrapperClass(RuntimeModeler.java:280)
at com.sun.xml.internal.ws.model.RuntimeModeler.processDocWrappedMethod(RuntimeModeler.java:674)
at com.sun.xml.internal.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:612)
at com.sun.xml.internal.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:401)
at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:240)
at com.sun.xml.internal.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:312)
at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:178)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:456)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:475)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:102)
at javax.xml.ws.Endpoint.publish(Endpoint.java:170)
at test.Server.main(Server.java:11)
Caused by: java.lang.IllegalArgumentException: value class test.CustomEnumAdapter
at com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter.newConstItem(ClassWriter.java:893)
at com.sun.xml.internal.ws.org.objectweb.asm.AnnotationWriter.visit(AnnotationWriter.java:185)
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createBeanImage(WrapperBeanGenerator.java:111)
at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createRequestWrapperBean(WrapperBeanGenerator.java:245)
... 14 more
我错过了什么?我试图直接使用'Day',但由于它没有默认构造函数,并且对get/set不友好,所以也不起作用。有什么提示吗?听起来它在运行时失败了,因为webmethod参数上有@XmlJavaTypeAdapter注释-如何将请求参数
Day
和布尔响应包装在请求包装器中的包装消息类型中,只需将其声明为@XmlRootElement
,并声明您的适配器@XmlJavaTypeAdapter(CustomEnumAdapter.class)
。这样,@Webservice声明就没有@XmlJavaTypeAdapter注释。EnumBean
如果EnumBean
是经过调整的类,那么它需要有一个默认构造函数
package forum10972195;
public class EnumBean {
int ordinal;
String name;
public EnumBean() {
}
public EnumBean(int ordinal, String name) {
this.ordinal = ordinal;
this.name = name;
}
public int getOrdinal() {
return ordinal;
}
public void setOrdinal(int ordinal) {
this.ordinal = ordinal;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
CustomEnumAdapter
此外,在扩展XmlAdapter
时,修改后的类应该作为第一个参数出现。由于要映射到的参数类型为Day
,因此需要将XmlAdapter
指定为绑定类型
package forum10972195;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CustomEnumAdapter extends XmlAdapter<EnumBean, Day> {
@Override
public EnumBean marshal(Day v) throws Exception {
EnumBean mine = new EnumBean(v.ordinal(), v.name());
return mine;
}
@Override
public Day unmarshal(EnumBean v) throws Exception {
Day day = new Day(v.getOrdinal(),v.getName());
return day;
}
}
用于UM10972195的包;
导入javax.xml.bind.annotation.adapters.XmlAdapter;
公共类CustomEnumAdapter扩展了XmlAdapter{
@凌驾
公共EnumBean封送处理(第五天)引发异常{
EnumBean mine=新的EnumBean(v.ordinal(),v.name());
回采;
}
@凌驾
公共日解组(EnumBean v)引发异常{
Day Day=新的一天(v.getOrdinal(),v.getName());
回归日;
}
}
测试客户端 通过我建议的更改,我在WebLogic 12.1.1中运行了您的服务,通过内置测试客户端,我得到了以下结果: 服务请求
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header />
<env:Body>
<callEndpoint xmlns="http://forum10972195/">
<!--Optional:-->
<arg0 xmlns="">
<!--Optional:-->
<name>string</name>
<ordinal>3</ordinal>
</arg0>
</callEndpoint>
</env:Body>
</env:Envelope>
一串
3.
服务响应
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns0:callEndpointResponse xmlns:ns0="http://forum10972195/">
<return>false</return>
</ns0:callEndpointResponse>
</S:Body>
</S:Envelope>
假的
我有点明白你的意思。。。所以XmlJavaTypeAdapter不能直接在WebMethod上工作?您可以在问题中给出的WebMethod的参数上使用@XmlJavaTypeAdapter
。我的答案()是否符合您的要求?如果没有,请让我知道我可以进一步帮助。我是EclipseLink JAXB(MOXy)的负责人,希望我能帮助您找到一个有效的解决方案。很抱歉,我已经离开办公桌两天了。今晚我将仔细研究你的解决方案。非常感谢你!
package forum10972195;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CustomEnumAdapter extends XmlAdapter<EnumBean, Day> {
@Override
public EnumBean marshal(Day v) throws Exception {
EnumBean mine = new EnumBean(v.ordinal(), v.name());
return mine;
}
@Override
public Day unmarshal(EnumBean v) throws Exception {
Day day = new Day(v.getOrdinal(),v.getName());
return day;
}
}
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header />
<env:Body>
<callEndpoint xmlns="http://forum10972195/">
<!--Optional:-->
<arg0 xmlns="">
<!--Optional:-->
<name>string</name>
<ordinal>3</ordinal>
</arg0>
</callEndpoint>
</env:Body>
</env:Envelope>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns0:callEndpointResponse xmlns:ns0="http://forum10972195/">
<return>false</return>
</ns0:callEndpointResponse>
</S:Body>
</S:Envelope>