Java
Client *.java sources placed under a project are compiled in-process by engine-java and dispatched via JavaEndpoint. Unlike JavaScript and TypeScript, Java sources are synchronized.
Lifecycle
JavaSynchronizer reconciles *.java files into JavaFile artefacts on every cycle. The expensive work happens once per cycle in finishing():
- One
javactask over every client source in the registry. - A single fresh
ClientClassLoader(parent = platform classloader) replaces the previous generation; old metaspace is GC-reclaimed. - Every loaded class is offered to each
JavaClassConsumerSPI implementation in@Order:EntityClassConsumer(@Order(100)) -@Entityclasses register with Hibernate dynamic-map mode.RepositoryClassConsumer(@Order(200)) -@Repositoryclasses become singletons inRepositoryRegistry.ControllerClassConsumer(@Order(300)) -@Controllerclasses register withControllerRouterand publish an OpenAPI fragment.HandlerClassConsumer-implements JavaHandlerclasses register catch-all URL handlers.
Cross-file references resolve in user code because every client class shares the same ClientClassLoader.
URL surface
/services/java/{project}/{*classPath} # authenticated
/public/java/{project}/{*classPath} # anonymous (if enabled)JavaEndpoint.dispatch tries ControllerRouter.match first (longest basePath wins, then most-specific path), then falls through to a JavaHandler, then returns 404.
Annotations
Two annotation packages are on the compile-time classpath of every client .java:
org.eclipse.dirigible.engine.java.annotations.*- persistence:@Entity,@Table,@Id,@GeneratedValue(+GenerationType),@Column,@Transient,@CreatedAt,@UpdatedAt,@CreatedBy,@UpdatedBy,@Documentation,@Repository,@Inject.org.eclipse.dirigible.engine.java.annotations.http.*- REST:@Controller,@Get,@Post,@Put,@Patch,@Delete,@Body,@PathParam,@QueryParam,@Context,@Roles.
A class may be exactly one of {handler, controller}; carrying both shapes is rejected.
Reaching platform beans
Client classes are loaded via ClientClassLoader, not Spring-scanned, so @Autowired is a no-op. Use BeanProvider.getBean(...) from components-core-base to fetch JavaEntityStore, IRepository, etc. The recommended pattern is @Inject CountryRepository - resolved by the DependencyResolver chain (RepositoryRegistry is the only resolver today).
Example
package demo;
import org.eclipse.dirigible.engine.java.annotations.http.Controller;
import org.eclipse.dirigible.engine.java.annotations.http.Get;
import org.eclipse.dirigible.engine.java.annotations.Inject;
@Controller
public class CountryController {
@Inject
private CountryRepository repository;
@Get("/list")
public Object list() {
return repository.findAll();
}
}The base path is the class FQN with . → / - the example serves GET /services/java/<project>/demo/CountryController/list.
Editor & language server
Monaco editor backed by ide-java-lsp (JDT.LS) for completion, navigation, refactor. The ide-java-debug view bridges the browser to a JDWP target via DAP (default JDWP port DIRIGIBLE_JAVA_DEBUG_JDWP_PORT=8000).