Hi Team , We planned to upgrade both guacamole and apache tomcat from 1.5.2 and 9.75.0 to 1.5.3 and 10.1.13 respectively , then came to know that there is a significant change from Tomcat 9.0.x and Tomcat 10.0.x. The Java package used by the specification APIs has changed from javax to jakarta. The problem arises here in guacamole where it still uses Javax servlets and other libraries which only support javax.
*What we tried :-* We tried to migrate Guacamole using the Apache Tomcat migration tool for Jakarta EE <https://tomcat.apache.org/download-migration.cgi> , moreover made changes in pom.xml and web.xml files in guacamole.war files to make the guacamole compatible with Jakarta. But still the errors occur due to mismatch in the configurations with Tomcat Jakarta Servlets and Guacamole. *Errors we got:* 1. java.lang.NoClassDefFoundError:javax/servlet/ServletContextListener 2. java.lang.NoSuchMethodError: 'void jakarta.servlet.http.HttpServletResponse.setStatus(int, java.lang.String)' at org.glassfish.jersey.servlet.internal.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:147) Were able to fix the first error after making changes in pom.xml and using the tomcat migration tool for Jakarta,but the second error still exists even after we changed the versions of all including *jersey server and client*. pom.xml and web.xml files are attached for reference.
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole</artifactId> <packaging>war</packaging> <version>1.5.3</version> <name>guacamole</name> <url>http://guacamole.apache.org/</url> <parent> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-client</artifactId> <version>1.5.3</version> <relativePath>../</relativePath> </parent> <description> The Guacamole web application, providing authentication and an HTML5 remote desktop client. </description> <!-- All applicable licenses --> <licenses> <license> <name>Apache License, Version 2.0</name> <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url> <distribution>repo</distribution> </license> </licenses> <!-- Git repository --> <scm> <url>https://github.com/apache/guacamole-client</url> <connection>scm:git:https://git.wip-us.apache.org/repos/asf/guacamole-client.git</connection> </scm> <build> <plugins> <!-- Build AngularJS portion of application using NPM --> <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.11.3</version> <configuration> <workingDirectory>src/main/frontend</workingDirectory> <installDirectory>${project.build.directory}</installDirectory> </configuration> <executions> <execution> <id>install-node-and-npm</id> <goals> <goal>install-node-and-npm</goal> </goals> <configuration> <nodeVersion>v14.16.0</nodeVersion> </configuration> </execution> <execution> <id>npm-ci</id> <goals> <goal>npm</goal> </goals> <configuration> <arguments>ci</arguments> </configuration> </execution> <execution> <id>npm-build</id> <phase>generate-resources</phase> <goals> <goal>npm</goal> </goals> <configuration> <arguments>run build</arguments> </configuration> </execution> </executions> </plugin> <!-- Copy automatically-generated set of NPM module dependencies for later use by LICENSE generator --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <executions> <execution> <id>copy-npm-dependency-list</id> <phase>generate-resources</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${dependency.list.directory}</outputDirectory> <resources> <resource> <directory>src/main/frontend/dist</directory> <includes> <include>npm-dependencies.txt</include> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin> <!-- Automatically generate LICENSE and NOTICE --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <id>generate-license-files</id> <phase>generate-resources</phase> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.1</version> <configuration> <webResources> <!-- Add frontend folder to war package ... --> <resource> <directory>src/main/frontend/dist</directory> <excludes> <exclude>translations/*.json</exclude> <exclude>index.html</exclude> <exclude>verifyCachedVersion.js</exclude> </excludes> </resource> <!-- ... but filter index.html and translation strings --> <resource> <directory>src/main/frontend/dist</directory> <filtering>true</filtering> <includes> <include>translations/*.json</include> <include>index.html</include> <include>verifyCachedVersion.js</include> </includes> </resource> <!-- Include all licenses within META-INF --> <resource> <directory>${project.build.directory}/licenses</directory> <targetPath>META-INF</targetPath> </resource> </webResources> <!-- Add files from guacamole-common-js --> <overlays> <overlay> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-common-js</artifactId> <type>zip</type> </overlay> </overlays> </configuration> <executions> <execution> <id>default-cli</id> <phase>process-resources</phase> <goals> <goal>exploded</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <!-- Jakarta servlet API --> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.servlet.jsp</groupId> <artifactId>jakarta.servlet.jsp-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jakarta.inject</groupId> <artifactId>jakarta.inject-api</artifactId> </dependency> <dependency> <groupId>jakarta.el</groupId> <artifactId>jakarta.el-api</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> <!-- Jakarta WebSocket API --> <dependency> <groupId>jakarta.websocket</groupId> <artifactId>jakarta.websocket-api</artifactId> <version>2.1.0</version> <scope>provided</scope> </dependency> <!-- Logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <exclusions> <!-- Exclude optional dependency on JavaMail --> <exclusion> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> </exclusion> </exclusions> </dependency> <!-- Guacamole Extension API --> <dependency> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-ext</artifactId> <version>1.5.3</version> </dependency> <!-- Guacamole JavaScript API --> <dependency> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-common-js</artifactId> <version>1.5.3</version> <type>zip</type> <scope>runtime</scope> </dependency> <!-- Jetty 8 servlet API (websocket) --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-websocket</artifactId> <version>8.1.1.v20120215</version> <scope>provided</scope> </dependency> <!-- Jetty 9.0 servlet API (websocket) --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-parent</artifactId> <version>20</version> <scope>provided</scope> <type>pom</type> </dependency> <dependency> <groupId>org.eclipse.jetty.websocket</groupId> <artifactId>websocket-api</artifactId> <version>9.0.7.v20131107</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.eclipse.jetty.websocket</groupId> <artifactId>websocket-servlet</artifactId> <version>9.0.7.v20131107</version> <scope>provided</scope> </dependency> <!-- Tomcat servlet API (websocket) --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>7.0.37</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>7.0.37</version> <scope>provided</scope> </dependency> <!-- Guice - Dependency Injection --> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>7.0.0</version> </dependency> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice</artifactId> <version>5.1.0-rc.2</version> </dependency> <dependency> <groupId>com.google.inject.extensions</groupId> <artifactId>guice-assistedinject</artifactId> <version>7.0.0</version> </dependency> <dependency> <groupId>ru.vyarus.guice.jakarta</groupId> <artifactId>guice-assistedinject</artifactId> <version>5.1.0-rc.2</version> </dependency> <dependency> <groupId>com.google.inject.extensions</groupId> <artifactId>guice-servlet</artifactId> <version>7.0.0</version> </dependency> <!-- Jersey Implementation --> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>guice-bridge</artifactId> <version>3.0.4</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>3.1.3</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>listenablefuture</artifactId> <version>1.0</version> </dependency> <!-- jakarta annotations --> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>2.1.1</version> </dependency> <!-- Guava Base Libraries --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> <!-- Force use of version 1.2.2 (transitive dependencies of jersey-media-json-jackson disagree on 1.2.1 vs. 1.2.2) --> <dependency> <groupId>jakarta.activation</groupId> <artifactId>jakarta.activation-api</artifactId> <version>2.0.1</version> </dependency> </dependencies> </project>
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <web-app version="6.0" xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"> <!-- Basic config --> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- Request that the browser always revalidate its cached copy of index.html --> <filter> <filter-name>cacheRevalidationFilter</filter-name> <filter-class>org.apache.guacamole.CacheRevalidationFilter</filter-class> </filter> <filter-mapping> <filter-name>cacheRevalidationFilter</filter-name> <url-pattern>/index.html</url-pattern> </filter-mapping> <!-- Route all requests through Guice --> <filter> <filter-name>guiceFilter</filter-name> <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> </filter> <filter-mapping> <filter-name>guiceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.apache.guacamole.GuacamoleServletContextListener</listener-class> </listener> <!-- Audio file mimetype mappings --> <mime-mapping> <extension>mp3</extension> <mime-type>audio/mpeg</mime-type> </mime-mapping> <mime-mapping> <extension>ogg</extension> <mime-type>audio/ogg</mime-type> </mime-mapping> </web-app>