带有Appache CXF和嵌入式Jetty的Websocket上的SOAP [英] SOAP over Websocket with Appache CXF and Embedded Jetty

查看:325
本文介绍了带有Appache CXF和嵌入式Jetty的Websocket上的SOAP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试通过CXF将带有Websocket的SOAP端点设置为传输协议,并通过CXF实现调用它.带嵌入式码头.我尝试了几种方法,但都没有成功.这是我所做的:

I have been trying to set a a SOAP endpoint with Websocket as transport protocol via CXF and implement invoke it via CXF. With Embeded jetty. I have tried a couple of approaches non of the aproaches worked unfortunatly. Here is what I did:

方法1 .根据CXF文档,websocket作为传输协议受支持,并且通过

Aproach 1. According to CXF documentation websocket is supported as transport protocol and its support is given via

<dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-websocket</artifactId>
            <version>3.3.2</version>
</dependency>

我已经设置了以下依赖项:

I have setup the following dependencies:

 <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"));

此代码的结果是:

严重:[ws] onError java.util.concurrent.TimeoutException:请求 在60000毫秒后超时到未连接 org.asynchttpclient.netty.timeout.TimeoutTimerTask.expire(TimeoutTimerTask.java:43) 在 org.asynchttpclient.netty.timeout.RequestTimeoutTimerTask.run(RequestTimeoutTimerTask.java:48) 在 io.netty.util.HashedWheelTimer $ HashedWheelTimeout.expire(HashedWheelTimer.java:682) 在 io.netty.util.HashedWheelTimer $ HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:757) 在 io.netty.util.HashedWheelTimer $ Worker.run(HashedWheelTimer.java:485) 在java.base/java.lang.Thread.run(Thread.java:834)

SEVERE: [ws] onError java.util.concurrent.TimeoutException: Request timeout to not-connected after 60000 ms at org.asynchttpclient.netty.timeout.TimeoutTimerTask.expire(TimeoutTimerTask.java:43) at org.asynchttpclient.netty.timeout.RequestTimeoutTimerTask.run(RequestTimeoutTimerTask.java:48) at io.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:682) at io.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:757) at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:485) at java.base/java.lang.Thread.run(Thread.java:834)

君. 2019年12月12日下午13:33 org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream 严重连接:无法连接 java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException:请求超时 60000毫秒后未连接 java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395) 在 java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999) 在 org.asynchttpclient.netty.NettyResponseFuture.get(NettyResponseFuture.java:172) 在 org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream.connect(AhcWebSocketConduit.java:309) 在 org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit $ AhcWebSocketWrappedOutputStream.setupWrappedStream(AhcWebSocketConduit.java:167) 在 org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1343) 在 org.apache.cxf.transport.http.HTTPConduit $ WrappedOutputStream.onFirstWrite(HTTPConduit.java:1304) 在 org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47) 在 org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69) 在 org.apache.cxf.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)

jun. 12, 2019 1:13:33 P.M. org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream connect SEVERE: unable to connect java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException: Request timeout to not-connected after 60000 ms at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395) at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999) at org.asynchttpclient.netty.NettyResponseFuture.get(NettyResponseFuture.java:172) at org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.connect(AhcWebSocketConduit.java:309) at org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.setupWrappedStream(AhcWebSocketConduit.java:167) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1343) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1304) at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47) at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1356) at org.apache.cxf.transport.websocket.ahc.AhcWebSocketConduit$AhcWebSocketWrappedOutputStream.close(AhcWebSocketConduit.java:139) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)

我绝对不知道为什么.当我尝试通过URL上的websocket chrome客户端进行连接时.它说成功.通过客户端连接时,同时显示超时.

I have absolutly no idea why. When I try to connect via websocket chrome client on the URL. It says success. At the same time when connecting via the client it says Timeout.

方法2.

我决定欺骗CXF,并提供一个手工Websocket端点,它将用作CXF Web服务的前端.这个想法是,客户端将通过websocket发送消息,消息将被解包,然后通过CXF发送.此方法与此处的方法非常相似,但此处使用JMS作为传输方式

