Summary: | 7.0.66 running with Java 6 fails unless unneeded "tomcat7-websocket.jar" is removed from lib/ | ||
---|---|---|---|
Product: | Tomcat 7 | Reporter: | Konstantin Kolinko <knst.kolinko> |
Component: | Catalina | Assignee: | Tomcat Developers Mailing List <dev> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | imgx64+bz |
Priority: | P2 | ||
Version: | trunk | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All |
Description
Konstantin Kolinko
2015-11-26 16:17:12 UTC
I've reverted r1715984 and refactored the code that required 1.7 so it compiles with 1.6. The fix will be in 7.0.67 onwards. (In reply to Mark Thomas from comment #1) > I've reverted r1715984 and refactored the code that required 1.7 so it > compiles with 1.6. The fix will be in 7.0.67 onwards. It's not an issue of compiling with Java 1.6, but an issue of class file versions. You can still use 1.7 source features and still have target="1.6". I'm not sure the re-factoring was necessary (but I haven't read the diff, yet). This is fixed when running standalone Tomcat 7.0.67, but it still breaks when running Tomcat embedded in Spring Boot. See this Spring Boot issue for more info: [1] To reproduce: 1- Download and unzip this Spring Boot Starter template: [2] 2- Edit pom.xml and add `<tomcat.version>7.0.67</tomcat.version>` inside `<properties>` element. 3- run `mvn package` in the unzipped directory (You either need to install Maven, or run `./mvnw package` instead which will automatically download Maven). 4- Make sure you're using Java 6 and run `java -jar target/demo-0.0.1-SNAPSHOT.jar' 5- This exception is thrown: java.lang.NoClassDefFoundError: java/nio/charset/StandardCharsets at org.apache.tomcat.websocket.WsWebSocketContainer.<clinit>(WsWebSocketContainer.java:112) ~[tomcat-embed-websocket-7.0.67.jar!/:7.0.67] at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:154) ~[tomcat-embed-websocket-7.0.67.jar!/:7.0.67] at org.apache.tomcat.websocket.server.WsContextListener.contextInitialized(WsContextListener.java:39) ~[tomcat-embed-websocket-7.0.67.jar!/:7.0.67] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5077) [tomcat-embed-core-7.0.67.jar!/:7.0.67] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5591) [tomcat-embed-core-7.0.67.jar!/:7.0.67] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-7.0.67.jar!/:7.0.67] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574) [tomcat-embed-core-7.0.67.jar!/:7.0.67] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564) [tomcat-embed-core-7.0.67.jar!/:7.0.67] at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) [na:1.6.0_65] at java.util.concurrent.FutureTask.run(FutureTask.java:138) [na:1.6.0_65] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) [na:1.6.0_65] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) [na:1.6.0_65] at java.lang.Thread.run(Thread.java:695) [na:1.6.0_65] Caused by: java.lang.ClassNotFoundException: java.nio.charset.StandardCharsets at java.net.URLClassLoader$1.run(URLClassLoader.java:202) ~[na:1.6.0_65] at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_65] at java.net.URLClassLoader.findClass(URLClassLoader.java:190) ~[na:1.6.0_65] at java.lang.ClassLoader.loadClass(ClassLoader.java:306) ~[na:1.6.0_65] at org.springframework.boot.loader.LaunchedURLClassLoader.doLoadClass(LaunchedURLClassLoader.java:178) ~[demo-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT] at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:142) ~[demo-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT] at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[na:1.6.0_65] ... 13 common frames omitted [1] (https://github.com/spring-projects/spring-boot/issues/4846 ) [2] (http://start.spring.io/starter.zip?name=demo&groupId=com.example&artifactId=demo&version=0.0.1-SNAPSHOT&description=Demo+project+for+Spring+Boot&packageName=com.example&type=maven-project&packaging=jar&javaVersion=1.6&language=java&bootVersion=1.3.2.BUILD-SNAPSHOT&dependencies=web ) There are multiple reasons this is not the same issue: - the stack trace is different - the GitHub issue makes it clear that a different set of Tomcat versions is affected. The Spring Boot team appear to have mis-read my comment, particularly the question mark at the end of the first sentence and the entire of the final sentence. I've taken a quick look at the demo and this is clearly a Spring Boot bug. I'll comment on the Spring Boot issue. I dug into the Tomcat 7 code, and I managed to "fix" the Spring Boot bug by copying StandardCharsets.ISO_8859_1 into WsWebSocketContainer and changing the static intializers. Is this an appropriate solution? Note that StandardCharsets.ISO_8859_1 is used elsewhere in WsWebSocketContainer, but only the static initializers are causing problems. Index: java/org/apache/tomcat/websocket/WsWebSocketContainer.java =================================================================== --- java/org/apache/tomcat/websocket/WsWebSocketContainer.java (revision 1721884) +++ java/org/apache/tomcat/websocket/WsWebSocketContainer.java (working copy) @@ -29,6 +29,7 @@ import java.nio.ByteBuffer; import java.nio.channels.AsynchronousChannelGroup; import java.nio.channels.AsynchronousSocketChannel; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.util.ArrayList; @@ -109,10 +110,12 @@ private static final Random random = new Random(); private static final byte[] crlf = new byte[] {13, 10}; - private static final byte[] GET_BYTES = "GET ".getBytes(StandardCharsets.ISO_8859_1); - private static final byte[] ROOT_URI_BYTES = "/".getBytes(StandardCharsets.ISO_8859_1); + private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + + private static final byte[] GET_BYTES = "GET ".getBytes(ISO_8859_1); + private static final byte[] ROOT_URI_BYTES = "/".getBytes(ISO_8859_1); private static final byte[] HTTP_VERSION_BYTES = - " HTTP/1.1\r\n".getBytes(StandardCharsets.ISO_8859_1); + " HTTP/1.1\r\n".getBytes(ISO_8859_1); private volatile AsynchronousChannelGroup asynchronousChannelGroup = null; private final Object asynchronousChannelGroupLock = new Object(); This issue is fixed. Please don't use it to discuss what is an unrelated issue in Spring Boot. If you want input from the Tomcat devs on possible options for fixing the Spring Boot issue, then the Tomcat dev list is the place to ask. |