JAX-WS项目调用Servlet报错:XML类型名称重复问题排查
我之前在搭建JAX-WS项目时也碰到过一模一样的问题——用命令行生成HelloService后,带?wsdl的URL能正常输出WSDL,但调用Servlet时直接炸出javax.xml.ws.WebServiceException,追根溯源就是JAXB的XML类型重复冲突,比如sayHello、sayHelloResponse这些类型同时出现在soap.endpoints.soap和soap.endpoints.soap.jaxws_asm两个包里,导致类加载冲突。下面给你几个亲测有效的解决办法:
清理重复生成的JAXB类
大概率是你重复执行了命令行生成指令(比如wsimport),或者生成路径配置有误,导致自动在jaxws_asm子包下又生成了一套和主包完全重复的JAXB类。你需要:- 找到项目里的
soap.endpoints.soap.jaxws_asm包,直接删除这个包下所有自动生成的类; - 检查你的生成命令,确保指定的源码生成路径是正确的,避免在嵌套包结构里重复生成。比如如果用
wsimport -s src/main/java http://localhost:8080/HelloService?wsdl,确认-s指向的目录不会生成多余的子包。
- 找到项目里的
显式指定JAXB命名空间与类型名称
如果删除重复类后还是有问题,或者你需要保留不同包的类,可以通过注解强制指定唯一的XML类型名称和命名空间,从根源避免冲突:
在你的WebService接口/实现类上,给方法添加明确的注解:@WebService(targetNamespace = "http://soap.endpoints/") public interface HelloService { @WebMethod(operationName = "sayHello") @WebResult(name = "sayHelloResponse") String sayHello(@WebParam(name = "name") String name); }要是手动编写JAXB实体类,也可以用
@XmlType指定唯一标识:@XmlType(name = "SayHelloRequest", namespace = "http://soap.endpoints/") public class SayHelloRequest { // 类内容 }调整WildFly的JAXB类加载配置
WildFly自带了JAXB实现,有时候服务器端的类加载优先级会和项目里的类冲突。你可以在项目的WEB-INF/jboss-deployment-structure.xml中添加配置,明确依赖关系:<jboss-deployment-structure> <deployment> <exclusions> <module name="javax.xml.bind.api" /> <module name="com.sun.xml.bind" /> </exclusions> <dependencies> <module name="javax.xml.bind.api" export="true" /> </dependencies> </deployment> </jboss-deployment-structure>这个配置能避免服务器端的JAXB实现干扰项目中的类。
彻底清理并重新部署
做完上面的修改后,一定要:- 在Eclipse里执行
Project -> Clean...清理项目缓存; - 重新执行构建(如果用Maven/Gradle的话);
- 重新部署到WildFly,确保旧的冲突类文件被完全替换。
- 在Eclipse里执行
按照这些步骤操作后,应该就能解决那个XML类型重复导致的WebServiceException了。
内容的提问来源于stack exchange,提问作者Alexander Mladzhov

