@WebService问题,请看CXF给出的HelloWorld的例子

68 views
Skip to first unread message

SkyTiger

unread,
Aug 23, 2007, 2:03:05 AM8/23/07
to cxf-zh
接口声明是这个样子:
@WebService
public interface HelloWorld {
String sayHi(String text);
}

按照这样的声明,最终的WSDL文件中的wsdl:port的名字应该是HelloWorld,因为缺省的情况下@WebService使用接口的名字
作为WSDL中名字,而客户端调用程序的代码缺很让人费解:
private static final QName PORT_NAME = new QName("http://
demo.huawei.com/", "HelloWorldPort");
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,
endpointAddress);

请注意这里是"HelloWorldPort";而按照JAX-WS的定义,PORT_NAME参数必须是WSDL中wsdl:port的名字,这个名
字是"HelloWorld",这个调用居然是成功的为什么?

如果修改一下:
@WebService(name="HelloWorldPort")
public interface HelloWorld {
String sayHi(String text);
}
这时生成的WSDL文件中的wsdl:port的名字应该是HelloWorldPort,而这时调用却是失败的。我不明白到底是CXF的问题还是
JAX-WS没有描述清楚?

如果我使用如下:
URL wsdlDeployURL = new URL("http://localhost:9000/HelloWorld?wsdl");
Service service = Service.create(wsdlDeployURL,SERVICE_NAME);
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,
endpointAddress);
service.addPort(null, SOAPBinding.SOAP11HTTP_BINDING,
endpointAddress);

永远都成功,这个容错的能力是CXF还是JAX-WS提供的?

JimMa

unread,
Aug 23, 2007, 4:12:30 AM8/23/07
to cxf-zh
按照JSR181规范, @WebSerice 中的name是wsdl:PortType的名字,@WebService中的portName是
wsdl:port的名字。
当interface HelloWorld的annotation @Websevice没有其他属性时
候,name,service,portName都取默认值:
name以class或者interface的simple name命名,映射为wsdl:portType名.
serciceName 以interface的simple name + "Service"作为wsdl:sercice的名字。
portName以@WebService.name + "Port" 作为wsdl:port的名字
所以生成client端的代码是没有错误的。

如果更改@WebService的name为HelloWorldPort, 对应的wsdl:portName名就会变为
HelloWorldPortPort。
生成的wsdl:service如下:
<wsdl:service name="HelloWorldService">
<wsdl:port name="HelloWorldPortPort"
binding="ns1:HelloWorldServiceSoapBinding">
<soap:address location="http://localhost:9090/hello"/>
</wsdl:port>
</wsdl:service>
在没有给定wsdl时,cxf 的service model 会build from class,当给定wsdl时候,servicemodel会
build from wsdl .
所以会产生不同的行为。这个容错能力应该是CXF提供的。

能否将出错的stack trace贴上来,我们一起来深入分析?

SkyTiger

unread,
Aug 23, 2007, 4:30:44 AM8/23/07
to cxf-zh
好像不是哦,看这个生成WSDL文件:
- <wsdl:portType name="HelloWorld">
- <wsdl:operation name="sayHi">
<wsdl:input message="ns1:sayHi" name="sayHi" />
<wsdl:output message="ns1:sayHiResponse" name="sayHiResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="HelloWorldSoapBinding" type="ns1:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/
soap/http" />
- <wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHi">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="sayHiResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="HelloWorld">
- <wsdl:port binding="ns1:HelloWorldSoapBinding"
name="HelloWorldImplPort">
<soap:address location="http://localhost:9000/HelloWorld" />
</wsdl:port>
</wsdl:service>

