CodeBlanks Logo Icon CodeBlanks

Putting it together

Combine all expert topics into a working app.

Project: combine

In the final lesson you will combine all layers. First you add a bytecode inspector: a ClassVisitor interface and an InspectorVisitor class print the class name. Then in main you run the registry, inspection, reactive publish, timing and native bridge in sequence.

So the five layers — annotation, pattern, reactive, performance, bytecode and native — work together in a single flow. This is the synthesis of the expert level.

Practice Add ClassVisitor and InspectorVisitor

Add an interface ClassVisitor to the structure above with a void visitClass(String name); method. Define a class InspectorVisitor implements ClassVisitor whose visitClass(String name) method does System.out.println("inspecting: " + name);. In main call new InspectorVisitor().visitClass("HelloService");.

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));
    }
}

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;"));
    }
}

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;
    }
}

interface ClassVisitor {
    void visitClass(String name);
}

class InspectorVisitor implements ClassVisitor {
    public void visitClass(String name) {
        System.out.println("inspecting: " + name);
    }
}

public class Main {
    public static void main(String[] args) {
        new InspectorVisitor().visitClass("HelloService");
    }
}

Expected output

inspecting: HelloService

Practice Write the main that combines all layers

Change the main method in the structure above: create Registry registry = new Registry();, build the service with HelloService svc = new HelloService(); and register it with registry.put("hello", svc);. Call new InspectorVisitor().visitClass("HelloService");. Create SimplePublisher publisher = new SimplePublisher();, subscribe with publisher.subscribe(s -> System.out.println("got: " + s));, call new TimedPublisher(publisher).publish(svc.greet());. Finally 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));
    }
}

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;
    }
}

interface ClassVisitor {
    void visitClass(String name);
}

class InspectorVisitor implements ClassVisitor {
    public void visitClass(String name) {
        System.out.println("inspecting: " + name);
    }
}

public class Main {
    public static void main(String[] args) {
        new InspectorVisitor().visitClass("HelloService");
    }
}

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;
    }
}

interface ClassVisitor {
    void visitClass(String name);
}

class InspectorVisitor implements ClassVisitor {
    public void visitClass(String name) {
        System.out.println("inspecting: " + name);
    }
}

public class Main {
    public static void main(String[] args) {
        Registry registry = new Registry();
        HelloService svc = new HelloService();
        registry.put("hello", svc);
        new InspectorVisitor().visitClass("HelloService");
        SimplePublisher publisher = new SimplePublisher();
        publisher.subscribe(s -> System.out.println("got: " + s));
        new TimedPublisher(publisher).publish(svc.greet());
        System.out.println(NativeBridge.describe("HelloService", "greet", "()Ljava/lang/String;"));
    }
}

Expected output

inspecting: HelloService
got: hello
elapsed measured: true
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 What does the combine step show?

  • A single concept
  • Only the database
  • All layers working together Correct answer
  • Only the GUI

Explanation: The combine step shows the five layers running in a single flow.

2 Complete the inspector call

Question
new InspectorVisitor().visitClass(____);
Answer
new InspectorVisitor().visitClass("HelloService");

Explanation: visitClass("HelloService") visits the class name.

3 Match the combine flow

Term Meaning
Registry.put Service registry
InspectorVisitor Class inspection
TimedPublisher Timing
NativeBridge Native bridge

All lessons in Expert