4

I'm writing some integration tests of my @ServerEndpoint, and after finally getting the endpoint to run, I now get a nullpointer in @OnOpen because injection fails.

I've uploaded the code on github: https://github.com/runarhk/Websockets-Test

The endpoints are defined like this:

@ServerEndpoint("/test")
public class MyEndpoint{

    @Inject
    private SessionHandler sessionHandler;

    @OnOpen
    public void open(Session session) {
        sessionHandler.addSession(session);//sessionhandler is @Singleton
    }

    @OnClose
    public void close(Session session) {
    }

    @OnError
    public void onError(Throwable error) {
    }

    @OnMessage
    public void handleMessage(String payload, Session session) {
    }
}

@Singleton
public class SessionHandler {
    public void addSession(Session session){}

}

@ClientEndpoint
public class SocketClient {

    @OnOpen
    public void onOpen(Session session) {
    }

    @OnMessage
    public void onMessage(String message, Session session) {
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        LOGGER.info(String.format("Session %s close because of %s",     session.getId(), closeReason));
    }

    public SocketClient openConnection(URL url) {//URL injected arquillian resource, where url is for http connection..
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        try {
            SocketClient  client = new SocketClient();
            URI uri = URI.create(url.toString().replace("http", "ws") + "test");
            container.connectToServer(client, uri);
            return client;
        } catch (DeploymentException | IOException ex) {
            LOGGER.log(Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }
    }

    public void closeConnection() {
        try {
            session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Client requested close"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

My test is written in spock, which fails in setup

@RunWith(ArquillianSputnik)
class SocketIT extends Specification {

    @Deployment
    public static Archive archive() {
       return ShrinkWrap.create(WebArchive.class, "test-sockets.war")
           .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"))
           .addClasses(MyEndpoint.class, SessionHandler.class);
    }
    @ArquillianResource
    URL url;

    SocketClient client;

    def setup() {
        client = SocketClient.openConnection(url);
    }

    def cleanup() {
        client.closeConnection();
    }

    def 'test connection'() {
        given: 'payload'
            def payload = "abc"
        when: 'sending payload'
            client.sendMessage(payload)
        then: 'it should not fail'
            ass
    }
}

My pom:

<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/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>slimy</groupId>
    <artifactId>test</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <tomee.version>1.7.2</tomee.version>
        <tomcat.version>7.0.65</tomcat.version>
    </properties>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.5</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.18</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.gmavenplus</groupId>
                <artifactId>gmavenplus-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.jboss.arquillian</groupId>
                <artifactId>arquillian-bom</artifactId>
                <version>1.1.5.Final</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- TEST DEPENDENCIES  -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.spock</groupId>
            <artifactId>arquillian-spock-container</artifactId>
            <version>1.0.0.Beta3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <version>0.7-groovy-2.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.1.8</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat7-websocket</artifactId>
            <version>${tomcat.version}</version>
            <scope>test</scope>
        </dependency>
        <!-- For Arquillian Integration tests in TOMEE -->
        <dependency>
            <groupId>org.apache.openejb</groupId>
            <artifactId>arquillian-tomee-embedded</artifactId>
            <version>${tomee.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.openejb</groupId>
            <artifactId>tomee-embedded</artifactId>
            <version>${tomee.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

My Arquillian.xml file looks like this:

<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://jboss.org/schema/arquillian"
        xsi:schemaLocation="http://jboss.org/schema/arquillian http://www.jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <container qualifier="tomee" default="true">
        <configuration>
            <property name="httpPort">-1</property>
            <property name="stopPort">-1</property>
        </configuration>
    </container>
</arquillian>

Edit: I just downloaded tomee 1.7.2-plus and ran my application there. It works like a charm. So this might be related to the tomee-embedded not being a plus-variant?

Edit: The Log from when running the test:

INFO: OpenWebBeans Container is starting...
nov 12, 2015 7:06:28 PM org.apache.webbeans.plugins.PluginLoader startUp
INFO: Adding OpenWebBeansPlugin : [CdiPlugin]
nov 12, 2015 7:06:28 PM org.apache.webbeans.plugins.PluginLoader startUp
INFO: Adding OpenWebBeansPlugin : [OpenWebBeansJsfPlugin]
nov 12, 2015 7:06:28 PM org.apache.webbeans.config.BeansDeployer validateInjectionPoints
INFO: All injection points were validated successfully.
nov 12, 2015 7:06:28 PM org.apache.openejb.cdi.OpenEJBLifecycle startApplication
INFO: OpenWebBeans Container has started, it took 255 ms.
nov 12, 2015 7:06:28 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Created Ejb(deployment-id=SessionHandler, ejb-name=SessionHandler, container=Default Singleton Container)
nov 12, 2015 7:06:28 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Started Ejb(deployment-id=SessionHandler, ejb-name=SessionHandler, container=Default Singleton Container)
nov 12, 2015 7:06:28 PM org.apache.openejb.assembler.classic.Assembler createApplication
INFO: Deployed Application(path=C:\Users\RunarKristiansen\AppData\Local\Temp\arquillian-tomee-app-working-dir\0\test-sockets)
nov 12, 2015 7:06:29 PM socket.MyEndpoint onError
SEVERE: null
java.lang.NullPointerException
    at socket.MyEndpoint.open(MyEndpoint.java:24)
    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:497)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:66)
    at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:70)
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:138)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:651)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

nov 12, 2015 7:06:29 PM org.apache.tomcat.websocket.pojo.PojoEndpointBase onClose
SEVERE: Failed to call onClose method of POJO end point for POJO of type [socket.MyEndpoint]
java.lang.reflect.InvocationTargetException
    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:497)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.onClose(PojoEndpointBase.java:107)
    at org.apache.tomcat.websocket.WsSession.fireEndpointOnClose(WsSession.java:501)
    at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:456)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:422)
    at org.apache.tomcat.websocket.WsSession.close(WsSession.java:416)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.handleOnOpenError(PojoEndpointBase.java:96)
    at org.apache.tomcat.websocket.pojo.PojoEndpointBase.doOnOpen(PojoEndpointBase.java:79)
    at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:70)
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:138)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:651)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at socket.MyEndpoint.close(MyEndpoint.java:29)
    ... 19 more