这里的PORTNAME是HelloWorldImplPort, 而PORTTYPE的NAME是HelloWorld
所以用private static final QName PORT_NAME = new QName("http://
demo.huawei.com/", "HelloWorldPort");这个PORT_NAME去调用应该不成功的,跟哪个也匹配不上,但是它却
是成功了!

如果修改一下:
@WebService(name="HelloWorldPort")
public interface HelloWorld {
String sayHi(String text);
}

生成的WSDL文件是这样的:
- <wsdl:portType name="HelloWorldPort">
- <wsdl:operation name="sayHi">
<wsdl:input message="ns1:sayHi" name="sayHi" />
<wsdl:output message="ns1:sayHiResponse" name="sayHiResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="HelloWorldSoapBinding"
type="ns1:HelloWorldPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/
soap/http" />
- <wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHi">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="sayHiResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="HelloWorld">
- <wsdl:port binding="ns1:HelloWorldSoapBinding"
name="HelloWorldImplPort">
<soap:address location="http://localhost:9000/HelloWorld" />
</wsdl:port>
</wsdl:service>
这样就是对的,portType name="HelloWorldPort" 而port
binding="ns1:HelloWorldSoapBinding" name="HelloWorldImplPort"

但是这样却调用不成功!why?

SkyTiger

unread,
Aug 23, 2007, 4:33:23 AM8/23/07
to cxf-zh
线程栈:

org.apache.cxf.interceptor.Fault: Could not send Message.
at
org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:
48)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:
207)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:254)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:205)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:
73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:
135)
at $Proxy12.sayHi(Unknown Source)
at com.huawei.demo.HelloServerClient.main(HelloServerClient.java:26)
Caused by: java.net.MalformedURLException
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:
732)
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:
722)
at
org.apache.cxf.transport.http.HTTPConduit.setupURL(HTTPConduit.java:
661)
at org.apache.cxf.transport.http.HTTPConduit.prepare(HTTPConduit.java:
467)
at
org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:
46)
... 7 more
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Could
not send Message.
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:
169)
at $Proxy12.sayHi(Unknown Source)
at com.huawei.demo.HelloServerClient.main(HelloServerClient.java:26)
Caused by: org.apache.cxf.interceptor.Fault: Could not send Message.
at
org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:
48)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:
207)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:254)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:205)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:
73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:
135)
... 2 more
Caused by: java.net.MalformedURLException
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:
732)
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:
722)
at
org.apache.cxf.transport.http.HTTPConduit.setupURL(HTTPConduit.java:
661)
at org.apache.cxf.transport.http.HTTPConduit.prepare(HTTPConduit.java:
467)
at
org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:
46)
... 7 more

JimMa

unread,
Aug 23, 2007, 5:33:23 AM8/23/07
to cxf-zh
你用的是CXF的最新版本吗?

@WebService(name="HelloWorldPort")
public interface HelloWorld {
String sayHi(String text);

}

我用最新版本为上面这个class生成的wsdl是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="HelloWorldService" targetNamespace="http://
test.org/" xmlns:ns1="http://test.org/" xmlns:xsd="http://www.w3.org/
2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://test.org/" attributeFormDefault="unqualified"
elementFormDefault="unqualified" targetNamespace="http://test.org/">
<xs:element name="sayHi" type="tns:sayHi"/>
<xs:element name="sayHiResponse" type="tns:sayHiResponse"/>
<xs:complexType name="sayHiResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHi">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHiResponse">
<wsdl:part name="result" element="ns1:sayHiResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHi">
<wsdl:part name="parameters" element="ns1:sayHi">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloWorldPort">
<wsdl:operation name="sayHi">
<wsdl:input name="sayHi" message="ns1:sayHi">
</wsdl:input>
<wsdl:output name="sayHiResponse" message="ns1:sayHiResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldServiceSoapBinding"


type="ns1:HelloWorldPort">
<soap:binding style="document" transport="http://
schemas.xmlsoap.org/soap/http"/>

<wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document"/>

<wsdl:input name="sayHi">
<soap:body use="literal"/>
</wsdl:input>

<wsdl:output name="sayHiResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name="HelloWorldService">
<wsdl:port name="HelloWorldPortPort"
binding="ns1:HelloWorldServiceSoapBinding">

<soap:address location="http://localhost:9090/hello"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


SkyTiger

