kevguy
kevguy

Reputation: 4438

Embedded Tomcat gives "did not permit the HTTP upgrade to WebSocket" error

I've been trying to develop an webapp with embedded Tomcat that have both @WebServlet (for serving webpages and RESTful requests) and a @ServerEndpoint (websocket). So far it's working fine on my Intellij. However, when I build the code with Maven and execute the jar file instead. I always got the following error:

Caused by: javax.websocket.DeploymentException: The HTTP response from the server [HTTP/1.1 404 Not Found] did not permit the HTTP upgrade to WebSocket

The error traces back to my socket client, where I am trying to open a connection:

container.connectToServer(this, endpointURI);

For your information, here's how the client looks like:

@ClientEndpoint
public class SocketClient {

    Session userSession = null;
    private MessageHandler messageHandler;

    public SocketClient(URI endpointURI) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            container.connectToServer(this, endpointURI);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @OnOpen
    public void onOpen(Session userSession) {
        System.out.println("opening websocket");
        this.userSession = userSession;
    }

    @OnClose
    public void onClose(Session userSession, CloseReason reason) {
        System.out.println("closing websocket");
        this.userSession = null;
    }

    @OnMessage
    public void onMessage(String message) {
        if (this.messageHandler != null) {
            this.messageHandler.handleMessage(message);
        }
    }

    public void addMessageHandler(MessageHandler msgHandler) {
        this.messageHandler = msgHandler;
    }

    public void sendMessage(String message) {
        this.userSession.getAsyncRemote().sendText(message);
    }

    public static interface MessageHandler {
        public void handleMessage(String message);
    }
}

And my websocket endpoint is defined as follows:

@ServerEndpoint(
    value="/hi",
    decoders = MessageDecoder.class,
    encoders = MessageEncoder.class )
public class SocketEndpoint {

    private Session session;

    private static Set<SocketEndpoint> chatEndpoints
            = new CopyOnWriteArraySet<>();

    public SocketEndpoint() {
        System.out.println("class loaded " + this.getClass());
    }

    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        chatEndpoints.add(this);
        System.out.println(session.getId() + " has open a connection");
        try {
            session.getBasicRemote().sendText("Connection Established");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(Message message, Session session) { /* ... */}

    @OnClose
    public void onClose(Session session) { /* ... */}

    @OnError
    public void onError(Session session, Throwable throwable) { /* ... */ }    
}

Like I said, it's working fine when I run the code on Intellij, but interestingly, when I hover over SocketEndpoint, I'll get a tooltip saying this class is never used while other HttpServlet classes they didn't have such problems. I also verified by checking if the SocketEndpoint class is loaded (look at the constructor), which it doesn't when I execute the jar.

And whatever dependencies (that maybe) needed I've already added them (pom.xml):

<properties>
    <tomcat.version>8.0.28</tomcat.version>
    <gson.version>2.8.0</gson.version>
    <junit.jupiter.version>5.2.0</junit.jupiter.version>
    <junit.platform.version>1.2.0</junit.platform.version>
    <junit.vintage.version>5.2.0</junit.vintage.version>
    <log4j2.version>2.8.2</log4j2.version>
    <maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-logging-juli</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper-el</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jsp-api</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-websocket</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper-el</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jsp-api</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-engine</artifactId>
        <version>${junit.platform.version}</version>
    </dependency>
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-runner</artifactId>
        <version>${junit.platform.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>${junit.vintage.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-migrationsupport</artifactId>
        <version>${junit.vintage.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-client-api</artifactId>
        <version>1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>${gson.version}</version>
    </dependency>
</dependencies>

Any help would be appreciated. I saw most of the people who encounter a similar problem are using Spring, which I didn't.

Upvotes: 1

Views: 7553

Answers (1)

GnanaJeyam
GnanaJeyam

Reputation: 3170

The error displays as your client trying to connect to Web-socket (URL) which is not found.

Caused by: javax.websocket.DeploymentException: The HTTP response from the server [HTTP/1.1 404 Not Found] did not permit the HTTP upgrade to WebSocket

Make sure you specified any context path in your application or find the exact websocket URL.

Upvotes: 2

Related Questions