Я пытался установить конечную точку SOAP с Websocket в качестве транспортного протокола через CXF и реализовать его вызов через CXF.С врезанным причалом.Я попробовал пару подходов, но ни один из подходов не сработал.Вот что я сделал:
Aproach 1. В соответствии с документацией CXF websocket поддерживается как транспортный протокол, и его поддержка предоставляется через
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-websocket</artifactId>
<version>3.3.2</version>
</dependency>
Я настроилследующие зависимости:
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.0.39</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>3.3.2</version>
</dependency>
Код, который я выполняю, выглядит следующим образом:
Endpoint endpoint = Endpoint.create(new MyHelloWorldServicePortType() {
@Override
public String sayHello(HelloMessage message) throws FaultMessage {
return message.sayHello();
}
};
((org.apache.cxf.jaxws.EndpointImpl)endpoint).getFeatures().add(new
WSAddressingFeature());
endpoint.publish("ws://localhost:8088/MyHelloWorldService" );
URL wsdlDocumentLocation = new URL("file:/path to wsdl file");
String servicePart = "MyHelloWorldService";
String namespaceURI = "mynamespaceuri";
QName serviceQN = new QName(namespaceURI, servicePart);
Service service = Service.create(wsdlDocumentLocation, serviceQN);
MyHelloWorldServicePortType port = service.getPort( MyHelloWorldServicePortType.class);
portType.sayHello(new HelloMessage("Say Hello"));
Результат этого кода:
SEVERE: [ws]onError java.util.concurrent.TimeoutException: запрос тайм-аута для неподключенного через 60000 мс в org.asynchttpclient.netty.timeout.TimeoutTimerTask.expire (TimeoutTimerTask.java:43) в org.asynchttpclient.nettyTimeasReRe.Time.TimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTimeTime.TimeRequestTimeoutTimerTask.java:48) в io.netty.util.HashedWheelTimer $ HashedWheelTimeout.expire (HashedWheelTimer.java:682) в io.netty.util.HashedWheelTimer $ HashedWheelBucket.exp..HashedWheelTimer $ Worker.run (HashedWheelTimer.java:485) в java.base / java.lang.Thread.run (Thread.java:834)
июнь.12, 2019 13:13:33 org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream connect SEVERE: невозможно подключить java.util.concurrent.ExecutionException: java.util.concurrent.Time Outout-подключен через 60000 мс в java.base / java.util.concurrent.CompletableFuture.reportGet (CompletableFuture.java:395) в java.base / java.util.concurrent.CompletableFuture.get (CompletableFuture.java:1999) в орг.asynchttpclient.netty.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream.setupWrappedStream (AhcWebSocketConduit.java:167) в org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.handlett.th.tht_tg_t3_t_p_W3_HT_PHT_T3_HTWrappedOutputStream.onFirstWrite (HTTPConduit.java:1304) в org.apache.cxf.io.AbstractWrappedOutputStream.write (AbstractWrappedOutputStream.java:47) в org.apache.cxf.io.AbstractThresholdOutputStream.write (AbstractThresholdOutputStream.jxfache. atc.ap.at).transport.http.HTTPConduit $ WrappedOutputStream.close (HTTPConduit.java:1356) в org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream.close (AhcWebSocketConduit.java:139) в org.apache.cxf.transport.AbstractConduit.close (AbstractConduit.java:56)
Я абсолютно не знаю, почему.Когда я пытаюсь подключиться через веб-сокет Chrome клиента по URL.Это говорит об успехе.В то же время при подключении через клиент он говорит Timeout.
Aproach 2.
Я решил обмануть CXF и предоставить конечную точку Websocket ручной работы, которая будет использоваться какфронт к веб-сервису CXF.Идея состоит в том, что Клиент отправит сообщение через веб-сокет, которое будет развернуто, а затем отправлено через CXF.Этот подход очень похож на этот подход, но здесь он использует JMS в качестве транспорта
https://github.com/pbielicki/soap-websocket-cxf
Чтобы сделать это, я создал следующую точку Websocket:
@ServerEndpoint("/jaxWSFront")
public class JaxWSFrontEnd {
@OnOpen
public void onOpen(final Session session) {
System.out.println("Hellooo");
}
@OnMessage
public void onMessage(String mySoapMessage,final Session session) throws Exception{
// The goal here is to get the soap message and redirect it via SOAP web //service. The JaxWSFacade acts as a point that understands websocket and then //gets the soap content and sends it to enpoint that understands SOAP.
session.getBasicRemote().sendText("Helllo . Now you see me.");
System.out.println("Hellooo again");
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Hellooo");
}
@OnError
public void onError(Throwable t, Session session) {
System.out.println("Hellooo");
}
}
Теперь я указал мой клиентский прокси на jaxWsFrontEnd вместо конечной точки веб-службы.Я ожидаю, что я получу сообщение SOAP в методе onMessage, а затем смогу перенаправить SOAP в веб-службу CXF.
Теперь мой код выглядит следующим образом:
server = new Server(8088);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath( "/" );
server.setHandler(context);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(JaxWSFrontEnd.class);
server.setHandler( context );
server.start();
Endpoint endpoint = Endpoint.create(new MyHelloWorldServicePortType() {
@Override
public String sayHello(HelloMessage message) throws FaultMessage {
return message.sayHello();
}
};
((org.apache.cxf.jaxws.EndpointImpl)endpoint).getFeatures().add(new
WSAddressingFeature());
URL wsdlDocumentLocation = new URL("file:/path to wsdl file");
String servicePart = "MyHelloWorldService";
String namespaceURI = "mynamespaceuri";
QName serviceQN = new QName(namespaceURI, servicePart);
Service service = Service.create(wsdlDocumentLocation, serviceQN);
MyHelloWorldServicePortType port = service.getPort( MyHelloWorldServicePortType.class);
portType.sayHello(new HelloMessage("Say Hello"));
Для второго подхода у меня были в дополнение к подходу 1 следующие зависимости:
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-common</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
</dependency>
Результат от подхода 2 абсолютно такой же, как и для подхода 1, исключения, которые я получаю, такие же, с одним небольшим отличием. Когда я использую клиент веб-сокета Chrome и указываю его непосредственно на jaxWsFrontend, я могу успешно отправить сообщение. Почему я не могу подключиться к веб-сокету с помощью механизмов транспортировки веб-сокетов CXF ???? Что я делаю не так?
ОБНОВЛЕНИЕ: включение регистрации из NETTY. Похоже, что netty выбросил java.lang.NoSuchMethodError: io.netty.channel.DefaultChannelId.newInstance () Lio / netty / channel / DefaultChannelId;
Возможно, у меня проблема совместимости версий с netty. Версия, которую я вижу, импортирована в проект - 4.1.33. Это транзитивная зависимость, которую я не объявил.