Environment variables not available in websocket

Viewed 779

I want to access an environment variable, defined in the web.xml, in an instance of a javax WebSocket, running with jetty9.

I can access the environment variable in any servlet, or the onOpen method of the WebSocket, but not in the onMessage method of the WebSocket

web.xml :

<env-entry>
    <env-entry-name>entry</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>env value</env-entry-value>
</env-entry>

WebSocket.java :

package com.example;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

@ServerEndpoint("/ws")
public class WebSocket {

    public String getEntry(Session session) {
        try {
            InitialContext ctx = new InitialContext();
            return (String) ctx.lookup("java:comp/env/entry");
        } catch (NamingException e) {
            e.printStackTrace();
            return null;
        }
    }

    @OnOpen
    public void onOpen(Session session) throws IOException {
        String entry = getEntry(session);
        System.out.println("onOpen: entry = " + (entry != null ? entry : "Not found"));
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        String entry = getEntry(session);
        System.out.println("onMessage: entry = " + (entry != null ? entry : "Not found"));
    }

}

pom.xml :

<dependencies>
    <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <webappDirectory>${webAppDirectory}</webappDirectory>
            </configuration>
        </plugin>
    </plugins>
</build>

Output:

onOpen: entry = env value
onMessage: entry = Not found
javax.naming.NameNotFoundException; remaining name 'env/entry'
    at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:538)
    at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:569)
    at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:584)
    at org.eclipse.jetty.jndi.java.javaRootURLContext.lookup(javaRootURLContext.java:108)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at com.example.WebSocket.getEntry(WebSocket.java:17)
    at com.example.WebSocket.onMessage(WebSocket.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.jetty.websocket.common.events.annotated.CallableMethod.call(CallableMethod.java:70)
    at org.eclipse.jetty.websocket.jsr356.annotations.OnMessageTextCallable.call(OnMessageTextCallable.java:60)
    at org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents.callText(JsrEvents.java:189)
    at org.eclipse.jetty.websocket.jsr356.endpoints.JsrAnnotatedEventDriver.onTextMessage(JsrAnnotatedEventDriver.java:377)
    at org.eclipse.jetty.websocket.common.message.SimpleTextMessage.messageComplete(SimpleTextMessage.java:69)
    at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.appendMessage(AbstractEventDriver.java:65)
    at org.eclipse.jetty.websocket.jsr356.endpoints.JsrAnnotatedEventDriver.onTextFrame(JsrAnnotatedEventDriver.java:359)
    at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.incomingFrame(AbstractEventDriver.java:161)
    at org.eclipse.jetty.websocket.common.WebSocketSession.incomingFrame(WebSocketSession.java:309)
    at org.eclipse.jetty.websocket.common.extensions.ExtensionStack.incomingFrame(ExtensionStack.java:214)
    at org.eclipse.jetty.websocket.common.Parser.notifyFrame(Parser.java:220)
    at org.eclipse.jetty.websocket.common.Parser.parse(Parser.java:258)
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.readParse(AbstractWebSocketConnection.java:632)
    at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:480)
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
    at java.lang.Thread.run(Thread.java:748)
3 Answers

Note: The following is probably not "best practice" and may not be guaranteed to work on all containers, but works for me on Tomcat, and may be of use to others?

You can assign the context to an instance variable in onOpen, and then use that same instance variable in onMessage.

@ServerEndpoint("/ws")
public class WebSocket {

    private Context envContext;

    public String getEntry(Session session) {
        try {
            return this.envContext.lookup("entry");
        } catch (NamingException e) {
            e.printStackTrace();
            return null;
        }
    }

    @OnOpen
    public void onOpen(Session session) throws IOException {
        try {
            InitialContext ctx = new InitialContext();
            this.envContext = ctx.lookup("java:comp/env");
        } catch (NamingException e) {
            e.printStackTrace();
            return null;
        }

        String entry = getEntry(session);
        System.out.println("onOpen: entry = " + (entry != null ? entry : "Not found"));
    }

    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        String entry = getEntry(session);
        System.out.println("onMessage: entry = " + (entry != null ? entry : "Not found"));
    }

}
Related