unread,
Aug 23, 2007, 5:46:39 AM8/23/07
to cxf-zh
Apache CXF 2.0.1
JDK6

生成的东西和你的不同!

JimMa

unread,
Aug 23, 2007, 5:54:14 AM8/23/07
to cxf-zh
你pass给java2wsdl的是interface 还是impl class?

maomao

unread,
Aug 23, 2007, 5:55:39 AM8/23/07
to cxf-zh
从头到尾,我也没看到HelloWorldImpl 这个类阿,为什么wsdl里面有impl?
你肯定是搞错了,从头来一遍看看

mmao

fuhu...@gmail.com

unread,
Aug 23, 2007, 6:10:39 AM8/23/07
to cxf-zh
是通过HTTP浏览器的方式得到的WSDL文件 例如:http://localhost:9000/helloWorld?wsdl
不是用java2wsdl这个工具生成的
对于浏览器端得到的WSDL文件是CXF生成的吗?

> > 生成的东西和你的不同!- Hide quoted text -
>
> - Show quoted text -

SkyTiger

unread,
Aug 23, 2007, 6:13:53 AM8/23/07
to cxf-zh

有这个类啊:
@WebService(endpointInterface = "com.huawei.demo.HelloWorld",
serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld{
public String sayHi(String text) {
return "Hello " + text;
}
}


JimMa

unread,
Aug 23, 2007, 6:15:31 AM8/23/07
to cxf-zh
是CXF生成的,并且应该和java2wsdl生成的是一样的。

server启动的时候你publish的是哪个类?

fuhu...@gmail.com

unread,
Aug 23, 2007, 6:17:03 AM8/23/07
to cxf-zh
按照CXF网站上的user guide写的例子:
System.out.println("Starting Server");
HelloWorldImpl implementor = new HelloWorldImpl();
String address = "http://localhost:9000/helloWorld";
Endpoint.publish(address, implementor);

> > > - Show quoted text -- Hide quoted text -

maomao

unread,
Aug 23, 2007, 6:18:45 AM8/23/07
to cxf-zh
是的,都是cxf生产的, 而且用的是同一个代码, 只不过通过工具有额外的一些参数可以使用

mmao


On Aug 23, 6:10 pm, "fuhua0...@gmail.com" <fuhua0...@gmail.com> wrote:

SkyTiger

unread,
Aug 23, 2007, 6:24:07 AM8/23/07
to cxf-zh
能否告诉我,你们说的WSDL文件是如何生成的?

为什么我这里使用"http://localhost:9000/helloWorld?wsdl "生成的东西和你们说的不同?

按照JAX-WS的定义,PORT_NAME参数必须是WSDL中wsdl:port的名字,就是说
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING,
endpointAddress);

中的PORT_NAME应该匹配WSDL中的portType名字。

问题出在哪里?

maomao

unread,
Aug 23, 2007, 10:00:30 PM8/23/07
to cxf-zh
我用java2wsdl 工具试过了,没有发现任何问题,
Oh, 你是从url来实验的。 不过应该也是一样的。

port 和 portType是不同的东西,你为什么会认为是一个东西呢?
<portType name='hello'>
...
</portType>
<binding name="..." type="Hello">
...
<binding>
<service name='foo'>
<port name='bar' binding='...'/>
</service>

你是按照文档在做实验吗?
如果不是,我建议先看看文档 http://cwiki.apache.org/confluence/display/CXF20DOC/
如果是的话,请把你的实验环境,操作步骤,如何能重现你的问题,稍微描述的具体点,(e.g 1, 2,3)
要不,我们可能需要花很多时间,也不一定能解决你的问题

Willem Jiang

unread,
Aug 23, 2007, 10:21:10 PM8/23/07
to cxf...@googlegroups.com
CXF目前支持WSDL First 和 Code First [1]两种开发模式。

?wsdl 生成的wsdl是通过ServiceModle[2]生成出来的。而java2wsdl复用了CXF
注意一条很重要的INFO日志 "Create service from WSDL: ..." 或者是 "Create
sevice from class ..."。
这条日志来表明Service Model是通过WSDL创建还是通过Class信息创建的。

