External plugins or extensions can easily be developed for OSGi.fx. Since OSGi.fx has itself been developed using OSGi and Eclipse e4, you can easily leverage their modular capabilities to build your own extensions.
See how the bundles with the com.osgifx.console.ui.* project name pattern are developed as a reference.
[!TIP] As a starting point, refer to the sample Tic-Tac-Toe Extension.
Once the extension is developed, install it via Actions -> Install Extension in the OSGi.fx menu.
To develop an extension, you need to provide an OSGi Deployment Package archive.
For ease of development, use the OSGi.fx workspace to build your own extensions. The workspace includes a bnd plugin that automatically generates a deployment package from a bndrun file.
The agent provides an AgentExtension SPI that allows you to execute custom code in the remote runtime and return JSON-compliant results.
Implement the AgentExtension interface and register it as an OSGi service:
public interface AgentExtension<C, R> {
/**
* Executes the extension logic.
*
* @param context the input context (must be DTO-compliant)
* @return the result (must be DTO-compliant)
*/
R execute(C context);
}
Register your extension with a unique name:
@Component(
service = AgentExtension.class,
property = "agent.extension.name=my-custom-extension"
)
public class MyExtension implements AgentExtension<Map<String, Object>, Map<String, Object>> {
@Override
public Map<String, Object> execute(Map<String, Object> context) {
// Your custom logic here
Map<String, Object> result = new HashMap<>();
result.put("status", "success");
return result;
}
}
The supervisor (OSGi.fx) can then invoke your extension via agent.executeExtension("my-custom-extension", context).
For remote runtimes where transferring large files (e.g., several hundred MBs of heap dumps) over RPC is inefficient or restricted, OSGi.fx provides the LargePayloadHandler Service Provider Interface (SPI).
This SPI allows you to implement custom logic to handle large payloads, such as uploading them to an external storage service (e.g., Amazon S3, Azure Blob Storage, or an internal Artifactory).
To use this feature, implement the LargePayloadHandler interface and register it as an OSGi service in your remote runtime.
public interface LargePayloadHandler {
/**
* Handles the large payload (e.g., uploads to S3).
*
* @param metadata the payload metadata
* @param content the payload content as a stream
* @return the result of the handling operation
*/
PayloadHandlerResult handle(PayloadMetadata metadata, InputStream content);
/**
* Returns the maximum payload size supported by this handler in bytes.
* Large payloads exceeding this limit will fallback to other methods.
*/
long getMaximumSize();
/**
* Returns a human-readable name for this handler (e.g., "S3 Upload").
*/
String getName();
}
When a large payload operation (like “Heap Dump”) is triggered:
LargePayloadHandler services.@Component(service = LargePayloadHandler.class)
public class S3PayloadHandler implements LargePayloadHandler {
@Override
public PayloadHandlerResult handle(PayloadMetadata metadata, InputStream content) {
try {
// Logic to upload 'content' to an S3 bucket...
String s3Url = "https://s3.amazonaws.com/my-bucket/" + metadata.getFilename();
return PayloadHandlerResult.success(s3Url);
} catch (Exception e) {
return PayloadHandlerResult.failure("Upload failed: " + e.getMessage());
}
}
@Override
public long getMaximumSize() {
return 5 * 1024 * 1024 * 1024L; // 5 GB
}
@Override
public String getName() {
return "Amazon S3";
}
}