Optional typed handler interfaces for @Scheduled / @Listener / @Websocket#6010
Open
delchev wants to merge 1 commit into
Open
Optional typed handler interfaces for @Scheduled / @Listener / @Websocket#6010delchev wants to merge 1 commit into
delchev wants to merge 1 commit into
Conversation
…cket Completes the typed-SDK story started with @ExtensionPoint: every decorator that has a runtime callback contract now ships an optional companion interface. Implementing it gives the user compile-time signature checking + IDE autocomplete + refactoring; the engine dispatches the callback via a direct virtual call instead of Method.invoke. Classes that don't implement the interface keep working through the existing reflective fallback — strictly additive. Three interfaces under org.eclipse.dirigible.sdk.*: - job.JobHandler — void run() - messaging.MessageHandler — void onMessage(String) + default onError(String) - net.WebsocketHandler — all four lifecycle methods default to no-op, so users only override what they care about. ScheduledClassConsumer / ListenerClassConsumer pick the typed path when `instance instanceof XHandler`, fall back to method-by-name reflection otherwise. Both log which path was chosen at INFO so the dispatch mode is visible in operational logs. ListenerClassConsumer extracts a small Dispatcher abstraction so the JMS message-receive callback stays uniform across both paths. WebsocketClassConsumer remains unchanged — it only registers the instance in JavaWebsocketRegistry; the actual dispatch lives in WebsocketProcessor (engine-websockets), which already reflects by method name. Reflection finds the interface's method body just as readily as a hand-rolled method of the same name, so users still get the typed-interface benefit (IDE + signature check) without engine-websockets needing to depend on api-modules-java. README adds a "Optional typed handler interfaces" section with the mapping and a WebsocketHandler example showing partial overrides via default methods. Companion sample-side PR landed at dirigiblelabs/sample-java-entity-decorators#6 — CleanupJob, OrderListener and ChatHandler now implement the new interfaces. The four single-decorator standalone samples stay on the reflective form so the fallback path is also exercised by CI. Verified locally with `mvn -P unit-tests clean install` (BUILD SUCCESS in 6:05) and JavaEngineIT (4/4 pass). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| * Fires when the listener container catches an exception while delivering a message. Default is a | ||
| * no-op so implementations only override it when they need to react to delivery failures. | ||
| */ | ||
| default void onError(String error) { |
| * @param message the text payload | ||
| * @param from a stable identifier for the originating session | ||
| */ | ||
| default void onMessage(String message, String from) { |
| * @param message the text payload | ||
| * @param from a stable identifier for the originating session | ||
| */ | ||
| default void onMessage(String message, String from) { |
| } | ||
|
|
||
| /** Fires when the underlying transport reports an error. */ | ||
| default void onError(String error) { |
delchev
added a commit
to dirigible-io/dirigible-io.github.io
that referenced
this pull request
Jun 11, 2026
Pairs with the platform change in eclipse-dirigible/dirigible#6010, which ships three companion interfaces alongside the existing decorators: - @scheduled -> sdk.job.JobHandler (single void run()) - @Listener -> sdk.messaging.MessageHandler (onMessage(String), default onError(String)) - @websocket -> sdk.net.WebsocketHandler (4 default no-op lifecycle methods) Implementing the interface is opt-in. Classes that don't implement it still work via method-by-name reflection. The typed path gives compile-time signature checking, IDE autocomplete + refactoring, default no-op methods for callbacks you don't care about (WebsocketHandler, MessageHandler.onError), and direct (non-reflective) dispatch. Updates: - /sdk/job/decorators - new JobHandler section, example switched to `implements JobHandler`. - /sdk/messaging/decorators - new MessageHandler section, both queue + topic examples switched to typed form; topic example shows the default onError no-op covering the rest. - /sdk/net/decorators - new WebsocketHandler section, example shortened to a single onMessage override (the other three callbacks default to no-op via the interface). - /help/develop/scheduled-jobs, message-listeners, websockets - each Java code block switched to the typed form with a one-paragraph note about the opt-in nature and a link to the matching /sdk/ page. - /help/develop/decorators-model - parallel-surface table mentions the Java optional interfaces in the @scheduled / @Listener / @websocket rows, plus a new "Optional typed contracts" paragraph after the consumer-ordering section. Build verified clean (`npm run docs:build`, 25s). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the typed-SDK story started with
@ExtensionPoint: every decorator that has a runtime callback contract now ships an optional companion interface. Implementing it gives the user compile-time signature checking + IDE autocomplete + refactoring; the engine dispatches the callback via a direct virtual call instead ofMethod.invoke. Classes that don't implement the interface keep working unchanged through the existing reflective fallback — strictly additive.New interfaces
Under
org.eclipse.dirigible.sdk.*:@Scheduledorg.eclipse.dirigible.sdk.job.JobHandlervoid run()@Listenerorg.eclipse.dirigible.sdk.messaging.MessageHandlervoid onMessage(String),default void onError(String) {}@Websocketorg.eclipse.dirigible.sdk.net.WebsocketHandlerEngine-side dispatch
ScheduledClassConsumer— picks the typed path wheninstance instanceof JobHandler, falls back to looking uprun()by name otherwise. Both log which path was chosen at INFO so the dispatch mode is visible in ops logs.ListenerClassConsumer— same pattern. The JMS receive callback funnels through a smallDispatcherabstraction (typed vs reflective record implementations) so the message-handling code path stays uniform regardless of which form the user chose.WebsocketClassConsumer— unchanged. It only registers the handler inJavaWebsocketRegistry; actual dispatch lives inWebsocketProcessor(engine-websockets) which already reflects by method name. Reflection finds the interface's default method body just as readily as a hand-rolled method of the same name, so users still get the typed-interface benefit (compile-time signature check + IDE) without engine-websockets needing to depend onapi-modules-java.Companion sample-side change
Already merged: dirigiblelabs/sample-java-entity-decorators#6 —
CleanupJob implements JobHandler,OrderListener implements MessageHandler,ChatHandler implements WebsocketHandler. The four single-decorator standalone samples (sample-java-{job,listener,websocket,extension}-decorator) intentionally stay on the reflective form so the fallback path also runs on every CI build.Example
Test plan
mvn -P unit-tests clean install— BUILD SUCCESS in 6:05.JavaEngineIT— 4/4 pass.JavaEntityDecoratorsSampleProjectITclones the now-typed sample) and the reflective fallback (JavaJobDecoratorSampleProjectIT+JavaListenerDecoratorSampleProjectIT+JavaWebsocketDecoratorSampleProjectITstill on the un-typed form) in the same suite.🤖 Generated with Claude Code