我们有一个发布/订阅WS应用程序,我们希望将现有Oracle的Java HTTP Server实现替换为嵌入式Jetty实现。不幸的是,当我们尝试使用Endpoint.publish(HttpContext)调用发布Web服务时,我们遇到了一些麻烦。作为附加信息,我们被迫使用此调用,我们不能使用Endpoint.publish(地址)。
我刚刚创建了一个测试应用程序,以便隔离问题并征求您的意见。
请在下面找到TestService类:
public class TestService {
public static void main(String[] args) throws IOException {
int port = 8081;
String path = "/myservice";
AsyncProvider<Source> internalProvider = new InternalProvider();
Endpoint endpoint = Endpoint.create(internalProvider);
// Preparing the Service
URL wsdlLocation = TestService.class.getResource("NotificationService.wsdl");
Source source = null;
try {
source = new StreamSource(wsdlLocation.openStream());
} catch (IOException ex) {
Logger.getLogger(TestService.class.getName()).log(Level.SEVERE, "Couldn't open WSDL", ex);
}
source.setSystemId(wsdlLocation.toExternalForm());
List<Source> metadata = new ArrayList<Source>();
metadata.add(source);
endpoint.setMetadata(metadata);
QName serviceName = new QName("http://notification/", "ConsumerService");
QName portName = new QName("http://notification/", "ConsumerPort");
Map<String, Object> map = new HashMap<String, Object>();
map.put(Endpoint.WSDL_SERVICE, serviceName);
map.put(Endpoint.WSDL_PORT, portName);
endpoint.setProperties(map);
// This is the fragment of code that is replacing Oracle’s HTTP Server with Jetty
Server s = new Server(new InetSocketAddress("localhost", port));
ServerConnector connector = new ServerConnector(s);
connector.setReuseAddress(true);
connector.setPort(port);
s.setConnectors(new Connector[] {connector});
s.setHandler(new ContextHandlerCollection());
JettyHttpServer httpServer = new JettyHttpServer(s, false);
JettyHttpContext context = (JettyHttpContext) httpServer.createContext(path); // It’s seems that is not taking into account the path
endpoint.publish(context);
httpServer.start();
W3CEndpointReference providerEPR = (W3CEndpointReference)endpoint.getEndpointReference(); // Throws a NullPointerException when calling HttpEndpoint.getEPRAddress()
System.out.println("providerEPR: " + providerEPR);
}
@WebServiceProvider
@ServiceMode(value = javax.xml.ws.Service.Mode.PAYLOAD)
private final static class InternalProvider implements AsyncProvider<Source>{
@Override
public void invoke(Source t, AsyncProviderCallback<Source> apc, WebServiceContext wsc) {
processCall(t, apc, wsc);
}
private void processCall(Source t, AsyncProviderCallback<Source> apc, WebServiceContext wsc) {
// Process the Request and generate a reply
…
}
}
此处附上消费者客户:
public class ConsumerClient {
public static void main(String[] args) throws Exception {
Dispatch<Source> consumer;
//Get the Service
URL wsdURL = new URL("http://localhost:8081/myservice?wsdl");
QName serviceName = new QName("http://notification/", "ConsumerService");
Service service = Service.create(wsdURL, serviceName);
//Get the Dispatch
QName portName = new QName("http://notification/", "ConsumerPort");
consumer = service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);
//ProducerService - Subscribe
String message = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<not:subscribe xmlns:not=\"http://notification/\" xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ "<name>Peter</name>"
+ "<epr> <Address xmlns=\"http://www.w3.org/2005/08/addressing\">http://localhost:8081/myservice</Address>"
+ "<Metadata xmlns=\"http://www.w3.org/2005/08/addressing\" xmlns:wsdli=\"http://www.w3.org/ns/wsdl-instance\" wsdli:wsdlLocation=\"http://notification/ http://localhost:8081/myservice?wsdl\">"
+ "<wsam:InterfaceName xmlns:wsam=\"http://www.w3.org/2007/05/addressing/metadata\" xmlns:wsaw=\"http://www.w3.org/2006/05/addressing/wsdl\" xmlns:wsns=\"http://notification/\">wsns:Consumer</wsam:InterfaceName>"
+ "<wsam:ServiceName xmlns:wsam=\"http://www.w3.org/2007/05/addressing/metadata\" xmlns:wsaw=\"http://www.w3.org/2006/05/addressing/wsdl\" xmlns:wsns=\"http://notification/\" EndpointName=\"ConsumerPort\">wsns:ConsumerService</wsam:ServiceName>"
+ "</Metadata> </epr> </not:subscribe> ";
System.out.println("[ConsumerClient] Sending Subscribe Message");
Source res = consumer.invoke(new StreamSource(new StringReader(message))); // Here is where it crashes cause it cannot find the service (com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 404: Not Found)
System.out.println("[ConsumerClient] Received Response:");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(System.out);
transformer.transform(res, output);
}
我附上了下面的日志
在服务器端
2016-05-03 17:14:24.374:INFO::main: Logging initialized @759ms
May 03, 2016 5:14:29 PM com.sun.xml.ws.server.MonitorBase createRoot
INFO: Metro monitoring rootname successfully set to: com.sun.metro:pp=/,type=WSEndpoint,name=ConsumerService-ConsumerPort
2016-05-03 17:14:30.317:INFO:oejs.Server:main: jetty-9.2.15.v20160210
2016-05-03 17:14:30.437:INFO:oejsh.ContextHandler:main: Started o.e.j.h.s.HttpSpiContextHandler@557db906{/myservice,null,AVAILABLE}
2016-05-03 17:14:30.494:INFO:oejs.ServerConnector:main: Started ServerConnector@44e8195b{HTTP/1.1}{0.0.0.0:8081}
2016-05-03 17:14:30.495:INFO:oejs.Server:main: Started @6883ms
Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.ws.transport.http.server.HttpEndpoint.getEPRAddress(HttpEndpoint.java:104)
at com.sun.xml.ws.transport.http.server.HttpEndpoint.getEndpointReference(HttpEndpoint.java:135)
at com.sun.xml.ws.transport.http.server.EndpointImpl.getEndpointReference(EndpointImpl.java:348)
at com.sun.xml.ws.transport.http.server.EndpointImpl.getEndpointReference(EndpointImpl.java:341)
at fr.endpoint.TestService.main(TestService.java:111)
在客户端
2016-05-03 17:14:39.518:INFO::main: Logging initialized @2297ms
[ConsumerClient] Sending Subscribe Message
Exception in thread "main" com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 404: Not Found
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:222)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:179)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:93)
at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:105)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:629)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:588)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:573)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:470)
at com.sun.xml.ws.client.Stub.process(Stub.java:319)
at com.sun.xml.ws.client.dispatch.DispatchImpl.doInvoke(DispatchImpl.java:189)
at com.sun.xml.ws.client.dispatch.DispatchImpl.invoke(DispatchImpl.java:215)
at fr.endpoint.ConsumerClient.main(ConsumerClient.java:54)
为此端点设置上下文时我们缺少什么?或者也许是因为我们没有正确初始化Jetty HttpServer?
我无法找到很多关于JAX-WS和Jetty集成的文档。如果您能给我们任何暗示和建议,我们将非常感激。
我们使用Metro 2.3作为JAX-WS RI,Jetty 9.2.15,Java 1.7(jdk1.7.0_21)和Netbeans 8.0.2。
感谢您的时间
大卫