websockets with Tomcat 8 and Spring 4 ClassCastException before handler is invoked

匿名 (未验证) 提交于 2019-12-03 02:20:02

问题:

I am trying to get a simple websocket to work to integrate into my application. However I have not been able to get it to work with the Spring API's, with a ClassCastException somewhere before my handler is invoked trying to convert a Tomcat type to a javax object. If I just use Tomcat directly without Spring (so the javax.websocket objects and annotations) it works perfectly, so I am really not sure why there is an issue with Spring.

08-May-2014 01:10:12.048 SEVERE [http-nio-8084-exec-88] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [dispatcher] in context with path [/WebsocketSpringTest] threw exception [Request processing failed; nested exception is org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://localhost:8084/WebsocketSpringTest/socket; nested exception is java.lang.ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server.ServerContainer] with root cause java.lang.ClassCastException: org.apache.tomcat.websocket.server.WsServerContainer cannot be cast to javax.websocket.server.ServerContainer at org.springframework.web.socket.server.standard.AbstractStandardUpgradeStrategy.getContainer(AbstractStandardUpgradeStrategy.java:67) 

TestSocket.java

import org.springframework.web.socket.WebSocketHandler; public class TestSocket implements WebSocketHandler {     ... 

web.xml

<servlet>     <servlet-name>dispatcher</servlet-name>     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping>     <servlet-name>dispatcher</servlet-name>     <url-pattern>/</url-pattern> </servlet-mapping> 

dispatcher-servlet.xml

<context:component-scan base-package="com.willnewbery.websocketspringtest" /> <context:annotation-config /> <mvc:annotation-driven /> <mvc:resources mapping="/resources/**" location="/resources/" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"          p:prefix="/WEB-INF/views/" p:suffix=".jsp" /> <websocket:handlers>     <websocket:mapping path="/socket" handler="socket"/> </websocket:handlers> <bean id="socket" class="com.willnewbery.websocketspringtest.TestSocket"/> 

pom.xml

<properties>     <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>     <spring.version>4.0.4.RELEASE</spring.version>     <tomcat.version>8.0.3</tomcat.version> </properties>  <dependencies>     <!--javax-->     <dependency>         <groupId>javax</groupId>         <artifactId>javaee-web-api</artifactId>         <version>7.0</version>         <scope>provided</scope>     </dependency>     <dependency>         <groupId>javax.websocket</groupId>         <artifactId>javax.websocket-api</artifactId>         <version>1.0</version>     </dependency>     <!--spring-->     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-core</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-web</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-webmvc</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-websocket</artifactId>         <version>${spring.version}</version>     </dependency>     <!--tomcat--> </dependencies> 

回答1:

The "javax.websocket-api" dependency may be the issue. It is already included in the server lib so you at least make it scope "provided" or try removing it, there is a good chance you don't need it in the application pom.



回答2:

You exclude tomcat-embed-websocket dependency from spring-boot-starter-web;

        <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>             <exclusions>                 <exclusion>                     <artifactId>tomcat-embed-logging-juli</artifactId>                     <groupId>org.apache.tomcat.embed</groupId>                 </exclusion>                 <exclusion>                     <artifactId>tomcat-embed-websocket</artifactId>                     <groupId>org.apache.tomcat.embed</groupId>                 </exclusion>                 <exclusion>                     <artifactId>tomcat-embed-el</artifactId>                     <groupId>org.apache.tomcat.embed</groupId>                 </exclusion>             </exclusions>         </dependency> 


回答3:

You need to exclude tomcat-embed-websocket-*.jar from the war file.

Add this line to your build.gradle

providedCompile("org.apache.tomcat.embed:tomcat-embed-websocket") 

or in Maven:

 <dependency>         <groupId>org.apache.tomcat.embed</groupId>         <artifactId>tomcat-embed-websocket</artifactId>         <version>${tomcat.version}</version>  </dependency> 


回答4:

When it comes to building a WAR file with Spring Boot, the reference docs will point out that you need to turn Tomcat into a provided dependency. Recommended practices for both Maven and Gradle can be seen in the reference docs here => http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!