CodeBlanks Logo Icon CodeBlanks

Microservice basics

Write a small HTTP-based microservice skeleton.

The service registry pattern

The microservice foundation starts with a Registry that holds @Service-marked classes by name. The Registry keeps a Map; put(name, instance) adds and get(name) finds. This is the core of dependency injection.

In this project you will add a HelloService instance to the Registry under the name "hello". In the next lesson this registry is used in the combine step.

The native bridge

NativeBridge is a class that builds the C function name of a native call. Its describe(cls, method, sig) method returns "Java_" + cls + "_" + method + sig. This models the JNI naming; no real call is made.

This model is used to decide which class and method to bind to native code. In the combine step NativeBridge works together with the service registry.

Practice Write the Registry and NativeBridge classes

Add a class Registry to the structure above with a java.util.Map<String, Object> field and void put(String name, Object instance) and Object get(String name) methods. Add a class NativeBridge with a static String describe(String cls, String method, String sig) method that returns "Java_" + cls + "_" + method + sig. In main create Registry registry = new Registry();, call registry.put("hello", new HelloService()); and print System.out.println(NativeBridge.describe("HelloService", "greet", "()Ljava/lang/String;"));.

Starter code

Main.java
@interface Service {}

@Service
class HelloService {
    String greet() { return "hello"; }
}

interface Subscriber {
    void onNext(String item);
}

class SimplePublisher {
    java.util.List<Subscriber> subs = new java.util.ArrayList<>();
    void subscribe(Subscriber s) { subs.add(s); }
    void publish(String item) {
        for (Subscriber s : subs) s.onNext(item);
    }
}

class TimedPublisher {
    SimplePublisher delegate;
    TimedPublisher(SimplePublisher delegate) {
        this.delegate = delegate;
    }
    void publish(String item) {
        long start = System.nanoTime();
        delegate.publish(item);
        long elapsed = System.nanoTime() - start;
        System.out.println("elapsed measured: " + (elapsed >= 0));
    }
}

public class Main {
    public static void main(String[] args) {
        SimplePublisher p = new SimplePublisher();
        p.subscribe(s -> System.out.println("got: " + s));
        new TimedPublisher(p).publish("hello");
    }
}

Sample solution

Main.java
@interface Service {}

@Service
class HelloService {
    String greet() { return "hello"; }
}

interface Subscriber {
    void onNext(String item);
}

class SimplePublisher {
    java.util.List<Subscriber> subs = new java.util.ArrayList<>();
    void subscribe(Subscriber s) { subs.add(s); }
    void publish(String item) {
        for (Subscriber s : subs) s.onNext(item);
    }
}

class TimedPublisher {
    SimplePublisher delegate;
    TimedPublisher(SimplePublisher delegate) {
        this.delegate = delegate;
    }
    void publish(String item) {
        long start = System.nanoTime();
        delegate.publish(item);
        long elapsed = System.nanoTime() - start;
        System.out.println("elapsed measured: " + (elapsed >= 0));
    }
}

class Registry {
    java.util.Map<String, Object> services = new java.util.HashMap<>();
    void put(String name, Object instance) { services.put(name, instance); }
    Object get(String name) { return services.get(name); }
}

class NativeBridge {
    static String describe(String cls, String method, String sig) {
        return "Java_" + cls + "_" + method + sig;
    }
}

public class Main {
    public static void main(String[] args) {
        Registry registry = new Registry();
        registry.put("hello", new HelloService());
        System.out.println(NativeBridge.describe("HelloService", "greet", "()Ljava/lang/String;"));
    }
}

Expected output

Java_HelloService_greet()Ljava/lang/String;

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Complete the registry put call

Question
registry.put(____, new HelloService());
Answer
registry.put("hello", new HelloService());

Explanation: registry.put("hello", new HelloService()); adds the entry.

2 What does the Registry pattern provide?

  • Class compilation
  • Name-to-instance mapping Correct answer
  • Thread pool
  • File reading

Explanation: The Registry holds a name-to-instance mapping.

3 Match the microservice elements

Term Meaning
Registry Service registry
@Service Service marker
NativeBridge Native call
put Add entry

All lessons in Expert