4

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

Marged
  • 10,577
  • 10
  • 57
  • 99
Roberto
  • 169
  • 9
  • Not really an answer to your question, but more a hint: Have you thought of using Spring Boot for this ? It has support for Undertow too and will take care of what you are doing manually in an automatic way. – Marged Nov 13 '15 at 17:20
  • 1
    thanks, but I do not know much about spring and really did not want to use it. – Roberto Nov 13 '15 at 20:31
  • Found this example: https://github.com/fourcube/guice-undertow-websockets – dsmith Jan 06 '17 at 17:09

1 Answers1

4

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'
Roberto
  • 169
  • 9
  • I've tried your approach but can't seem to get injection into websocket endpoints working. Does that work for you? – Robby Cornelissen Jul 27 '16 at 03:31
  • Actually I use dependency injection side RESTful WebService in the endpoints I have not tested. – Roberto Aug 04 '16 at 12:10
  • Yup, injection in the REST endpoints works for me as well. Can't get it to work for the websocket endpoints. It looks like the websocket spec doesn't specify how the integration with CDI is supposed to work, which contexts are in play, etc. – Robby Cornelissen Aug 09 '16 at 08:38
  • Hey so I was able to implement something similar, did you have any work around for the CDI problem. Injecting beans into websocket serverendpoints doesn't seem to work as expected. – thekevshow Oct 07 '16 at 20:33