Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dropwizard - Resources on multiple ports

I have a Dropwizard(v 0.7.1) based Jersey REST service. Currently I use one application connector port (8810) and I have two resources (say "/path1","/path2").

I will be able to access these resources as http:\\localhost:8810\path1 and http:\\localhost:8810\path2 respectively. What am trying to achieve is have a separate port for each resource. (e.g http:\\localhost:8810\path1 and http:\\localhost:8820\path2). I tweaked the yaml file to have the below configuration and when I started the application both resources were available using both ports and am not sure how to configure these resources to use specific ports or is that even possible with Dropwizard?

server:   
  applicationConnectors:
   - 
     type: http 
     port: 8810
   - 
     type: http 
     port: 8820

Appreciate if someone can enlighten.

Thanks

like image 485
daknight1987 Avatar asked Dec 10 '15 11:12

daknight1987


People also ask

How do I add resources to Dropwizard?

Registering A Resource A Dropwizard application can contain many resource classes, each corresponding to its own URI pattern. Just add another @Path -annotated resource class and call register with an instance of the new class. Before we go too far, we should add a health check for our application.

Does Dropwizard use Log4j?

Dropwizard uses Logback for its logging backend. It provides an slf4j implementation, and even routes all java. util. logging , Log4j, and Apache Commons Logging usage through Logback.

How do I change the server port in Dropwizard?

Add your configuration to the command line after server . See dropwizard.codahale.com/getting-started/#running-your-service for more information. It should have the desired effect. Perfect!


1 Answers

your issue is that the DefaultServerFactory adds all applicationConntectors to the same Handler, see DefaultServerFactory#build:

@Override
public Server build(Environment environment) {
    printBanner(environment.getName());
    final ThreadPool threadPool = createThreadPool(environment.metrics());
    final Server server = buildServer(environment.lifecycle(), threadPool);

    LOGGER.info("Registering jersey handler with root path prefix: {}", applicationContextPath);
    environment.getApplicationContext().setContextPath(applicationContextPath);
    final Handler applicationHandler = createAppServlet(server,
                                                        environment.jersey(),
                                                        environment.getObjectMapper(),
                                                        environment.getValidator(),
                                                        environment.getApplicationContext(),
                                                        environment.getJerseyServletContainer(),
                                                        environment.metrics());

    LOGGER.info("Registering admin handler with root path prefix: {}", adminContextPath);
    environment.getAdminContext().setContextPath(adminContextPath);
    final Handler adminHandler = createAdminServlet(server,
                                                    environment.getAdminContext(),
                                                    environment.metrics(),
                                                    environment.healthChecks());
    final RoutingHandler routingHandler = buildRoutingHandler(environment.metrics(),
                                                              server,
                                                              applicationHandler,
                                                              adminHandler);
    server.setHandler(addStatsHandler(addRequestLog(server, routingHandler, environment.getName())));
    return server;
}

What you need to do is implement your own ServerFactory.

You can extend DefaultServerFactory and overwrite the build method to set up your connectors in the way you want them to be. Presumably you'll want to add some more configuration that indicates what goes where, since in terms of your yaml it will not be possible to map a resource to a specific connector. How would dropwizard know about that.

For overwriting the behaviour for dropwizard (adding a new ServerFactory) you can see this post I wrote about adding logging: Dropwizard doesn't log custom loggers to file

It basically involves implementing the class and making it discoverable for dropwizard. After that all you need to do is to change the yaml file to point to the correct ServerFactory.

If you don't like that approach, you can overwrite the get/set method on the configuration to return your class. For this, your class MUST extend DefaultServerFactory, since otherwise the yaml mapping won't work anymore. You can overwrite the build method regardless though.

Update:

Looking at it in a bit more detail, you'll run into a second problem:

Your Environment only has one jersey environment that it can use. You will need to configure a second jersey environment since currently by default each Handler will get the same Jersey config passed to it (the only one that exists). This is why it will be available for all of your http configurations. So in summary:

  1. Create a new Environment that supports multiple jersey configurations
  2. Create a server factory that knows what jersey config belongs to which Handler and instantiates the handlers in that form.

I believe those two steps would be required.

In terms of environment, you will have to create your own ServerCommand (that is the command that starts up dropwizard server). Looking in EnvironmentCommand#run you can see where the Environment is created. This will be the only place you can overwrite the default Environment (as far as I know) which is what you need to do to support multiple jersey configs.

To be honest with you, looking at this, I do not believe that this is what the dropwizard guys had in mind.

like image 190
pandaadb Avatar answered Nov 14 '22 22:11

pandaadb