GithubHelp home page GithubHelp logo

dropwizard-websockets's Introduction

Dropwizard Websocket Support

Build Status Maven Central Coverage Status

A 3rd party Dropwizard bundle, that enhances Dropwizard capabilities to support not only JAX-RS resources but also websockets endpoints using the JSR-356 API.

The websockets endpoints will be instrumented the same way Dropwizards does with JAX-RS resources, and their metrics will be exposed in the same way. This includes:

  • Counters of current open sessions.
  • Counters and rate meters for new connections.
  • Counters and rate meters for messages reviewed by the endpoint.
  • Timers and statistics for session duration.

Maven Dependency

Add the Maven dependency:

<dependency>
  <groupId>com.liveperson</groupId>
  <artifactId>dropwizard-websockets</artifactId>
  <version></version>
</dependency>

Usage

In your code you should add the WebsocketBundle in the initialization stage of the Application. Give the bundle your endpoints classes (or ServerEndpoindConfig in case of programmatic endpoints) as parameters:

public void initialize(Bootstrap<Configuration> bootstrap) {
    bootstrap.addBundle(new WebsocketBundle(MyWebSocket1.class, MyWebSocket2.class));
}

Or, if you prefer, you can register the endpoint before the running stage:

public void initialize(Bootstrap<Configuration> bootstrap) {
    websocketBundle = new WebsocketBundle();        
    bootstrap.addBundle(websocketBundle);
}

@Override
public void run(Configuration configuration, Environment environment) throws Exception {
    // Using BasicServerEndpointConfig lets you inject objects to the websocket endpoint:
    final BasicServerEndpointConfig bsec = new BasicServerEndpointConfig(EchoServer.class, "/extends-ws");
    // bsec.getUserProperties().put(Environment.class.getName(), environment);
    // Then you can get it from the Session object
    // - obj = session.getUserProperties().get("objectName");            
    websocketBundle.addEndpoint(bsec);
}

That's all. A full example can be found in the tests classes.

Metrics

In order to collect metrics on your endpoints, you should annotate them with metrics annotations:

@Metered
@Timed
@ExceptionMetered
@ServerEndpoint("/annotated-ws")
public static class AnnotatedEchoServer {
    @OnOpen
    public void myOnOpen(final Session session) throws IOException {
        session.getAsyncRemote().sendText("welcome");
    }

    @OnMessage
    public void myOnMsg(final Session session, String message) {
        session.getAsyncRemote().sendText(message.toUpperCase());
    }

    @OnClose
    public void myOnClose(final Session session, CloseReason cr) {
    }
}

Then you'll be able to see your metrics as follows:

{
  "counters" : {
    "io.dropwizard.websockets.MyApp$AnnotatedEchoServer.openConnections" : {
      "count" : 2
    }
  },
  "meters" : {
    "io.dropwizard.websockets.MyApp$AnnotatedEchoServer.OnError" : {
      "count" : 0,
      "m15_rate" : 0.0,
      "m1_rate" : 0.0,
      "m5_rate" : 0.0,
      "mean_rate" : 0.0,
      "units" : "events/second"
    },
    "io.dropwizard.websockets.MyApp$AnnotatedEchoServer.OnMessage" : {
      "count" : 3,
      "m15_rate" : 0.6,
      "m1_rate" : 0.6,
      "m5_rate" : 0.6,
      "mean_rate" : 0.3194501069682357,
      "units" : "events/second"
    }
  },
  "timers" : {
    "io.dropwizard.websockets.MyApp$AnnotatedEchoServer" : {
      "count" : 1,
      "max" : 0.101819137,
      "mean" : 0.101819137,
      "min" : 0.101819137,
      "p50" : 0.101819137,
      "p75" : 0.101819137,
      "p95" : 0.101819137,
      "p98" : 0.101819137,
      "p99" : 0.101819137,
      "p999" : 0.101819137,
      "stddev" : 0.0,
      "m15_rate" : 0.2,
      "m1_rate" : 0.2,
      "m5_rate" : 0.2,
      "mean_rate" : 0.10647618704871187,
      "duration_units" : "seconds",
      "rate_units" : "calls/second"
    }
  }
}

