-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extension mechanism with Groups Management APIs (#620)
The BDK extension mechanism aims to allow developers to provide additional features without necessary having to contribute in the finos/symphony-bdk-java repository. All extensions must implement the BdkExtension marker interface, and can optionally implement extension point interfaces such as: - `BdkExtensionServiceProvider` - `BdkApiClientFactoryAware` - `BdkAuthenticationAware` - `BdkRetryBuilderAware` - `BdkConfigurationAware` As a first use-case, this PR also brings the Symphony's Groups API support as an extension.
- Loading branch information
Showing
127 changed files
with
1,882 additions
and
73 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
37 changes: 37 additions & 0 deletions
37
buildSrc/src/main/groovy/bdk.java-codegen-conventions.gradle
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
plugins { | ||
id 'org.openapi.generator' | ||
} | ||
|
||
dependencies { | ||
implementation 'javax.annotation:jsr250-api:1.0' | ||
implementation 'io.swagger:swagger-annotations' | ||
implementation 'com.google.code.findbugs:jsr305' | ||
} | ||
|
||
|
||
def generatedFolder = "$buildDir/generated/openapi" | ||
sourceSets.main.java.srcDirs += "$generatedFolder/src/main/java" | ||
|
||
tasks.compileJava.dependsOn tasks.openApiGenerate | ||
|
||
openApiGenerate { | ||
generatorName = 'java' | ||
library = 'jersey2' | ||
outputDir = generatedFolder | ||
inputSpec = "$projectDir/src/main/resources/api.yaml" | ||
skipOverwrite = true | ||
generateApiTests = false | ||
generateModelTests = false | ||
generateModelDocumentation = false | ||
generateApiDocumentation = false | ||
invokerPackage = 'com.symphony.bdk.http.api' | ||
templateDir = "${rootDir}/templates" | ||
globalProperties = [ | ||
models : "", | ||
apis : "", | ||
supportingFiles: "false" | ||
] | ||
configOptions = [ | ||
dateLibrary: "java8" | ||
] | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
# Extension Model | ||
> :bulb: since `2.6` | ||
> :warning: The BDK Extension Mechanism is still an experimental feature, contracts might be subject to **breaking changes** | ||
> in following versions. | ||
## Overview | ||
The BDK extension model consists of a simple concept: the `BdkExtension` API. Note, however, that `BdkExtension` | ||
itself is just a marker interface. | ||
|
||
The `BdkExtension` API is available through the module `:symphony-bdk-extension-api` but other modules might be required | ||
depending on what your extension needs to use. | ||
|
||
## Registering Extensions | ||
Extensions are registered _programmatically_ via the `ExtensionService`: | ||
```java | ||
class ExtensionExample { | ||
|
||
public static void main(String[] args) { | ||
// using the ExtensionService | ||
final SymphonyBdk bdk = new SymphonyBdk(loadFromSymphonyDir("config.yaml")); | ||
bdk.extensions().register(MyBdkExtension.class); | ||
|
||
// or using the SymphonyBdkBuilder | ||
final SymphonyBdk bdk = SymphonyBdk.builder() | ||
.config(loadFromSymphonyDir("config.yaml")) | ||
.extension(MyBdkExtension.class) | ||
.build(); | ||
} | ||
} | ||
``` | ||
|
||
### Registering Extensions in Spring Boot | ||
To use your extension in the [BDK Spring Boot Starter](./spring-boot/core-starter.md), you simply need to register your | ||
extension as a bean added to the application context. Note that your extension class must implement `BdkExtension` in order | ||
to automatically be registered: | ||
```java | ||
@Configuration | ||
public class MyBdkExtensionConfig { | ||
|
||
@Bean | ||
public MyBdkExtension myBdkExtension() { | ||
return new MyBdkExtension(); | ||
} | ||
} | ||
``` | ||
This way, your extension will automatically be registered within the `ExtensionService`. | ||
|
||
## Service Provider Extension | ||
A _Service Provider_ extension is a specific type of extension loaded on demand when calling the | ||
`ExtensionService#service(Class)` method. | ||
|
||
To make your extension _Service Provider_, your extension definition class must implement the `BdkExtensionServiceProvider` | ||
interface along with the `BdkExtension` marker interface: | ||
```java | ||
/** | ||
* The Service implementation class. | ||
*/ | ||
public class MyBdkExtensionService implements BdkExtensionService { | ||
|
||
public void sayHello(String name) { | ||
System.out.println("Hello, %s!", name); // #noLog4Shell | ||
} | ||
} | ||
/** | ||
* The Extension definition class. | ||
*/ | ||
public class MyBdkExtension implements BdkExtension, BdkExtensionServiceProvider<MyBdkExtensionService> { | ||
|
||
private final MyBdkExtensionService service = new MyBdkExtensionService(); | ||
|
||
@Override | ||
public MyBdkExtensionService getService() { | ||
return this.service; | ||
} | ||
} | ||
/** | ||
* Usage example. | ||
*/ | ||
class ExtensionExample { | ||
|
||
public static void main(String[] args) { | ||
final SymphonyBdk bdk = SymphonyBdk.builder() | ||
.config(loadFromSymphonyDir("config.yaml")) | ||
.extension(MyBdkExtension.class) | ||
.build(); | ||
|
||
final MyBdkExtensionService service = bdk.extensions().service(MyBdkExtension.class); | ||
service.sayHello("Symphony"); | ||
} | ||
} | ||
``` | ||
|
||
### Access your Extension's service in Spring Boot | ||
In Spring Boot, your extension's service is _lazily_ initialized. It means that you must annotate your injected extension's service | ||
field with the `@Lazy` annotation in addition to the `@Autowired` one: | ||
```java | ||
@Configuration | ||
public class MyBdkExtensionConfig { | ||
|
||
@Bean | ||
public MyBdkExtension myBdkExtension() { | ||
return new MyBdkExtension(); | ||
} | ||
} | ||
|
||
@RestController | ||
@RequestMapping("/api") | ||
public class ApiController { | ||
|
||
@Lazy // required, otherwise Spring Boot application startup will fail | ||
@Autowired | ||
private MyBdkExtensionService groupService; | ||
} | ||
``` | ||
> :bulb: Note that your IDE might show an error like "_Could not autowire. No beans of 'MyBdkExtensionService' type found_". | ||
> To disable this warning you can annotate your class with `@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")` | ||
## BDK Aware Extensions | ||
The BDK Extension Model allows extensions to access to some core objects such as the configuration or the api clients. | ||
Developers that wish to use these objects a free to implement a set of interfaces all suffixed with the `Aware` keyword. | ||
|
||
### `BdkConfigAware` | ||
The interface `com.symphony.bdk.core.config.extension.BdkConfigAware` allows extensions to read the BDK configuration: | ||
```java | ||
public class MyBdkExtension implements BdkExtension, BdkConfigAware { | ||
|
||
private BdkConfig config; | ||
|
||
@Override | ||
public void setConfiguration(BdkConfig config) { | ||
this.config = config; | ||
} | ||
} | ||
``` | ||
|
||
### `BdkApiClientFactoryAware` | ||
The interface `com.symphony.bdk.core.extension.BdkApiClientFactoryAware` can be used by extensions that need to | ||
use the `com.symphony.bdk.core.client.ApiClientFactory` class: | ||
```java | ||
public class MyBdkExtension implements BdkExtension, BdkApiClientFactoryAware { | ||
|
||
private ApiClientFactory apiClientFactory; | ||
|
||
@Override | ||
public void setApiClientFactory(ApiClientFactory apiClientFactory) { | ||
this.apiClientFactory = apiClientFactory; | ||
} | ||
} | ||
``` | ||
|
||
### `BdkAuthenticationAware` | ||
The interface `com.symphony.bdk.core.extension.BdkAuthenticationAware` can be used by extensions that need to rely on the | ||
service account authentication session (`com.symphony.bdk.core.auth.AuthSession`), which provides the `sessionToken` and | ||
`keyManagerToken` that are used to call the Symphony's APIs: | ||
```java | ||
public class MyBdkExtension implements BdkExtension, BdkAuthenticationAware { | ||
|
||
private AuthSession authSession; | ||
|
||
@Override | ||
public void setAuthSession(AuthSession authSession) { | ||
this.authSession = authSession; | ||
} | ||
} | ||
``` | ||
|
||
### `BdkRetryBuilderAware` | ||
The interface `com.symphony.bdk.core.extension.BdkRetryBuilderAware` allows extensions to leverage the internal BDK retry API | ||
through the `com.symphony.bdk.core.retry.RetryWithRecoveryBuilder<?>` class: | ||
```java | ||
public class MyBdkExtension implements BdkExtension, BdkRetryBuilderAware { | ||
|
||
private RetryWithRecoveryBuilder<?> retryBuilder; | ||
|
||
@Override | ||
public void setRetryBuilder(RetryWithRecoveryBuilder<?> retryBuilder) { | ||
this.retryBuilder = retryBuilder; | ||
} | ||
} | ||
``` |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# BDK Configuration | ||
This module contains the logic used to load a `BdkConfig` object from a YAML, JSON or properties file. For more detailed | ||
information, please read [symphony-bdk-java.finos.org/configuration](https://symphony-bdk-java.finos.org/configuration.html). | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
plugins { | ||
id 'bdk.java-library-conventions' | ||
id 'bdk.java-publish-conventions' | ||
} | ||
|
||
description = 'Symphony Java BDK Core - Configuration' | ||
|
||
dependencies { | ||
|
||
compileOnly 'org.projectlombok:lombok' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
|
||
api 'org.apiguardian:apiguardian-api' | ||
|
||
implementation 'org.slf4j:slf4j-api' | ||
implementation 'commons-io:commons-io' | ||
implementation 'org.apache.commons:commons-lang3' | ||
implementation 'org.apache.commons:commons-text' | ||
|
||
api 'com.fasterxml.jackson.core:jackson-databind' | ||
api 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml' | ||
api 'com.fasterxml.jackson.dataformat:jackson-dataformat-properties' | ||
|
||
testImplementation 'org.junit.jupiter:junit-jupiter' | ||
testImplementation 'ch.qos.logback:logback-classic' | ||
testImplementation 'org.assertj:assertj-core' | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
16 changes: 16 additions & 0 deletions
16
...config/src/main/java/com/symphony/bdk/core/config/exception/BdkConfigFormatException.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.symphony.bdk.core.config.exception; | ||
|
||
import org.apiguardian.api.API; | ||
|
||
/** | ||
* Thrown when a configuration field is not located at the right place in the YAML tree. | ||
* @see com.symphony.bdk.core.config.model.BdkSslConfig | ||
*/ | ||
@API(status = API.Status.STABLE) | ||
public class BdkConfigFormatException extends RuntimeException { | ||
|
||
public BdkConfigFormatException(String message) { | ||
super(message); | ||
} | ||
|
||
} |
File renamed without changes.
20 changes: 20 additions & 0 deletions
20
symphony-bdk-config/src/main/java/com/symphony/bdk/core/config/extension/BdkConfigAware.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.symphony.bdk.core.config.extension; | ||
|
||
import com.symphony.bdk.core.config.model.BdkConfig; | ||
|
||
import org.apiguardian.api.API; | ||
|
||
/** | ||
* Interface to be implemented by any {@code com.symphony.bdk.extension.BdkExtension} that wishes to access and read | ||
* the BDK configuration. | ||
*/ | ||
@API(status = API.Status.EXPERIMENTAL) | ||
public interface BdkConfigAware { | ||
|
||
/** | ||
* Set the {@link BdkConfig} object. | ||
* | ||
* @param config the {@code BdkConfig} instance to be used by this object | ||
*/ | ||
void setConfiguration(BdkConfig config); | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...config/model/BdkAuthenticationConfig.java → ...config/model/BdkAuthenticationConfig.java
This file contains 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
File renamed without changes.
Oops, something went wrong.