你所使用的HelloWorld例子中annotation没有WSDL文件,所以应该是通过
Refelction的方式创建的。

好现在回到前面的问题, 就是java2wsdl 和 ?wsdl生成出来的内容为何不同,这
和具体的参数设置以及传入的SEI以及缺省的命名方式有关。


由于你的hello world 使用的JAX-WS API, 你完全可以通过设置annotation来定制
serviceName和portName.

@WebService(name = "Hello", serviceName = "HelloService", portName =
"HelloPort",

endpointInterface = "com.huawei.demo.HelloWorld")

public class HelloWorldImpl implements HelloWorld{

......


[1]http://willem.bokeland.com/blog/794/3115/2006/12/10/108854
[2]http://willem.bokeland.com/blog/794/6089/2007/06/05/199825

JimMa

unread,
Aug 23, 2007, 10:22:07 PM8/23/07
to cxf-zh

1. 使用interface和impl class产生出来的wsdl是不一样的.和你产生不一样的wsdl是用interface产生的。

2. "按照JAX-WS定义PORT_NAME参数必须是WSDL中wsdl:port的名字",我没有在Jaxws中找到找到这个rule。

Service.addPort是为这个service再创建一个新的port ,这个方法的说明:
Creates a new port for the service. Ports created in this way
contain no WSDL port type information and can only be used for
creating Dispatchinstances.
整个链接给你参考:

http://java.sun.com/javase/6/docs/api/javax/xml/ws/Service.html#addPort(javax.xml.namespace.QName,%20java.lang.String,%20java.lang.String)

JimMa

unread,
Aug 24, 2007, 1:54:35 AM8/24/07
to cxf-zh
我用以下的client去测试了你说case,我没有重现这个问题:

QName serviceName = new QName("http://demo.huawei.com/",
"HelloWorld");
QName portName = new QName("http://demo.huawei.com/",
"HelloWorldPort");

Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING,
"http://localhost:9090/hello");
HelloWorld hello = service.getPort(portName,
HelloWorld.class);
String res = hello.sayHi("test");
System.out.println("---res--- " + res);

我的server是这样的:
HelloWorldImpl serviceImpl = new HelloWorldImpl();
EndpointImpl ep = new EndpointImpl(serviceImpl);
ep.publish("http://localhost:9090/hello");

我改变interface 的@WebService.name ,然后去publish,两次client 调用都成功。
你的server和我的client有什么不同?

SkyTiger

unread,
Aug 24, 2007, 8:18:49 AM8/24/07
to cxf-zh
我从客户端得到的WSDL中没有"HelloWorldPort"名字啊

仅仅有"HelloWorld" 制定Porttype的名字
还有就是"HelloWorldimplPort"指定port的名字
所以在客户端指定的"HelloWorldPort", CXF是如何准确映射到接口"HelloWorld" 上去的呢?

@WebService


public interface HelloWorld {
String sayHi(String text);
}

这个是CXF自己的例子,别跟我说为什么,我没有改任何东西!我只是无意中看了一下WSDL文件,和客户端的代码,发现这个问题!

SkyTiger

unread,
Aug 24, 2007, 8:19:49 AM8/24/07
to cxf-zh
看来我要问一下那个TOMZEK!

SkyTiger

unread,
Aug 24, 2007, 8:30:46 AM8/24/07
to cxf-zh

"Service.addPort是为这个service再创建一个新的port"? 就是说第一个参数的名字可以随便起喽?

但是不行哦,只能是"HelloWorldPort",其他的不灵哦!

为什么是"HelloWorldPort"? 后面的那个"port"是不是CXF自己加上去的?


