Передача объекта из программного развертывания сервлета Undertow JSR-356 в экземпляр ServerEndpoint? - PullRequest
0 голосов
/ 08 июня 2019

Я пытаюсь программно создать сервлет 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 это просто не работает. Объект всегда нулевой.

Хотя в конечном итоге я просто хочу иметь возможность передавать произвольный объект (ы) со стороны развертывания на сам экземпляр без использования какого-либо статического метода взлома.

...