Alternatives

See also dropwizard-websocket-jee7-bundle.

dropwizard-websockets's People

Contributors

dinomite avatar eitan101 avatar johndashbase avatar kebernet avatar syllant avatar vemilyus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dropwizard-websockets's Issues

Support to Dropwizard authentication

Hi!

It is possible use the default io.dropwizard.auth with dropwizard-websockets?
In our project we are using OAuth authenticantion in resources.

I'm testing this class

@Timed(name = "timed")
@Metered(name = "metered")
@ExceptionMetered(name = "exception")
@ServerEndpoint("/socket")
@PermitAll
public class NotificationSocket {

    @OnOpen
    public void myOnOpen(final Session session) throws IOException {
        System.out.println("Principal: " + session.getUserPrincipal());
        session.getAsyncRemote().sendText("welcome");
    }

    @OnMessage
    public void myOnMsg(final Session session, String message) {
        session.getAsyncRemote().sendText(message);
    }

    @OnClose
    public void myOnClose(final Session session, CloseReason cr) {
    }

}

with this simple node script:

var WebSocket = require('ws')

const options = {
    headers: {
        'Authorization': 'Bearer token' // token is a system generated string
    }
}

const ws = new WebSocket('ws://localhost:58040/socket', options)
ws.on('message', function incoming(data) {
  console.log(data);
})

and the Principal always is null.

I want to associate each session ith the logged user.

Thanks!

Websocket Bundle cannot be initialised with zero arg constructor

Dropwizard 1.3.0
Dropwizard-websockets 1.3.2

In the docs it shows the possibility to create a Websocket bundle object in the Dropwizard Application class as a property.

Then in the run() and initialize() stages you can add Websocket endpoints.

However the WebsocketBundle class does not have a zero arg constructor. To hack it and make it work you have to provide a Websocket class.
This is not ideal if you are wanting to programmatically control the websocket instance. Therefore a DummyWebsocket was used as an argument, and is ignored by the application, like so.

