Running 7.0.66 release candidate (smoke-testing) I see an issue that I think is caused by r1715984 change in build.xml: - source="${compile.source}" - target="${compile.target}" + source="1.7" + target="1.7" To reproduce: 1. Unpack apache-tomcat-7.0.66.zip 2. Set JAVA_HOME = Java 6 3. Start Tomcat 4. Deployment of every web application fails, including the ROOT one. INFO: Deploying web application directory REDACTED\apache-tomcat-7.0.66\webapps\ROOT 26.11.2015 18:54:53 org.apache.catalina.core.ContainerBase addChildInternal SEVERE: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652) at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1263) at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1975) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) at java.util.concurrent.FutureTask.run(FutureTask.java:138) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) at java.lang.Thread.run(Thread.java:662) Caused by: java.lang.UnsupportedClassVersionError: org/apache/tomcat/websocket/server/WsSci : Unsupported major.minor version 51.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:249) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1842) at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1705) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:249) at org.apache.catalina.startup.WebappServiceLoader.loadServices(WebappServiceLoader.java:192) at org.apache.catalina.startup.WebappServiceLoader.load(WebappServiceLoader.java:157) at org.apache.catalina.startup.ContextConfig.processServletContainerInitializers(ContextConfig.java:1577) at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1281) at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:889) at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:386) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5460) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) ... 11 more ]]] Solution --------- The workaround is to remove the following two files from lib directory: tomcat7-websocket.jar websocket-api.jar I guess that removing tomcat7-websocket.jar alone is enough, but I only tested with removing both of them. It is known that websocket API (JSR356) requires Java 7, so there is no use for those jar files when running with Java 6. Good news: 1. The examples web app runs successfully without those files. (I feared that it won't start). 2. JSR356 examples successfully show their HTML pages. Attempting to open a websocket connection fails immediately, as expected. Thoughts --------- 1. Starting Tomcat 7.0.65 with Java 6 logs a nice warning: 26.11.2015 19:12:19 org.apache.tomcat.websocket.server.WsSci onStartup INFO: JSR 356 WebSocket (Java WebSocket 1.1) support is not available when running on Java 6. To suppress this message, run Tomcat on Java 7, remove the WebSocket JARs from $CATALINA_HOME/lib or add the WebSocket JARs to the tomcat.util.scan.DefaultJarScanner.jarsToSkip property in $CATALINA_BASE/conf/catalina.properties. Note that the deprecated Tomcat 7 WebSocket API will be available. The above warning message is no longer written by 7.0.66. Tomcat 7.0.66 just fails. 2. An update to installation instructions (RUNNING.txt) is needed. Currently it says to unpack the binary archive, but with Java 6 that is no longer enough. 3. An update to Windows installer is needed. If I remember correctly, there is no option to omit those jar files when installing Tomcat.
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.