Search code examples
websocketundertow

Embedded Undertown deploy websocket and servlet at same time, not work


I am new using undertow, I'm developing a stand alone application that will use this as embedded server. I wish I could deploy web sockets, servlets, and restfull htmls services within my embedded undertow.

So far I've only done the test with web sockets and servlets, the problem that each separate function properly, but deploy them together web sockets not I access from a test page with HTML and JavaScript, if I remove the servlet page nigun test runs without error.

This is my code:

    /*
     * Create the  appWebSocketDeploymentInfo and configure
     */
    WebSocketDeploymentInfo appWebSocketDeploymentInfo = new WebSocketDeploymentInfo();
    appWebSocketDeploymentInfo.setBuffers(new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 17000, 17000 * 16));
    appWebSocketDeploymentInfo.addEndpoint(WebSocketEndpoint1.class);
    appWebSocketDeploymentInfo.addEndpoint(WebSocketEndpoint2.class);

    /*
     * Create the  appDeploymentInfo and configure
     */
    DeploymentInfo appDeploymentInfo = Servlets.deployment()
                                    .setClassLoader(Server.class.getClassLoader())
                                    .setContextPath("/myapp)
                                    .setDeploymentName("app.war")
                                    .setResourceManager(new FileResourceManager(new File("src/main/webapp"), 1024))
                                    .addServlets(Servlets.servlet("HomeServlet", HomeServlet.class).addMapping("/home"))
                                    .setResourceManager(new ClassPathResourceManager(Server.class.getClassLoader(), Server.class.getPackage()))
                                    .addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, appWebSocketDeploymentInfo);

    /*
     * Create the deploymentManager
     */
    deploymentManager = Servlets.defaultContainer().addDeployment(appDeploymentInfo);

    /*
     * Deploy the app
     */
    deploymentManager.deploy();

    /*
     * Create the path handle
     */
    pathHandler = Handlers.path(Handlers.redirect("/myapp/home")).addPrefixPath("/myapp", deploymentManager.start());

    /*
     * Create the server
     */
    undertowServer = Undertow.builder().addHttpListener(DEFAULT_PORT, DEFAULT_IP).setHandler(pathHandler).build();

The javascript log error is

WebSocket connection to 'ws://localhost:8080/fermat/node-channel' failed: Error during WebSocket handshake: Unexpected response code: 404


Solution

  • After extensive testing and research, I got the right way to do the configuration and start the server, also will add support for other technologies such as:

    • WebSocket
    • Resteasy
    • Weld

    My final code:

    UndertowJaxrsServer server = new UndertowJaxrsServer();
    Undertow.Builder serverBuilder = Undertow.builder().addHttpListener(DEFAULT_PORT, DEFAULT_IP);
    ServletContainer servletContainer = Servlets.defaultContainer();
    
       /*
        * Create the App WebSocketDeploymentInfo and configure
        */
        WebSocketDeploymentInfo appWebSocketDeploymentInfo = new WebSocketDeploymentInfo();
        appWebSocketDeploymentInfo.setBuffers(new    ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 17000, 17000 * 16));
        appWebSocketDeploymentInfo.addEndpoint(WebSocketNodeChannelServerEndpoint.class);
        appWebSocketDeploymentInfo.addEndpoint(WebSocketClientChannelServerEndpoint.class);
    
        /*
         * Create the App ResteasyDeployment and configure
         */
        ResteasyDeployment deployment = new ResteasyDeployment();
        deployment.setApplicationClass(JaxRsActivator.class.getName());
        deployment.setInjectorFactoryClass("org.jboss.resteasy.cdi.CdiInjectorFactory");
    
        /*
         * Create the App DeploymentInfo and configure
         */
        DeploymentInfo appDeploymentInfo  = server.undertowDeployment(deployment, APP_NAME);
        appDeploymentInfo.setClassLoader(FermatEmbeddedNodeServer.class.getClassLoader())
                        .setContextPath(APP_NAME)
                        .setDeploymentName(WAR_APP_NAME)
                        .addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, appWebSocketDeploymentInfo)
                        .addServlets(Servlets.servlet("HomeServlet", HomeServlet.class).addMapping("/home"))
                        .addListeners(Servlets.listener(org.jboss.weld.environment.servlet.Listener.class));
    
        server.deploy(appDeploymentInfo);
        server.start(serverBuilder);
    

    Gradle dependencies

    compile 'io.undertow:undertow-core:1.3.6.Final'
    compile 'io.undertow:undertow-servlet:1.3.6.Final'
    compile 'io.undertow:undertow-websockets-jsr:1.3.6.Final'
    
    compile 'org.jboss.resteasy:resteasy-undertow:3.0.13.Final'
    compile 'org.jboss.resteasy:resteasy-cdi:3.0.13.Final'
    compile 'org.jboss.weld.servlet:weld-servlet:2.3.1.Final'
    
    compile 'javax:javaee-api:7.0'