public class ServiceApplication extends Application {

private WebsocketBundle websocketBundle;

public static void main(final String[] args) throws Exception {
    new ServiceApplication().run(args);
}


@Override
public void initialize(final Bootstrap<ServiceConfiguration> bootstrap) {

    websocketBundle = new WebsocketBundle(DummyWebsocket.class);
    bootstrap.addBundle(websocketBundle);

}

@Override
public void run(final ServiceConfiguration config,
                final Environment environment) {

    //websocket - queue handler
    final ServerEndpointConfig wsConfig = BasicServerEndpointConfig.Builder.create(WebsocketQueueHandler.class, "/websocket").build();
    websocketBundle.addEndpoint(wsConfig);

}

Can we have support to create a WebsocketBundle instance without any constructor arguments?

Thanks

DeflateFrameExtension could not be instantiated

I tried to setup a project with drop-wizard 1.1.0 (also 1.1.2), but the server do no starts because of this error:
org.eclipse.jetty.websocket.api.extensions.Extension: Provider org.eclipse.jetty.websocket.common.extensions.compress.DeflateFrameExtension could not be instantiated

Can you provide some suggestion. I tried all the ways that was suggested in the documentation.

Thanks!

sessions are invalidating for subsequent requests

Hi,
We recently have upgrade one of our product from Jetty 6.1.2 to jetty 9.4.12. Post to upgrade, we landed up in an issue where session is being invalidated for subsequent requests. We are using embedded Jetty here. I have configured the DefaultSessionCache and NullSessionDataStore to persist sessions in-memory. I also have set cookie-config flags i.e "http-only" and "secure" as false also, to check in case it works with that. But still the same issue where we can see stale connections error is being logged in the logs.

Please help with your expert recommendations on what am I missing here to configure.

Regards...!

Jetty websocket error

I have added the dependency to my maven project as specified and overrides initialize as:

@Override public void initialize(Bootstrap<AppConfiguration> bootstrap) { //attaches the WebSocket endpoint bootstrap.addBundle(new WebsocketBundle(WebSocketEndpoint.class)); }

When I run the application without the WebSocket endpoint it works fine but when I uncomment bootstrap.addBundle(new WebsocketBundle(WebSocketEndpoint.class)); I keep getting this error:

org.eclipse.jetty.websocket.api.extensions.Extension: Provider org.eclipse.jetty.websocket.common.extensions.compress.DeflateFrameExtension could not be instantiated

onMessage callback isn't being invoked

Hi,

I'm using Dropwizard 1.0.5 with the 1.0.0-1 version of the plugin.

Tried this example.

The AnnotatedEchoServer's myOnMsg callback gets invoked when you send a message from a websocket client. However, the EchoServer's onMessage callback does not. Though onOpen and onClose of EchoServer get invoked normally.

Dependencies out of date

Thanks for this project. It's sorely needed. However, it looks like the dependencies are out of date when you try to use this project w/ Dropwizard 1.2.2. There was another issue made about this, it looks like that person figured it out, but I wasn't able to: #16

Can you please look into the dependencies and get the project building w/ dropwizard 1.2.2?

Dependency injection in end point

Hi,

I am trying to have a dependency injected into the server end point but it's not working, I understand that the bundle and the endpoint are not going through the dependency injection cycle. Is it possible to inject objects without adding them to the user properties config, that's the work around I am using right now.

Thanks for your help.

Cannot call method onMsg

Randomly I seem to get following error

ERROR [2023-09-07 08:38:58,147] com.myProject.websockets.LiveWebsocketResource: websocket error: Cannot call method public void com.myProject.websockets.LiveWebsocketResource#onMsg(java.lang.Object, java.lang.String) with args: [org.eclips
e.jetty.websocket.jsr356.JsrSession, java.lang.String]
ERROR [2023-09-07 08:41:00,371] org.hibernate.engine.jdbc.spi.SqlExceptionHelper: (conn=2269) Lock wait timeout exceeded; try restarting transaction
ERROR [2023-09-07 08:41:00,375] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 6324d703a0d6b8fa

I can't reproduce locally though. Even if onMsg is accepting only javax.websocket.Session it occurs.
This error seems to lock some of my DB tables.

Maybe this is related to me using dropwizard2.1

Upgrade Jetty

We're still using Jetty 9.4.10 while the current version is already 9.4.18.
There's at least one breaking change in 9.4.17:

  • 3464 Split SslContextFactory into Client and Server

which blows up my current project for another dependency in my fat jar includes a 9.4.18 jetty leading to a NoClassDefFoundError.

Can we upgrade to the latest jetty version? I'll try to file a PR if I find some spare time.

Allow endpoints to be registered during run()

It would be nice if the endpoint classes could be registered in the application run() method, instead of having to be provided during initialize().

Among other advantages, this would allow them to be optional based on the configuration.

Can't @Inject into websocket endpoint

I'm trying to figure out the best way of accessing singleton services in from a websocket endpoint class without resorting to static fields/methods. I was expecting to be able to use @Inject since it's managed by jersey but it's not working.

I've thrown together an example project using @Inject on both a regular Dropwizard resource and a websocket endpoint, see https://github.com/mpbarnwell/dropwizard-websockets-test

As expected, using curl against the Dropwizard resource returns the service's hash code:

curl -X GET http://localhost:8080/test
1979257230

But running against the webservice endpoint produces a NPE.

curl 'http://localhost:8080/ws' -H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: Yx2RoE1qwByK+r3fO25+/Q==' -H 'Upgrade: websocket' -H 'Connection: Upgrade'
��NullPointerException

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.