I decided to cheat CXF and provide a handmade Websocket endpoint that will be used as a front to the CXF webservice. The idea is that the Client will send a message via websocket the message will be unwrapped and then sent over CXF. This aproach is very similar to the aproach here but here it uses JMS as transport

https://github.com/pbielicki/soap-websocket-cxf

为此,我创建了以下Websocket enpoint:

In oprder to do this I created the following Websocket enpoint:

@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而不是Webservice端点.我的期望是,我将在onMessage方法中接收SOAP消息,然后将能够转发到SOAP到CXF Web服务.

Now I pointed my Client proxy to the jaxWsFrontEnd instead of the webservice endpoint. My expectation is that I will recieve the SOAP message in the onMessage method and then I will be able to forwards to SOAP to the CXF web service.

现在我的代码如下:

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以外,还具有以下依赖性:

For the second aproach I had in addition to the aproach 1 the following dependencies:

<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 Websocket客户端并将其直接指向jaxWsFrontend时,我能够成功发送消息.为什么我无法通过CXF Websocket传输机制连接到Websocket?我在做什么错了?

Result from aproach 2 is absolutly the same as Aproach 1 the exceptions I recieve are the same, with one minor difference. When I use the the Chrome websocket client and point it directly the the jaxWsFrontend I am able to successfuly send a message. Why I am not able to connect to websocket wia the CXF websocket transport mechanisms ???? What am I doing wrong ?

更新:启用NETTY的日志记录.这说明网易引发了java.lang.NoSuchMethodError:io.netty.channel.DefaultChannelId.newInstance()Lio/netty/channel/DefaultChannelId;

UPDATE: enabling the loging from NETTY. It apears that netty has thrown java.lang.NoSuchMethodError: io.netty.channel.DefaultChannelId.newInstance()Lio/netty/channel/DefaultChannelId;

也许我有netty的版本兼容性问题.我看到的导入到项目中的版本是4.1.33.我没有声明它是一个传递依赖.

Maybe I have a version compatability issue with netty. The version I can see is imported in the project is 4.1.33. It is a transitive dependency I don|t have it declared.

推荐答案

好吧,我实际上设法独自破解了它.我将发布完成答案.显然,CXF专家应该更新其IMO文档.在他们的网站上指出,为了启用Websocket作为传输协议,我们需要 cxf-rt-transports-websocket 依赖项.

Ok I actualy managed to crack it alone. I will post the answer for completion. Apparantly CXF guys should update their documentation IMO. On their website it is stated that in order to enable Websocket as transport protocol we need cxf-rt-transports-websocket dependency.

他们没有说的是,您还需要 async-http-client 而不是任何版本,而需要 2.0.39 一个很老的版本.问题在于它自动包括对 netty 4.1 的传递依赖,并且上面指定的错误开始显现.您实际需要的是nett 4.0.56

What they do not say is that you in addition need async-http-client not any version but 2.0.39 a prettey old one. The problem is that it automaticaly includes transitive dependencies to netty 4.1 and the error specified above begins to manifest. What you actualy need is nett 4.0.56

以下是使事情对我有用的片段:

Here is the fragment that made the things work for me:

<dependency>
            <groupId>org.asynchttpclient</groupId>
            <artifactId>async-http-client</artifactId>
            <version>2.0.39</version>
             <exclusions>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-buffer</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-codec-http</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-handler</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-transport-native-epoll</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-transport</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-common</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-codec</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-all</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.0.56.Final</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-websocket</artifactId>
        <version>3.3.2</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>

方法1正在运作 方法2我设法触发了onConnect事件,即onMessage超时,但是我认为它应该可以工作,但我缺少一些小东西.无论如何,我没有更多的时间花在我身上,并且对Aproach 1感到满意.

Aproach 1 is working Aproach 2 I managed to trigger the onConnect event, the onMessage timedout, but in my opinion it should work I am missing something small. Anyway I don|t have more time to spent and I am happy with Aproach 1.

这篇关于带有Appache CXF和嵌入式Jetty的Websocket上的SOAP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