JWS的一次排错经历

笔者项目要用到webservice,以往都是直接用cxf或者axis,来发布和动态的生成客户端,去调用,仅仅会用。作为一个骨灰级的程序猿,笔者想一探webservice的本身,但是,出师未捷身先死,第一步,就卡主了,因为照着网上的教程,笔者碰到一个错误,而且几乎无从下手。


1.描述惨案的发生过程

1.1 编写并发布服务端

接口:IHelloWorld
package server;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface IHelloWorld {

	@WebMethod
	public String sayHello(String name);
}

实现类:HelloWorldImpl
package server;

import javax.jws.WebService;

@WebService
public class HelloWorldImpl implements IHelloWorld {

	@Override
	public String sayHello(String name) {
		return "hello [" + name + "]";
	}

}
服务端发布类:ServerPublish
package server;

import javax.xml.ws.Endpoint;

public class ServerPublish {

	public static void main(String[] args) {
		Endpoint.publish("http://192.168.8.101:9001/helloworld", new HelloWorldImpl());
	}
}

1.2测试发布情况

在浏览器中输入:http://192.168.8.101:9001/helloworld?wsdl  就可以看到wsdl描述文件了

1.3自动生成客户端代码

wsimport.exe -keep http://192.168.8.101:9001/helloworld?wsdl

然后在笔者的test目录下,可以看到新生成了一个server目录,里面是自动生成的.class和.java文件

1.4把自动生成的代码集成到我自己的工程中

然后,"理所当然"的,笔者,在自己工程下建立了一个package:client.error
然后,手动的把之前server目录下的.java文件,拷贝到,client.error包下,然后打开每个类,修正其中的package的错误
这一切看来似乎都理所当然。

1.5 编写客户端测试类

TestClient:
package client.error;

public class TestClient {
	public static void main(String[] args) {
		System.out.println(new HelloWorldImplService().getHelloWorldImplPort().sayHello("robin"));
	}
}

然后,运行,得到了错误的结果:
Exception in thread "main" com.sun.xml.internal.ws.spi.db.DatabindingException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
两个类具有相同的 XML 类型名称 "{http://server/}sayHello"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。
	this problem is related to the following location:
		at client.error.SayHello
		at public client.error.SayHello client.error.ObjectFactory.createSayHello()
		at client.error.ObjectFactory
	this problem is related to the following location:
		at server.SayHello
两个类具有相同的 XML 类型名称 "{http://server/}sayHelloResponse"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。
	this problem is related to the following location:
		at client.error.SayHelloResponse
		at public client.error.SayHelloResponse client.error.ObjectFactory.createSayHelloResponse()
		at client.error.ObjectFactory
	this problem is related to the following location:
		at server.SayHelloResponse

	at com.sun.xml.internal.ws.db.glassfish.JAXBRIContextFactory.newContext(JAXBRIContextFactory.java:90)
	at com.sun.xml.internal.ws.spi.db.BindingContextFactory.create(BindingContextFactory.java:167)
	at com.sun.xml.internal.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:203)
	at com.sun.xml.internal.ws.model.AbstractSEIModelImpl$1.run(AbstractSEIModelImpl.java:176)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.xml.internal.ws.model.AbstractSEIModelImpl.createJAXBContext(AbstractSEIModelImpl.java:176)
	at com.sun.xml.internal.ws.model.AbstractSEIModelImpl.postProcess(AbstractSEIModelImpl.java:95)
	at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:309)
	at com.sun.xml.internal.ws.db.DatabindingImpl.<init>(DatabindingImpl.java:85)
	at com.sun.xml.internal.ws.db.DatabindingProviderImpl.create(DatabindingProviderImpl.java:59)
	at com.sun.xml.internal.ws.db.DatabindingProviderImpl.create(DatabindingProviderImpl.java:43)
	at com.sun.xml.internal.ws.db.DatabindingFactoryImpl.createRuntime(DatabindingFactoryImpl.java:105)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.buildRuntimeModel(WSServiceDelegate.java:875)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.createSEIPortInfo(WSServiceDelegate.java:892)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.addSEI(WSServiceDelegate.java:855)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:435)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:404)
	at com.sun.xml.internal.ws.client.WSServiceDelegate.getPort(WSServiceDelegate.java:386)
	at javax.xml.ws.Service.getPort(Service.java:119)
	at client.error.HelloWorldImplService.getHelloWorldImplPort(HelloWorldImplService.java:72)
	at client.error.TestClient.main(TestClient.java:5)
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
两个类具有相同的 XML 类型名称 "{http://server/}sayHello"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。
	this problem is related to the following location:
		at client.error.SayHello
		at public client.error.SayHello client.error.ObjectFactory.createSayHello()
		at client.error.ObjectFactory
	this problem is related to the following location:
		at server.SayHello
两个类具有相同的 XML 类型名称 "{http://server/}sayHelloResponse"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。
	this problem is related to the following location:
		at client.error.SayHelloResponse
		at public client.error.SayHelloResponse client.error.ObjectFactory.createSayHelloResponse()
		at client.error.ObjectFactory
	this problem is related to the following location:
		at server.SayHelloResponse

	at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:445)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
	at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
	at com.sun.xml.internal.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:152)
	at com.sun.xml.internal.bind.api.JAXBRIContext.newInstance(JAXBRIContext.java:96)
	at com.sun.xml.internal.ws.developer.JAXBContextFactory$1.createJAXBContext(JAXBContextFactory.java:98)
	at com.sun.xml.internal.ws.db.glassfish.JAXBRIContextFactory.newContext(JAXBRIContextFactory.java:79)
	... 20 more


ok,拿到这个异常信息,笔者是一头雾水,网上百度了一番,也没有找到直接的解决办法

2.解决问题


某一个时刻,重新回顾异常" 两个类具有相同的 XML 类型名称 "{http://server/}sayHello"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。"
莫名,笔者感觉,可以试由于路径的问题,因为笔者在1.4中,修改了包名,而自动生成的代码中,或许有引用的时候,写的是 包名.类名 的方式,这样,就会使得路径不正确。
基于这一灵感,笔者去做了一些实验。于是修改步骤 1.3和1.4

2.3 动态生成客户端代码,并指定包名

wsimport -keep -p client.right http://192.168.8.101:9001/helloworld?wsdl

2.4 导入到工程

保证工程中的包名也是 client.right

然后,同样的和之前的1.5一样,运行测试客户端,得到正确的输出结果。

3.回顾

回顾之前的做法,
最开始,笔者基本是全部找网上搜到的教程来做的,可就算照做,还是出现了问题,而且难以解决,问题在于
1.wsimport的命令笔者没有理解,知其然不知其所以然
2.对自动生成的代码过于信赖,并没有去分析源码

对于wsimport其实只要-help就能很详细的看到其使用方法
-keep 会同时生成.class和.java
当目标的地址的webservice,发布的方法很多,可能要想办法将.java和.class分开,否则,手动导入到自己工程的时候,也会不小心出错。

这个时候可以直接使用-s哦












你可能感兴趣的:(webservice,jws)