nov 12, 2015 7:06:29 PM utils.SocketClient onClose
INFO: Session 0 close because of CloseReason: code [1000], reason [null]

java.lang.IllegalStateException: The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session
    at org.apache.tomcat.websocket.WsSession.checkState(WsSession.java:710)
    at org.apache.tomcat.websocket.WsSession.getBasicRemote(WsSession.java:409)
    at utils.SocketClient.sendMessage(SocketClient.java:64)
    at socket.SocketIT.test connection(SocketIT.groovy:42)

nov 12, 2015 7:06:29 PM org.apache.openejb.assembler.classic.Assembler destroyApplication
INFO: Undeploying app: C:\Users\RunarKristiansen\AppData\Local\Temp\arquillian-tomee-app-working-dir\0\test-sockets
nov 12, 2015 7:06:30 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-bio-20001"]
nov 12, 2015 7:06:30 PM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-bio-20001"]
nov 12, 2015 7:06:30 PM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service Tomcat
nov 12, 2015 7:06:30 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-bio-20001"]`
Runar Halse
  • 3,528
  • 10
  • 39
  • 59
  • You package a SessionHandler in your deployable war but shows a GameSessionHandler. Can you maybe edit your post to reflect what you have? – Franck Nov 12 '15 at 13:20
  • sorry about that, fixed now, and I think all the code needed to reproduce is supplied in the post – Runar Halse Nov 12 '15 at 13:45
  • You're still showing a GameSessionHandler type without definition. Anyway I suggest to look at the logs produced by tom-ee/open-webbeans component to see if beans (i.e. SessionHandler) are silently not loaded for some reason (e.g. referenced classes not available in the archive). You can customize logging if needed with http://tomee.apache.org/configuring-logging-in-tests.html – Franck Nov 12 '15 at 15:10
  • Have you tried to add to the file `arquillian.xml` a line ``? – G. Demecki Nov 13 '15 at 09:16
  • that just made the container unable to start, and adding the `javax.servlet:javax.servlet-api` dependency does not fix it.. – Runar Halse Nov 13 '15 at 12:17

0 Answers0