On Aug 24, 7:22 am, JimMa <mail2ji...@gmail.com> wrote:
> 1. 使用interface和impl class产生出来的wsdl是不一样的.和你产生不一样的wsdl是用interface产生的。
>
> 2. "按照JAX-WS定义PORT_NAME参数必须是WSDL中wsdl:port的名字",我没有在Jaxws中找到找到这个rule。
>
> Service.addPort是为这个service再创建一个新的port ,这个方法的说明:
> Creates a new port for the service. Ports created in this way
> contain no WSDL port type information and can only be used for
> creating Dispatchinstances.
> 整个链接给你参考:
>

> http://java.sun.com/javase/6/docs/api/javax/xml/ws/Service.html#addPo...)

willem

unread,
Aug 24, 2007, 9:38:12 PM8/24/07
to cxf-zh
在JAXWS API中,对于Server端你可以通过调用 Endpoint.publish(address,
implementor)将服务发布到对应的地址上。

对于Client端来说,你可以通过WSDL,也可以通过Code First的方式来创建你想要
的Proxy(Port)。
如果你采用Code First编程模式,当你的SEI如果没有指定WSDL location以及
binding信息时,Service无法获知你的要创建的Port将使用什么样的address,使
用什么样的binding。
这时你就需要调用Service.addPort 来创建一个port name 和 binding id 以及
address的映射。。
如果你使用addPort API之后,你还需要通过调用 getPort(QName portName,
Class<T> type)来获取到Client的proxy
设想一下你如果调用 addPort之后,只是简单调用 getPort(QName protName) 是
获得不到正确的Port的。
要知道这时候你的Service还没获得到SEI的信息(Service可以通过SEI获得与
operation相关),因此无法Client端创建出真正的Proxy


如果想熟悉JAXWS API的话,建议你研究一下CXF的代码

1. JAXWS front end 的 CodeFirstTest 演示了如何在Code First编程模式下如何
使用Jaxws API
https://svn.apache.org/repos/asf/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/CodeFirstTest.java

2. ServiceImpl ,JAXWS Service API的具体实现,你可以看看addPort,
getPort等函数的具体实现
https://svn.apache.org/repos/asf/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ServiceImpl.java


Willem.

> > > 问题出在哪里?- Hide quoted text -

SkyTiger

unread,
Aug 25, 2007, 3:38:05 AM8/25/07
to cxf-zh
从客户的角度,我是从"http://localhost:9000/helloWorld?wsdl "拿到WSDL文件,
并且依据这个WSDL文件来编写客户端代码,我不关心服务器是怎么实现的!

从这个WSDL中,我看到的是porttype="HelloWorld"; port name 是"HelloWorldImplPort"!

我在创建客户端程序的时候是绝对不会构建一个"HelloWorldPort"这样名字的portname的,没有理由告诉我要去这么做!
我使用"HelloWorld"作为portname,但是调用失败,服务端告诉我要用"HelloWorldPort",这不和逻辑啊,哪里有这样的
描述说后面一定要加一个"port"?

willem

unread,
Aug 25, 2007, 5:32:03 AM8/25/07
to cxf-zh
我不知道你客户端的代码是什么样的, 是通过wsdl2java 生成的吗?
如果你是使用"http://localhost:9000/helloWorld?wsdl" 中的wsdl, 来生成Client
Artifacts的话,是不会用到addPort API的。
如果你是使用Service(URL,Qname serviceName), Serice.getPort(Qname portName) 来创
建Client的话,那你还是得自己弄清楚什么是WSDL中正确的portName。
CXF创建的Server之所以会使用 "HelloWorldImplPort" 作为portName,是因为你在SEI中没有明确制定
PortName,CXF使用缺省的命名方式给你创建了一个portName (implementor class name +
"Port")。

"勿在浮沙筑高台" , 你认为不合逻辑的问题,很多情况下是自己了解得太少了。

BTW,
如果你为运行上面的HelloWorld花费了很多时间,我建议你好好跑一下CXF Samples中的例子, 这些例子都是能正常工作的。

willem

unread,
Aug 25, 2007, 5:34:27 AM8/25/07
to cxf-zh

On 8月25日, 下午3时38分, SkyTiger <darktemplars...@gmail.com> wrote:

