La integración de WebSocket en proyectos Spring Boot es una práctica común para habilitar comunicación en tiempo real. Sin embargo, al compilar o ejecutar pruebas, especialmente durante el proceso de empaquetado (build), es posible encontrarse con un error que impide el inicio correcto de la aplicación. Este problema se manifiesta con frecuencia a través de una excepción que indica que javax.websocket.server.ServerContainer no está disponible.
El mensaje de error típico en la consola o los logs del servidor se asemejará a la siguiente traza:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serverEndpointExporter' defined in class path resource [com/example/config/WebSocketConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1694)
...
Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
at org.springframework.util.Assert.state(Assert.java:73)
at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:107)
...
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
[ERROR] ApplicationTests.testContextLoads » IllegalState Failed to load ApplicationContext
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
Este error se origina porque la clase ServerEndpointExporter de Spring, encargada de descubrir y registrar los puntos finales (endpoints) de WebSocket, requiere un entorno de contenedor de servlets completamente funcional para acceder al objeto ServerContainer. Cuando se ejceutan pruebas con @SpringBootTest por defecto, el contexto de aplicación podría no inicializar un contenedor de servlets completo o el entorno web necesario para WebSocket, llevanddo a que ServerContainer no sea encontrado.
La solución a este inconveniente radica en configurar la anotación @SpringBootTest en las clases de prueba para que inicie un entorno web adecuado. Al especificar webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, le indicamos a Spring Boot que inicie un servidor web incrustado (como Tomcat, Jetty o Undertow) en un puerto aleatorio, proporcionando así el ServerContainer necesario para la inicialización de los componentes de WebSocket.
A continuación, se muestra cómo aplicar esta configuración en una clase de prueba:
package com.example.testing;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class WebSocketApplicationIntegrationTest {
@Test
void applicationContextLoadsSuccessfully() {
// Este test simplemente verifica que el contexto de Spring Boot
// se carga correctamente con soporte para WebSocket.
// No se requiere lógica adicional para demostrar la solución del error.
}
// Otros métodos de prueba para componentes WebSocket o servicios de la aplicación
}
Al incluir webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT en las pruebas que interactúan o dependen de la configuración de WebSocket, se asegura que el entorno de ejecución de la prueba replique las condiciones de un despliegue real, permitiendo que ServerEndpointExporter encuentre y utilice corectamente el javax.websocket.server.ServerContainer.