# Eo / Ejb / Wiki

The `eo.ejb.wiki` package is a subpackage under `eo.ejb` that provides two utility classes: a simple greeting class for basic string templating, and a reflection-based class for dynamically loading and invoking methods on external classes at runtime. This module sits under the EJB service layer and appears to offer low-level helper utilities consumed by broader EJB service functionality.

## Overview

This module contains only two classes and a handful of methods — it is not a feature-rich module on its own. Instead, it serves as a small toolbox:

- **`PlainClass`** provides straightforward string-based greeting functionality with no side effects.
- **`ReflectiveClass`** enables dynamic class loading and method invocation via Java reflection, allowing the system to operate on classes whose concrete types are only known at runtime.

## Key Classes and Interfaces

### PlainClass

**Source:** [PlainClass.java](PlainClass.java)

`PlainClass` is a simple, immutable-ish value object. It stores a single `name` field and provides a `greet()` method that returns a formatted greeting string.

- **Constructor:** `PlainClass(String name)` — initialises the instance with a name. (See [constructor source](PlainClass.java:6))
- **`greet()`** — returns a formatted greeting. Given a `name` of `"World"`, this method returns `"Hello, World"`. (See [method source](PlainClass.java:10))

```java
public String greet() {
    return "Hello, " + name;
}
```

This class has no dependencies, no side effects, and does not interact with any external systems. It appears to be used for generating human-readable greeting messages.

### ReflectiveClass

**Source:** [ReflectiveClass.java](ReflectiveClass.java)

`ReflectiveClass` is a reflection utility that dynamically loads classes and invokes methods on them. It takes a fully qualified class name as a String and uses the JVM reflection API to work with it at runtime.

- **Constructor:** `ReflectiveClass(String targetClass)` — stores the fully qualified name of the class to be loaded dynamically. (See [constructor source](ReflectiveClass.java:6))

- **`loadByReflection()`** — Uses `Class.forName(targetClass).newInstance()` to load and instantiate the target class by its fully qualified name. Returns an `Object` instance. Throws `Exception` if the class cannot be found, instantiated, or if the class name is invalid. (See [method source](ReflectiveClass.java:10))

```java
public Object loadByReflection() throws Exception {
    return Class.forName(targetClass).newInstance();
}
```

- **`invokeMethod(Class<?> cls)`** — Uses Java reflection to locate a method named `"execute"` (with no parameters) on the given class and invokes it as a **static** call (passing `null` as the object instance to `Method.invoke`). Throws `Exception` if the method does not exist or cannot be invoked. (See [method source](ReflectiveClass.java:14))

```java
public void invokeMethod(Class<?> cls) throws Exception {
    java.lang.reflect.Method m = cls.getMethod("execute");
    m.invoke(null);
}
```

**Key design notes for `ReflectiveClass`:**

- `loadByReflection` resolves the class by its string name using `Class.forName`, then instantiates it with the no-arg constructor via `newInstance()`. This means the target class must have a public no-argument constructor.
- `invokeMethod` hardcodes the method name `"execute"` — it will only work with classes that expose a public static void `execute()` method with no parameters.
- Both methods throw `Exception` broadly rather than specific reflection exceptions (`ClassNotFoundException`, `NoSuchMethodException`, `IllegalAccessException`, `InstantiationException`, `InvocationTargetException`).

## How It Works

### Typical Usage Patterns

**Greeting generation** (using `PlainClass`):

1. Create an instance: `new PlainClass("Alice")`
2. Call `greet()` to get `"Hello, Alice"`

**Dynamic class loading** (using `ReflectiveClass`):

1. Create an instance with a fully qualified class name: `new ReflectiveClass("com.example.MyService")`
2. Call `loadByReflection()` to dynamically load and instantiate `com.example.MyService` at runtime
3. Call `invokeMethod(MyService.class)` to find and invoke the static `execute()` method on that class

The reflection flow in `ReflectiveClass` follows a straightforward pattern:

1. The class name string is resolved to a `Class<?>` object via `Class.forName()`.
2. A new instance is created by calling the no-arg constructor.
3. For invocation, the target method `"execute"` is resolved via `cls.getMethod("execute")`, then called statically via `m.invoke(null)`.

## Dependencies and Integration

- **Internal dependency:** This package depends on `eo.ejb.service`. Any classes or interfaces defined in that parent package may be referenced by consumers of this module's utilities.
- **JDK reflection API:** `ReflectiveClass` uses `java.lang.reflect.Method` and `Class.forName()` directly from the JDK. No additional libraries are required.

```mermaid
flowchart LR
    PKG["Package: eo.ejb.wiki"]
    PC["PlainClass"]
    RC["ReflectiveClass"]
    PKG --> PC
    PKG --> RC
    PC --> SVC["eo.ejb.service"]
    RC --> SVC
```

## Notes for Developers

- **`ReflectiveClass` is brittle.** The `invokeMethod` method hardcodes the method name `"execute"` and expects it to be a static, no-argument method. This is not validated at compile time — failures will surface as runtime exceptions if the target class does not conform to this contract.
- **`newInstance()` deprecation.** `Class.newInstance()` was deprecated in Java 9 in favour of `Class.getDeclaredConstructor().newInstance()`. Consider upgrading this call if targeting newer Java versions.
- **No null checks.** Neither `PlainClass` nor `ReflectiveClass` validate that their constructor parameters are non-null. Passing `null` will likely cause a `NullPointerException` later, in `greet()` for `PlainClass` and in `Class.forName()` for `ReflectiveClass`.
- **Broad exception handling.** Both reflection methods in `ReflectiveClass` declare `throws Exception` rather than specific checked exceptions. Callers should be prepared to catch and handle `ClassNotFoundException`, `InstantiationException`, `IllegalAccessException`, `NoSuchMethodException`, and `InvocationTargetException`.
- **Extension point.** `ReflectiveClass` could be extended to support parameterised method invocations, instance method calls (rather than static), and custom method name resolution if more flexible runtime dispatch is needed.
