Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
# sample-java-extension-decorator

Showing how to use `@Extension` to register a contribution to an extension point in
[Eclipse Dirigible](https://www.dirigible.io/).
Showing how to define and consume extension points in
[Eclipse Dirigible](https://www.dirigible.io/) — no dedicated annotation: an extension point is a
plain interface and a contribution is a `@Component` implementing it.

## Layout

```
sample-java-extension-decorator/ # Dirigible project (registry path)
└── demo/
└── extension/
├── SampleContribution.java # @Extension — registers to "java-sample-extension-point"
└── ExtensionConsumer.java # @Controller — queries the registry and returns contributions
├── SampleExtensionPoint.java # plain interface — the extension point
├── SampleContribution.java # @Component implementing it — a contribution
├── ExtensionConsumer.java # @Controller — Extensions.find(...) lookup
└── InjectingConsumer.java # @Controller — List<SampleExtensionPoint> collection injection
```

## Usage

Drop this project into the Dirigible IDE (clone via the Git perspective and publish, or copy it
to `/registry/public/sample-java-extension-decorator/`). The synchronizer compiles the classes and
registers `SampleContribution` against the extension point. Verify via:
Drop this project into the Dirigible IDE (clone via the Git perspective and publish, or copy it to
`/registry/public/sample-java-extension-decorator/`). The synchronizer compiles the classes; the bean
container registers `SampleContribution` as a `@Component`.

```
GET /services/java/sample-java-extension-decorator/demo/extension/ExtensionConsumer/contributions
```
## Consuming extensions

Two ways, both returning the same contributions:

- **Collection injection (preferred, Spring-style)** — `InjectingConsumer` takes a
`List<SampleExtensionPoint>` in its constructor; the bean container injects every contribution.
Verify: `GET /services/java/sample-java-extension-decorator/demo/extension/InjectingConsumer/injected-contributions`
- **Programmatic lookup** — `ExtensionConsumer` calls `Extensions.find(SampleExtensionPoint.class)`.
Verify: `GET /services/java/sample-java-extension-decorator/demo/extension/ExtensionConsumer/contributions`

Both return `["Hello from SampleContribution!"]`.

Returns a JSON array including `{ "name": "sample-contribution", "module": "demo.extension.SampleContribution" }`.
See the [Develop guide](https://www.dirigible.io/help/develop/extension-providers/) and the [Java SDK](https://www.dirigible.io/sdk/).
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package demo.extension;

import java.util.List;

import org.eclipse.dirigible.sdk.http.Controller;
import org.eclipse.dirigible.sdk.http.Get;

/**
* Spring-style "inject all implementations of an interface": the bean container populates the
* List<SampleExtensionPoint> with every @Extension contribution (each is also a @Component), so no
* explicit Extensions.find() lookup is needed.
*/
@Controller
public class InjectingConsumer {

private final List<SampleExtensionPoint> contributions;

public InjectingConsumer(List<SampleExtensionPoint> contributions) {
this.contributions = contributions;
}

@Get("/injected-contributions")
public List<String> list() {
return contributions.stream()
.map(SampleExtensionPoint::describe)
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package demo.extension;

import org.eclipse.dirigible.sdk.extensions.Extension;
import org.eclipse.dirigible.sdk.component.Component;

/**
* Demonstrates {@code @Extension}: registers this class as a typed contribution to
* {@link SampleExtensionPoint}. The runtime validates the implementation at registration time —
* consumers that call {@code Extensions.find(SampleExtensionPoint.class)} receive a
* {@code List<SampleExtensionPoint>} that they can invoke directly.
* A contribution is simply a {@code @Component} bean implementing the extension-point interface —
* no {@code @Extension} annotation. Its {@code @Component} name ("sample-contribution") is the
* contribution name. Consumers receive it via {@code List<SampleExtensionPoint>} or
* {@code Extensions.find(SampleExtensionPoint.class)}.
*/
@Extension(target = SampleExtensionPoint.class, name = "sample-contribution")
@Component("sample-contribution")
public class SampleContribution implements SampleExtensionPoint {

@Override
public String describe() {
return "Hello from SampleContribution!";
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package demo.extension;

import org.eclipse.dirigible.sdk.extensions.ExtensionPoint;

/**
* Demonstrates {@code @ExtensionPoint}: declares the typed contract that contributing classes
* implement. Consumers retrieve every registered implementor via
* {@code Extensions.find(SampleExtensionPoint.class)} and call {@link #describe()} directly,
* with no reflection.
* An extension point is just a plain Java interface — no annotation needed. Contributions are
* {@code @Component} beans that implement it; consumers receive them all via collection injection
* ({@code List<SampleExtensionPoint>}) or {@code Extensions.find(SampleExtensionPoint.class)}.
*/
@ExtensionPoint("Sample Java extension point")
public interface SampleExtensionPoint {

String describe();
Expand Down