> 从客户的角度,我是从"http://localhost:9000/helloWorld?wsdl"拿到WSDL文件,
> 并且依据这个WSDL文件来编写客户端代码,我不关心服务器是怎么实现的!

请注意我给出的链接都是客户端的代码。

SkyTiger

unread,
Aug 26, 2007, 11:22:00 PM8/26/07
to cxf-zh
客户端代码是CXF上的例子啊,我没有改过任何一行!请参考CXF给出的客户端代码的连接!

"CXF使用缺省的命名方式给你创建了一个portName (implementor class name +

"Port")。 "这个是不是JAX-WS20规定的做法,还是CXF自己做的?


http://svn.apache.org/repos/asf/incubator/cxf/trunk/distribution/src/main/release/samples/java_first_jaxws/src/demo/hw/client/Client.java

SkyTiger

unread,
Aug 26, 2007, 11:24:02 PM8/26/07
to cxf-zh
http://svn.apache.org/repos/asf/incubator/cxf/trunk/distribution/src/main/release/samples/java_first_jaxws/src/demo/hw/client/Client.java

没有改动过一行!

"CXF使用缺省的命名方式给你创建了一个portName (implementor class name +

"Port")" 这个动作是JAX-WS20规定的吗? 还是CXF自己的做法?

如果客户端不知道服务器是CXF,如何做?

willem

unread,
Aug 27, 2007, 2:45:21 AM8/27/07
to cxf-zh
我有查了一遍规范 , 请见 JSR-224 Final Release P45

Conformance (Port selection): The portName element of the WebService
annotation, if present, MUST
be used to derive the port name to use in WSDL. In the absence of a
portName element, an implementation
MUST use the value of the name element of the WebService annotation,
if present, suffixed with
"Port". Otherwise, an implementation MUST use the simple name of the
class annotated with WebService
suffixed with "Port".

BTW , CXF 已经通过了JAWS 2.0的TCK。

On Aug 27, 11:22 am, SkyTiger <darktemplars...@gmail.com> wrote:
> 客户端代码是CXF上的例子啊,我没有改过任何一行!请参考CXF给出的客户端代码的连接!
>
> "CXF使用缺省的命名方式给你创建了一个portName (implementor class name +
> "Port")。 "这个是不是JAX-WS20规定的做法,还是CXF自己做的?
>

> http://svn.apache.org/repos/asf/incubator/cxf/trunk/distribution/src/...

willem

unread,
Aug 27, 2007, 2:51:12 AM8/27/07
to cxf-zh

On Aug 27, 11:24 am, SkyTiger <darktemplars...@gmail.com> wrote:
> http://svn.apache.org/repos/asf/incubator/cxf/trunk/distribution/src/...


>
> 没有改动过一行!
>
> "CXF使用缺省的命名方式给你创建了一个portName (implementor class name +
> "Port")" 这个动作是JAX-WS20规定的吗? 还是CXF自己的做法?
>
> 如果客户端不知道服务器是CXF,如何做?

你可以通过 ?wsdl 来创建 Client Artifacts。

请注意 samples java_first_jaxws 中的例子没有用到?wsdl 中的PortName

SkyTiger

unread,
Aug 27, 2007, 5:08:31 AM8/27/07
to cxf-zh

没错啊,portname是应该加"port",但是你看看WSDL文件中的portname是什么啊。是"HelloWorldImplPort",
不是客户端的"HelloWorldPort"

这个是不一样的啊!

如果你在客户端代码中使用"HelloWorldImplPort",不能调用成功啊!

我就说"HelloWorldPort"是从哪里来的?WSDL文件中没有任何关于这个名字的描述!

还有作为客户端,我只能看到"HelloWorldImplPort",没有这个"HelloWorldPort"!

SkyTiger

unread,
Aug 27, 2007, 5:10:24 AM8/27/07
to cxf-zh
不是通过"?wsdl 来创建 Client Artifacts"来创建,我没有改动CXF的例子代码,我只是看了一下服务器端生成的WSDL文件,
发现里面没有CXF客户端代码中给出这个"HelloWorldPort"的名字,我就奇怪了,这个名字是怎么出来的?

