Putting it together
- Java course
- Expert
- Lesson 46/46
- 6 min
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
@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
@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
@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
@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
new InspectorVisitor().visitClass(____);
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 |