0

In my JIRA plug-in I have created a WebListener which add a websocket endpoint to the SeverContainer.

The problem is, when I make changes to my plugin and upload it in JIRA, the new code is not executed.

This is because the endpoint is not being deployed again. I get the following exception: Multiple Endpoints may not be deployed to the same path

My weblistener:

@WebListener
public class MyListener implements ServletContextListener {

    private static final Logger LOG = LoggerFactory.getLogger(MyListener.class);

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        final ServerContainer serverContainer = (ServerContainer) servletContextEvent.getServletContext()
                .getAttribute("javax.websocket.server.ServerContainer");
        try {
            serverContainer.addEndpoint(MyWebsocket.class); //Generates exception when the plug-in is updated
        } catch (DeploymentException e) {
            LOG.error("Error adding endpoint to the servercontainer: " + e.getMessage());
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        LOG.error("CONTEXT DESTROYED!");
    }
}

My websocket:

@ServerEndpoint(value = "/websocket/{myPathParam}")
public class MyWebsocket {

    private static final Logger LOG = LoggerFactory.getLogger(MyWebsocket.class);

    @OnOpen
    public void onOpen(Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnOpen");
    }

    @OnClose
    public void onClose(Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnClose");
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnMessage: " + message);
    }
}

Is there a way to remove the endpoint from the servercontainer, so it will be deployed again?

Mike
  • 137
  • 1
  • 13
  • I believe this can help you http://stackoverflow.com/questions/17936440/accessing-httpsession-from-httpservletrequest-in-a-web-socket-serverendpoint – Ghayel Jan 19 '16 at 18:20

1 Answers1

0

In the specification, I did not find any way to deactivate a websocket. The same applies for ServletContextListeners. They can only be added. So you need a workaround.

I suggest, that you do not replace the MyEndpoint.class, but make it a proxy that will call an implementation. Thus, the endpoint will not be required to re-register and the new proxy class calls the new code, when it is deployed.

So, you can just safely ignore the DeploymentException in your code, because you change the MyWebsocket.class as follows:

@ServerEndpoint(value = "/websocket/{myPathParam}")
public class MyWebsocket {

    private static final Logger LOG = LoggerFactory.getLogger(MyWebsocket.class);

    @OnOpen
    public void onOpen(Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnOpen");
        WebSocketImpl impl = ImplementationFactory.get(MyWebsocket.class);
        impl.onOpen(session, myPathParam);
    }

    @OnClose
    public void onClose(Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnClose");
        WebSocketImpl impl = ImplementationFactory.get(MyWebsocket.class);
        impl.onClose(session, myPathParam);
    }

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("myPathParam") String myPathParam) {
        LOG.error("OnMessage: " + message);
        WebSocketImpl impl = ImplementationFactory.get(MyWebsocket.class);
        impl.onMessage(message, session, myPathParam);
    }
}

I understand, that this will not really answer your question, but it is a solution how to work around the missing remove options.

One problem is there with this workaround: It will fix your interface, you cannot add parameters in a new version of the plugin.

To enable this, you add another websocket by adding another context listener (V7 has been choosen at random):

@WebListener
public class MyListener_V7 implements ServletContextListener {

private static final Logger LOG = LoggerFactory.getLogger(MyListener_V7.class);

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    final ServerContainer serverContainer = (ServerContainer) servletContextEvent.getServletContext()
            .getAttribute("javax.websocket.server.ServerContainer");
    try {
        serverContainer.addEndpoint(MyWebsocket_V7.class); //Generates exception when the plug-in is updated
    } catch (DeploymentException e) {
        LOG.error("Error adding endpoint to the servercontainer: " + e.getMessage());
    }
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    LOG.error("CONTEXT DESTROYED!");
}
}

@ServerEndpoint(value = "/websocket_V7/{myPathParam}")
public class MyWebsocket_V7 {

private static final Logger LOG = LoggerFactory.getLogger(MyWebsocket.class);

This will litter the JIRA instance with endpoints until a restart happens. But if you mix the two suggestions, you will only add a new endpoint every once in a while.

thst
  • 4,592
  • 1
  • 26
  • 40