SkyTiger

unread,
Aug 27, 2007, 5:37:42 AM8/27/07
to cxf-zh
这是我用CXF中的SPRING的例子生成的WSDL文件:
<?xml version="1.0" encoding="utf-8" ?>
- <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ns1="http://demo.huawei.com/" xmlns:soap="http://
schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/
XMLSchema" name="HelloWorld" targetNamespace="http://
demo.huawei.com/">
- <wsdl:types>
- <xsd:schema xmlns="http://demo.huawei.com/"
attributeFormDefault="unqualified" elementFormDefault="unqualified"
targetNamespace="http://demo.huawei.com/" xmlns:xsd="http://www.w3.org/
2001/XMLSchema">
<xsd:element name="sayHi" type="sayHi" />
- <xsd:complexType name="sayHi">
- <xsd:sequence>
<xsd:element minOccurs="0" name="arg0" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sayHiResponse" type="sayHiResponse" />
- <xsd:complexType name="sayHiResponse">
- <xsd:sequence>
<xsd:element minOccurs="0" name="return" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
- <wsdl:message name="sayHiResponse">
<wsdl:part element="ns1:sayHiResponse" name="result" />
</wsdl:message>
- <wsdl:message name="sayHi">
<wsdl:part element="ns1:sayHi" name="parameters" />
</wsdl:message>
- <wsdl:portType name="HelloWorld">
+ <wsdl:operation name="sayHi">
<wsdl:input message="ns1:sayHi" name="sayHi" />
<wsdl:output message="ns1:sayHiResponse" name="sayHiResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="HelloWorldSoapBinding" type="ns1:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/
soap/http" />
- <wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document" />
- <wsdl:input name="sayHi">
<soap:body use="literal" />
</wsdl:input>
- <wsdl:output name="sayHiResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="HelloWorld">
+ <wsdl:port binding="ns1:HelloWorldSoapBinding"
name="HelloWorldImplPort">
<soap:address location="http://localhost:8080/CXF/HelloWorld" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


怎我都看不到什么"HelloWorldPort"这个名字!

willem

unread,
Aug 27, 2007, 5:50:30 AM8/27/07
to cxf-zh

On Aug 27, 5:08 pm, SkyTiger <darktemplars...@gmail.com> wrote:
> 没错啊,portname是应该加"port",但是你看看WSDL文件中的portname是什么啊。是"HelloWorldImplPort",
> 不是客户端的"HelloWorldPort"

客户端的Port名字和服务器端的Port名字可以是不一样的。
因为SOAP消息包里面没有Port的信息。
Port 主要对应的是Address信息
PortType 主要对应的Operation信息。
在Client 和Server端Port 名字可以不一样,但是PortType信息以及Address信息必须是一致的

>
> 这个是不一样的啊!
>
> 如果你在客户端代码中使用"HelloWorldImplPort",不能调用成功啊!
这里就是getPort的参数细节问题了。
因为在客户端传入的参数时SEI, 因此如果在没有制定Service.getPort() 没有指定PortName的情况下,PortName是通
过分析SEI的class名字("HelloWorld") + "Port"来获得。
与你开始调用的Serive.addPort()的名字不匹配,这样就没有办法拿到正确的Address,于是就调用不成功。

这时候你只需要 把原来的getPort调用加一个PORT_NAME参数就可以了。
HelloWorld hw = service.getPort(PORT_NAME, HelloWorld.class);


>
> 我就说"HelloWorldPort"是从哪里来的?WSDL文件中没有任何关于这个名字的描述!

