我正在从 CXF 复制最简单的 Web 服务示例;它逐步编写一个接口,然后是一个实现文件,以向 Web 服务使用者提供的名称打招呼。我更改了包名和方法名,因为我想看看事情出现在哪里;如果您将所有内容命名为 HelloWorld,您将看不到方法、包、类等是什么。
这些指令包括发布 Web 服务的程序。在我这样做之后,把网址
http://localhost:9000/helloWorld?wsdl
在浏览器中显示一个 wsdl 文件,其中包含我拼写的足够内容,以使我相信它是从我的代码生成的。基于此,我假设 WSDL 生成和发布都有效。
这是服务接口:
package hw;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface HelloWorld
{
String sayHi(@WebParam(name="firstName") String firstName);
}
这是服务实现:
package hwimpl;
import javax.jws.WebService;
@WebService(endpointInterface = "hw.HelloWorld", serviceName = "HelloWorld")
public class HelloWorldImpl
{
static public void say(String msg) { System.out.println(msg); }
public String sayHi(String firstName)
{ say ("sayHi called with " + firstName);
return "Hello " + firstName + " from the World.";
}
}
这是发布程序:
package hwimpl;
import javax.xml.ws.Endpoint;
public class PublishHelloWorldService
{
protected PublishHelloWorldService() throws Exception
{
// START SNIPPET: publish
System.out.println("Starting Server");
HelloWorldImpl implementor = new HelloWorldImpl();
String address = "http://localhost:9000/helloWorld";
Endpoint.publish(address, implementor);
// END SNIPPET: publish
}
public static void main(String args[]) throws Exception
{
new PublishHelloWorldService();
System.out.println("Server ready...");
Thread.sleep(5 * 60 * 1000);
System.out.println("Server exiting");
System.exit(0);
}
}
现在我编译并运行这个程序:
package client;
import hw.HelloWorld;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
public final class HelloWorldClient
{
private static final QName SERVICE_NAME = new QName("http://server.hw.demo/", "HelloWorld");
private static final QName PORT_NAME = new QName("http://server.hw.demo/", "HelloWorldPort");
private HelloWorldClient()
{
}
public static void main(String args[]) throws Exception
{
Service service = Service.create(SERVICE_NAME);
String endpointAddress = "http://localhost:9000/helloWorld";
// If web service deployed on Tomcat deployment, endpoint should be changed
// to:
// String
// endpointAddress =
// "http://localhost:8080/java_first_jaxws/services/hello_world";
// Add a port to the Service
service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
HelloWorld hw = service.getPort(HelloWorld.class);
System.out.println(hw.sayHi("Albert"));
}
}
我得到这个错误:
Exception in thread "main" javax.xml.ws.WebServiceException: Could not send Message.
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)
at com.sun.proxy.$Proxy20.sayHi(Unknown Source)
at client.HelloWorldClient.main(HelloWorldClient.java:37)
Caused by: java.net.MalformedURLException: Invalid address. Endpoint address cannot be null.
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:872)
at org.apache.cxf.transport.http.HTTPConduit.getURL(HTTPConduit.java:854)
at org.apache.cxf.transport.http.HTTPConduit.setupURL(HTTPConduit.java:800)
at org.apache.cxf.transport.http.HTTPConduit.prepare(HTTPConduit.java:548)
at org.apache.cxf.interceptor.MessageSenderInterceptor.handleMessage(MessageSenderInterceptor.java:46)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:516)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:265)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:124)
... 2 more
我正在运行来自 Eclipse 的程序——发布和客户端。Eclipse 在 Window / Preferences 中设置了 http 和 https 的代理;在运行客户端之前,我删除了 http 的那个,但它并没有改变消息。
它实际上是一个 tomcat 服务器;我在发布程序中尝试了备用 URL,没有任何变化。
在这种情况下,我不会从 Eclipse 中运行 tomcat;我在我的机器上自己运行它,然后运行发布程序(来自 eclipse),验证显示 wsdl 的 url 是否正常工作,然后运行客户端程序(来自 eclipse)并得到我的错误。
有人可以告诉我我做错了什么吗?我已经看到有关此确切错误消息的其他帖子,但没有一个答案是确定的,我似乎已经尝试了所有这些。