Calling Another Service

In a microservice environment, each service is responsible for providing the functionality or service to other collaborators. If we wish to extend the “hello world” microservice, we will need to create a service to which we can call using Dropwizard’s REST client functionality. Just like we did for the Spring Boot microservice, we’ll leverage the backend service from the source code that accompanies the book. The interaction will look similar to this:

If you look in this book’s source code, we’ll see a Maven module called backend which contains a very simple HTTP servlet that can be invoked with a GET request and query parameters. The code for this backend is very simple, and does not use any of the microservice frameworks (Spring Boot, Dropwizard, or WildFly Swarm).

To start up the backend service on port 8080, navigate to the back end directory and run the following:

$ mvn clean install jetty:run

This service is exposed at /api/backend and takes a query parameter greeting. For example, when we call this service with this path /api/backend?greeting=Hello, then the backend service will respond with a JSON object like this:

$ curl -X GET http://localhost:8080/api/backend?greeting=Hello

Before we get started, let’s add the dropwizard-client dependency to our pom.xml:

<dependency>

<groupId>io.dropwizard</groupId> <artifactId>dropwizard-client</artifactId>

</dependency>

We will create a new HTTP endpoint, /api/greeting in our Dropwizard hola-dropwizard example and use Jersey to call this backend! Let’s start off by creating two new classes in the src/main/java/com/ redhat/examples/dropwizard/resources folder of our holadropwizard project named GreeterRestResource and Greeter SayingFactory. The GreeterRestResource will implement our JAX-RS REST endpoints, and the GreeterSayingFactory class will encapsulate the configuration options we wish to use for our Greeter service.

The GreeterRestResource class is shown in Example 3-15.

Example 3-15. src/main/java/com/redhat/examples/dropwizard/ resources/GreeterRestResource.java

@Path("/api")

public class GreeterRestResource {

private String saying; private String backendServiceHost; private int backendServicePort; private Client client;

public GreeterRestResource(final String saying, String host, int port, Client client) {

this.saying = saying; this.backendServiceHost = host; this.backendServicePort = port; this.client = client; }

@Path("/greeting")

@GET

@Timed

public String greeting() {

String backendServiceUrl =

String.format("http://%s:%d&quot;, backendServiceHost, backendServicePort); System.out.println("Sending to: " + backendServiceUrl);

return backendServiceUrl;

}

}

The GreeterSayingFactory class encapsulates configuration options we’ll need, like the service host and service port, which could change in different environments (see Example 3-16). It also declares a JerseyClientConfiguration, which provides us a nice DSL for building up our Jersey client. Let’s add this as a section to our HolaDropwizardConfiguration class, as shown in

Example 3-17.

Example 3-16. src/main/java/com/redhat/examples/dropwizard/ resources/GreeterSayingFactory.java

public class GreeterSayingFactory {

@NotEmpty private String saying;

@NotEmpty private String host;

@NotEmpty private int port;

private JerseyClientConfiguration jerseyClientConfig = new JerseyClientConfiguration();

@JsonProperty("jerseyClient")

public JerseyClientConfiguration getJerseyClientConfig() {

return jerseyClientConfig; }

public String getSaying() { return saying; }

public void setSaying(String saying) {

this.saying = saying; }

public String getHost() { return host; }

public void setHost(String host) {

this.host = host; }

public int getPort() { return port;

}

public void setPort(int port) { this.port = port;

}

}

Example 3-17. src/main/java/com/redhat/examples/dropwizard/ HolaDropwizardConfiguration.java

public class HolaDropwizardConfiguration extends Configuration {

private HelloSayingFactory sayingFactory; private GreeterSayingFactory greeterSayingFactory;

@JsonProperty("helloapp")

public HelloSayingFactory getSayingFactory() {

return sayingFactory; }

@JsonProperty("helloapp") public void setSayingFactory(

HelloSayingFactory sayingFactory) { this.sayingFactory = sayingFactory; }

@JsonProperty("greeter")

public GreeterSayingFactory getGreeterSayingFactory() {

return greeterSayingFactory; }

@JsonProperty("greeter")

public void setGreeterSayingFactory( GreeterSayingFactory greeterSayingFactory) {

this.greeterSayingFactory = greeterSayingFactory;

}

}

We can also update our conf/application.yml file to add these values in:

greeter:

saying:${GREETER_SAYING:-Guten Tag Dropwizard} host:${GREETER_BACKEND_HOST:-localhost} port:${GREETER_BACKEND_PORT:-8080}

Note we specify defaults for the various configuration options if they’re not provided by OS environment variables.

Now let’s wire up the client and the greeter resource inside our Hola

DropwizardApplication class, which is where all of our services and resources are wired into the Environment object

(Example 3-18).

Example 3-18. src/main/java/com/redhat/examples/dropwizard/

HolaDropwizardApplication.java

@Override

public void run(HolaDropwizardConfiguration configuration, Environment environment) {

environment.jersey().register( new HolaRestResource(configuration

.getSayingFactory()

.getSaying()));

// greeter service

GreeterSayingFactory greeterSayingFactory = configuration.getGreeterSayingFactory();

Client greeterClient =

new JerseyClientBuilder(environment)

.using(

greeterSayingFactory.getJerseyClientConfig()) .build("greeterClient");

environment.jersey().register( new GreeterRestResource( greeterSayingFactory.getSaying(), greeterSayingFactory.getHost(),

greeterSayingFactory.getPort(), greeterClient)); }

Lastly, let’s implement the client that will make the call to the backend service with all of the appropriate host and port information injected, see Example 3-19.

Example 3-19. src/main/java/com/redhat/examples/dropwizard/ resources/GreeterRestResource.java

@Path("/greeting")

@GET

@Timed

public String greeting() {

String backendServiceUrl = String.format(

"http://%s:%d&quot;, backendServiceHost,

backendServicePort); System.out.println("Sending to: " + backendServiceUrl);

BackendDTO backendDTO = client

.target(backendServiceUrl)

.path("api")

.path("backend")

.queryParam("greeting", saying)

.request().accept("application/json")

.get(BackendDTO.class);

return backendDTO.getGreeting() +

" at host: " + backendDTO.getIp();

}

Dropwizard offers two convenience wrappers for making REST calls: the HttpComponents library directly (if you need low-level HTTP access) or the Jersey/JAX-RS REST client libraries, which have a nice higher-level DSL for making HTTP calls. In the previous example, we’re using the Jersey client to make the call.

Now let’s build the microservice and verify that we can call this new greeting endpoint and that it properly calls the backend. First, let’s start the backend if it’s not already running. Navigate to the backend directory of the source code that comes with this application and run it:

$ mvn clean install jetty:run

Next let’s build and run our Dropwizard microservice. Let’s also configure this service to run on a different port than its default port (8080) so that it doesn’t collide with the backend service which is already running on port 8080. Later on in the book we can see how running these microservices in their own container removes the restriction of port swizzling at runtime.

First let’s make explicit which port we want to use as default. Open the conf/application.yml file and add the server port information:

server:

applicationConnectors:

  • type: http port: 8080

Now start the microservice by overriding the default port:

$ mvn clean install exec:java \

-Ddw.server.applicationConnectors[0].port=9090

Now, let’s navigate our browser to http://localhost:9090/api/greeting to see if our microservice properly calls the backend and displays what we’re expecting:

results matching ""

    No results matching ""