你可以修改Client的代码如下 (这就是从WSDL构建ServiceModel, address 信息是通过PORT_NAME获得的)
Service service = Service.create(new URL("http://localhost:
9000/helloWorld?wsdl"),SERVICE_NAME);

HelloWorld hw = service.getPort(PORT_NAME, HelloWorld.class);
System.out.println(hw.sayHi("World"));

willem

unread,
Aug 27, 2007, 5:54:42 AM8/27/07
to cxf-zh

建议你读一下规范,跑一下CXF的例子,很快就能明白了。
BTW
以后讨论问题最好有代码或者测试示例,否则我们也不好重现问题,光凭猜测是很难马上定位问题的。

SkyTiger

unread,
Aug 27, 2007, 6:11:44 AM8/27/07
to cxf-zh
OK!

ufo

unread,
Aug 27, 2007, 10:25:30 PM8/27/07
to cxf-zh
为什么一个简单的hello world弄的这么多问题,我认为还需要再将helloworld再完整些。
我遇到的问题是Client可以invoke but get a null response的问题。两种生成wsdl的方式都试过了。
现在用的人还少,希望有更多的人加入,同时也希望将helloworld做的完善些。

> > 发现里面没有CXF客户端代码中给出这个"HelloWorldPort"的名字,我就奇怪了,这个名字是怎么出来的?- Hide quoted text -

maomao

unread,
Aug 27, 2007, 10:41:13 PM8/27/07
to cxf-zh
On Aug 28, 10:25 am, ufo <chenxing...@gmail.com> wrote:
> 为什么一个简单的hello world弄的这么多问题,我认为还需要再将helloworld再完整些。
> 我遇到的问题是Client可以invoke but get a null response的问题。两种生成wsdl的方式都试过了。

其实要解决一个问题很简单, 一般情况下我们都会这么做

1. 试验环境, 写清楚你的操作系统,jdk版本,cxf版本等等
2. 试验步骤,简单列举你的步骤, e.g 1,2,3, 要能达到让别人能重现你的问题就可以了

that's it!

当然每个人的认识程度不一样,不一定能很快解决问题,但我希望大家都能从中学到东西。
所以不必担心, 我们都以解决问题为目的。
只要你问, just ask!


> 现在用的人还少,希望有更多的人加入

同意, 希望大家一起努力 :)

willem

unread,
Aug 27, 2007, 10:49:54 PM8/27/07
to cxf-zh

On Aug 28, 10:25 am, ufo <chenxing...@gmail.com> wrote:
> 为什么一个简单的hello world弄的这么多问题,我认为还需要再将helloworld再完整些。

在Code First情况下SEI 提供的信息不完整,规范中定义很多Rule, 如果你不遵循相关的规定很难创建正确的服务和客户端。
建议你还是从WSDL First的例子开始玩,这样能对规范有更理性的认识。

> 我遇到的问题是Client可以invoke but get a null response的问题。两种生成wsdl的方式都试过了。

上面的Code我都测试过了,是可以工作的。
建议你用TCPMonitor 抓一下包,看看SOAP消息包是否正确。

> 现在用的人还少,希望有更多的人加入,同时也希望将helloworld做的完善些。
现在CXF的使用者并不少。
如果你看一下 http://www.nabble.com/CXF-f16913.html
cxf-...@incubator.apache.org 基本上每个小时都有流量,而且用户也是来自世界各地的。

ufo

unread,
Aug 27, 2007, 11:26:31 PM8/27/07
to cxf-zh
感谢 回复!:)
上面提出的问题是半个月前按http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-
service.html做时遇到的,当时用的近一天时间没找到原因。例子里的hello world和其它没有问题。

Willem Jiang

unread,
Aug 27, 2007, 11:37:24 PM8/27/07
to cxf...@googlegroups.com
http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-service.html
已于8月20号更新过了。Please check it out :)

ufo

unread,
Aug 28, 2007, 12:15:12 AM8/28/07
to cxf-zh
谢谢 Willem Jiang.

刚换为2.0.1问题解决了,感谢及时的支持。

充满信心,拥抱CXF的将来。

> > service.html做时遇到的,当时用的近一天时间没找到原因。例子里的hello world和其它没有问题。- Hide quoted text -

Reply all
Reply to author
Forward
0 new messages