Get up to 80 % extra points for free! More info:

Lesson 3 - Java Server - Google Guice

In the previous lesson, Java Server - Server Parameters, we looked at server parameters. Today we're going to implement dependency management using the Google guice library. The result of our efforts will be to get an instance implementing IParameterProvider using Google guice. In the future, we'll acquire all instances like this.

Google guice

If you have no idea what dependency injection is, I suggest you read the local DI course carefully. To understand Google guice itself, I recommend the following video series.

In short, it's a library that will create class instances for us and take care of passing them across the application to places where we need them.

Adding a Dependency

We'll start by adding a dependency to our project, specifically to the server module. Open the build.gradle file and add the following dependency to the dependencies block:

implementation group: 'com.google.inject', name: 'guice', version: '4.2'

Parameter Factory

From the previous lesson we got the CmdParser class and IParameterProvider interface. Now, let's show how to create an instance implementing IParameterProvider by using Google guice. We need to use a factory to create the instance, because the CmdParser class has a parameter in its constructor that we must pass from the "outside". In the cmd package we'll create a new interface named IParameterFactory. This interface will have one method that will create a concrete instance with the IParameterProvider interface:

package cz.stechy.chat.cmd;

public interface IParameterFactory {

    IParameterProvider getParameters(String[] args);
}

Next we'll implement this factory as a ParameterFactory class:

package cz.stechy.chat.cmd;

import com.google.inject.Singleton;

@Singleton
public class ParameterFactory implements IParameterFactory {

    @Override
    public IParameterProvider getParameters(String[] args) {
        return new CmdParser(args);
    }
}

The implementation of the getParameters() method is very simple. It just creates and returns a new CmdParser class instance.

Configuring guice

Now let's configure Google guice to map instances correctly. We'll create a new ServerModule class that will inherit from the com.google.inject.AbstractModule class and implement a single method in it: configure(). The class is not in the cmd package, but one package up.

package cz.stechy.chat;

import com.google.inject.AbstractModule;
import cz.stechy.chat.cmd.IParameterFactory;
import cz.stechy.chat.cmd.ParameterFactory;

public class ServerModule extends AbstractModule {

    @Override
    public void configure() {
        bind(IParameterFactory.class).to(ParameterFactory.class);
    }
}

This is the class doing all the magic, mapping implementations to the corresponding interfaces. In our case we have only one mapping here, which is the implementation of the IParameterFactory interface by the ParameterFactory class.

Main class

Finally, we'll create the application's startup class. So we'll create a new Server class. Place it in the same folder as ServerModule.

Next we'll create one instance constant of the IParameterFactory type in the class:

private final IParameterFactory parameterFactory;

The class constructor will have one parameter, the IParameterFactory interface:

@Inject
public Server(IParameterFactory parameterFactory) {
    this.parameterFactory = parameterFactory;
}

Notice the @Inject annotation. This annotation comes from the Google guice library and says that the constructor parameters are the dependencies guice will pass automatically.

Then we'll create a private run() instance method, which will be the entry point of the application:

private void run(String[] args) {
    final IParameterProvider parameters = parameterFactory.getParameters(args);
    System.out.println("Maximum number of clients: " + parameters.getInteger(CmdParser.CLIENTS));
}

For now, we'll just write the information about the maximum number of clients to the console.

Finally, we'll create a static main() method to create an injector, get a server class instance, and run the run() method above:

public static void main(String[] args) throws Exception {
    final Injector injector = Guice.createInjector(new ServerModule());
    Server server = injector.getInstance(Server.class);
    server.run(args);
}

Launching the Application

To start the application, we'll use the gradient command:

gradlew server:run -Parg=-port=6298,-clients=5,-max_waiting_queue=10

The result should be number 5, which corresponds to the maximum number of clients.

If everything works for you, congratulations, you've just implemented dependency injection using the Google guice library. In case of problems, you can look in the attached archive, which is available for download below the article, and find your mistake. Next time, in the lesson Java Server - Server Thread, we'll create a code template for the server thread.


 

Previous article
Java Server - Server Parameters
All articles in this section
Server for Client Applications in Java
Skip article
(not recommended)
Java Server - Server Thread
Article has been written for you by Petr Štechmüller
Avatar
User rating:
2 votes
Activities