Я пытаюсь программно создать сервлет WebSocket (JSR-356), используя JBoss Undertow, с возможностью передачи зависимости (например, «myObject» ниже) из метода, в котором я создаю сервер / развертывание Undertow в экземпляр ServerEndpoint что это позже создает.
Поскольку созданием экземпляра управляет Undertow, я не могу просто передать зависимость в конструктор. Я пытался использовать атрибут ServerContext, так как он, кажется, потенциально может быть выставлен на обоих концах, но возникают проблемы с доступом к нему на стороне ServerEndpoint без обращения к отражению.
Код развертывания:
UUID myObject = UUID.randomUUID()
Xnio xnio = Xnio.getInstance("nio", Undertow.class.getClassLoader());
XnioWorker xnioWorker = xnio.createWorker(OptionMap.builder()
.set(Options.WORKER_IO_THREADS, 1)
.set(Options.WORKER_TASK_CORE_THREADS, 3)
.set(Options.WORKER_TASK_MAX_THREADS, 5)
.set(Options.TCP_NODELAY, true)
.getMap());
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo().addEndpoint(WSMicroServer.class);
DeploymentInfo websocketDeployment = Servlets.deployment().setDeploymentName("DSA-Agent-WebSocket")
.setClassLoader(WSInterface.class.getClassLoader())
.setContextPath(contextPath)
.addServletContextAttribute("myObject", myObject)
.addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, webSocketDeploymentInfo);
DeploymentManager manager = Servlets.defaultContainer().addDeployment(websocketDeployment);
manager.deploy();
Undertow server = Undertow.builder()
.setHandler(Handlers.path().addPrefixPath(websocketDeployment.getContextPath(), manager.start()))
.addHttpListener(port, bindHost)
.setWorker(xnioWorker)
.build();
server.start();
Код ServerEndpoint:
@ServerEndpoint(value = "/", configurator = WSMicroServer.ServletAwareConfig.class)
public class WSMicroServer
{
private UUID myObject = null;
@OnMessage
public void message(Session session, String message) throws IOException
{
System.out.println(myObject + " >>> " + message);
}
public static class ServletAwareConfig extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response)
{
HttpSession httpSession = (HttpSession)request.getHttpSession(); // does not work in WildFly
config.getUserProperties().put("httpSession", httpSession);
//ExchangeHandshakeRequest req = (ExchangeHandshakeRequest)request;
//ServletWebSocketHttpExchange ex = req.exchange;
//HttpServletRequestImpl reqImpl = ex.request;
//ServletContext ctx = reqImpl.getServletContext();
//Object myObj = ctx.getAttribute("myObject");
// How can myObject be set ??
}
}
}
Есть много источников, которые говорят, что вы можете легко получить его, позвонив по HandshakeRequest.getHttpSession в ServerEndpointConfig.Configurator , как в этом ответе: https://stackoverflow.com/a/23405830/1060650
Однако в Undertow это просто не работает. Объект всегда нулевой.
Хотя в конечном итоге я просто хочу иметь возможность передавать произвольный объект (ы) со стороны развертывания на сам экземпляр без использования какого-либо статического метода взлома.