Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APP-3106 1.3-rc backports #264

Merged
merged 7 commits into from
Oct 5, 2020
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
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ New feature requests on the legacy SDK will not be accepted.
This repository contains both the legacy Java SDK under the [symphony-bdk-legacy module](symphony-bdk-legacy)
and the BDK2.0 under all other root modules.
Please check the [legacy module readme file](symphony-bdk-legacy/README.md) and the
[BDK2.0 architecture file](docs/internal/bdk-architecture.md) for more information.
[BDK architecture](docs/tech/architecture.md) documentation for more information.

## Testing

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ext.projectVersion = project.properties['projectVersion'] ?: '1.3.0.BETA'
ext.projectVersion = project.properties['projectVersion'] ?: '1.3.1.BETA'
ext.isReleaseVersion = !ext.projectVersion.endsWith('SNAPSHOT')

ext.symphonyRepoUrl = project.properties['symphonyRepoUrl'] ?: 'Symphony repository URL'
Expand Down
14 changes: 8 additions & 6 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ If you want to use [Maven](https://maven.apache.org/) as build system, you have
<dependency>
<groupId>com.symphony.platformsolutions</groupId>
<artifactId>symphony-bdk-bom</artifactId>
<version>1.2.1.BETA</version>
<version>1.3.1.BETA</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand All @@ -53,11 +53,13 @@ If you want to use [Maven](https://maven.apache.org/) as build system, you have
</dependency>
<dependency>
<groupId>com.symphony.platformsolutions</groupId>
<artifactId>symphony-bdk-core-invoker-jersey2</artifactId>
<artifactId>symphony-bdk-http-jersey2</artifactId> <!-- or symphony-bdk-http-webclient -->
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.symphony.platformsolutions</groupId>
<artifactId>symphony-bdk-template-freemarker</artifactId>
<artifactId>symphony-bdk-template-freemarker</artifactId> <!-- or symphony-bdk-http-handlebars -->
<scope>runtime</scope>
</dependency>
<!-- Logger implementation -->
<dependency>
Expand All @@ -84,12 +86,12 @@ repositories {
dependencies {

// import a BOM
implementation platform('com.symphony.platformsolutions:symphony-bdk-bom:1.2.1.BETA')
implementation platform('com.symphony.platformsolutions:symphony-bdk-bom:1.3.1.BETA')

// define dependencies without versions
implementation 'com.symphony.platformsolutions:symphony-bdk-core'
implementation 'com.symphony.platformsolutions:symphony-bdk-core-invoker-jersey2'
implementation 'com.symphony.platformsolutions:symphony-bdk-template-freemarker'
runtimeOnly 'com.symphony.platformsolutions:symphony-bdk-http-jersey2' // or symphony-bdk-http-webclient
runtimeOnly 'com.symphony.platformsolutions:symphony-bdk-template-freemarker' // or symphony-bdk-http-handlebars

implementation 'ch.qos.logback:logback-classic'
}
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ The reference documentation consists of the following sections:
Getting Started guides are also available for Spring Boot:
- [Core Starter](./spring-boot/core-starter.md)

### Technical Documentation
You can find an overview of the BDK Architecture [here](./tech/architecture.md).
18 changes: 0 additions & 18 deletions docs/internal/bdk-architecture.md

This file was deleted.

111 changes: 80 additions & 31 deletions docs/message.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,54 +17,103 @@ More precisely:

## How to use
The central component for the Message API is the `MessageService`.
It exposes all the services mentioned above and is accessible from the `SymphonyBdk` object by calling the `messages()` method.
For instance:

It exposes all the services mentioned above and is accessible from the `SymphonyBdk` object by calling the `messages()` method:
```java
import com.symphony.bdk.core.MessageService;

public class Example {
public static final String STREAM_ID = "gXFV8vN37dNqjojYS_y2wX___o2KxfmUdA";

public static void main(String[] args) throws Exception {
// Create BDK entry point
final SymphonyBdk bdk = new SymphonyBdk(loadFromClasspath("/config.yaml"));
// Get the MessageService object
final MessageService messageService = bdk.message();

//send a regular message
final V4Message regularMessage = messageService.send(STREAM_ID, "<messageML>Hello, World!</messageML>");
System.out.println("Message sent, id: " + regularMessage.getMessageId());
// send a regular message
final V4Message regularMessage = bdk.message().send(STREAM_ID, "<messageML>Hello, World!</messageML>");
log.info("Message sent, id: " + regularMessage.getMessageId());
}
}
```

A more detailed example with all exposed services can be found [here](../symphony-bdk-examples/bdk-core-examples/src/main/java/com/symphony/bdk/examples/MessageExampleMain.java).
## Using templates
The `MessageService` also allows you to send messages using templates. So far, the BDK supports two different template
engine implementations:
- [FreeMarker](https://freemarker.apache.org/) (through dependency `com.symphony.platformsolutions:symphony-bdk-template-freemarker`)
- [Handlebars](https://github.com/jknack/handlebars.java) (through dependency `com.symphony.platformsolutions:symphony-bdk-template-handlebars`)

### How to send a message from a template
> In the code examples below, we will assume that FreeMarker as been selected as template engine implementation.
> See [how to select the template engine implementation](#select-your-template-engine-implementation).

## Send messages with templates
The Message service also allows you to send messages using templates. So far, we only support [FreeMarker templates](https://freemarker.apache.org/),
but we may add support for other template engines.
For instance, if you have the following template file:
First you need to define your message template file. Here `src/main/resources/templates/simple.ftl`:
```
<messageML>${message}</messageML>
<messageML>Hello, ${name}!</messageML>
```
you will be able to use it when sending message:
```java
final SymphonyBdk bdk = new SymphonyBdk(loadFromClasspath("/config.yaml"));
final V4Message regularMessage = bdk().message().send(streamId, "path/to/template.ftl", Collections.singletonMap("message", "Hello!"));
public class Example {
public static final String STREAM_ID = "gXFV8vN37dNqjojYS_y2wX___o2KxfmUdA";

public static void main(String[] args) {
final SymphonyBdk bdk = new SymphonyBdk(loadFromClasspath("/config.yaml"));

final V4Message regularMessage = bdk.message().send(streamId, "/templates/simple.ftl", Collections.singletonMap("name", "User"));
}
}
```
The above will send the message `<messageML>Hello, User!</messageML>` as expected.

> Please note that the `MessageService` will try fetch template from different locations ordered by:
> 1. classpath
> 2. file system

It is also possible to get direct access to the `TemplateEngine` through the `MessageService`:
```java
public class Example {

public static void main(String[] args) {
final SymphonyBdk bdk = new SymphonyBdk(loadFromClasspath("/config.yaml"));

// load template from classpath location
final Template template = bdk.messages().templates().newTemplateFromClasspath("/complex-message.ftl");

// process template with some vars and retrieve content
// any POJO can also be processed by the template
final String content = template.process(Collections.singletonMap("name", "Freemarker"));

// display processed template content
log.info(content);
}
}
```

#### Select your template engine implementation
Developers are free to select the underlying template engine implementation. This can be done importing the right
dependency in your classpath.

With [Maven](./getting-started.md#maven-based-project):
```xml
<dependencies>
<dependency>
<groupId>com.symphony.platformsolutions</groupId>
<artifactId>symphony-bdk-template-freemarker</artifactId>
<scope>runtime</scope>
</dependency>
<!-- or -->
<dependency>
<groupId>com.symphony.platformsolutions</groupId>
<artifactId>symphony-bdk-template-handlebars</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
```
With [Gradle](./getting-started.md#gradle-based-project):
```groovy
dependencies {
runtimeOnly 'com.symphony.platformsolutions:symphony-bdk-template-freemarker'
// or
runtimeOnly 'com.symphony.platformsolutions:symphony-bdk-template-handlebars'
}
```
The above will send the message `<messageML>Hello!</messageML>` as expected.
Please check the [FreeMarker documentation](https://freemarker.apache.org/docs/pgui_quickstart_createdatamodel.html)
to know more about the data model you can use in templates and about the corresponding object structure you need to pass as parameter.

The template name passed as parameter can be the name of a built-in template
(only ["simpleMML"](../symphony-bdk-template/symphony-bdk-template-freemarker/src/main/resources/com/symphony/bdk/template/freemarker/simpleMML.ftl)
available so far), the path to a template file or a URL to a template file.
The templates will be looked for in this order:
* in built-in templates
* in the classpath
* in the file system
* lastly as a URL
> :warning: If multiple implementations found in classpath, an exception is throw in order to help you to define which one
> your project really needs to use.

----
[Home :house:](./index.md)
3 changes: 3 additions & 0 deletions docs/spring-boot/core-starter.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,6 @@ public class GifFormActivity extends FormReplyActivity<FormReplyContext> {
}
}
```

----
[Home :house:](../index.md)
46 changes: 46 additions & 0 deletions docs/tech/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# BDK Architecture Presentation
The Symphony BDK for Java is a multi-module library that uses [Gradle](https://gradle.org/) as build system.
This page will help to clearly understand how the library has been designed. This can be also useful for new contributors
aiming to provide additional features or implementations or existing APIs.

## Architecture Overview
The following diagram aims to give an overview of the different layers and modules provided by the BDK library.
![Architecture Overview Diagram](architecture.svg)

### symphony-bdk-core
The `symphony-bdk-core` is the main module that allows developers to write bots from a pure Java main application. It contains
all necessary BDK features such as:
- [configuration](../configuration.md)
- [authentication](../authentication.md)
- [datafeed](../datafeed.md)
- [services](../message.md)
- [activity API](../activity-api.md)

#### Code Generation
The `symphony-bdk-core` module relies on the [openapi-generator-maven-plugin](https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-maven-plugin/README.md)
to generate API clients and models from official Symphony's [Swagger specifications](https://github.com/symphonyoss/symphony-api-spec).
API's clients are located under package `com.symphony.bdk.gen.api` and models under `com.symphony.bdk.gen.api.model`.

### symphony-bdk-http
The `symphony-bdk-http-api` module defines a generic interface for performing HTTP calls. Along with this interface, it
also provides a utility `com.symphony.bdk.http.api.HttpClient` class helping developers to perform calls to external systems.
> :warning: It is important to notice that interface `com.symphony.bdk.http.api.ApiClient` is used by generated code.
> Changing contract would break the build. See [Code Generation](#code-generation).

At the moment, two different implementations have been created for the `com.symphony.bdk.http.api.ApiClient` interface:
- `com.symphony.bdk.http.jersey2.ApiClientJersey2` contained in module `symphony-bdk-http-jersey2` (default implementation for [Core](#symphony-bdk-core))
- `com.symphony.bdk.http.webclient.ApiClientWebClient` contained in module `symphony-bdk-http-webclient` (default implementation for [Spring Boot](#symphony-bdk-spring))

### symphony-bdk-template
The `symphony-bdk-template-api` module defines a set of interfaces that allows developers to load and fill text files with
data. This API is especially useful for complex MessageML templating.

At the moment, two different module implementations have been created:
- `symphony-bdk-template-freemarker`
- `symphony-bdk-template-handlebars`

### symphony-bdk-spring
The Symphony BDK comes also with two _starter_ modules to ease integration with the Spring Boot framework:
- `symphony-bdk-core-spring-boot-starter` that is basically a wrapper around the [symphony-bdk-core](#symphony-bdk-core) module
- `symphony-bdk-app-spring-boot-starter` that is a foundation for [Extension Applications](https://developers.symphony.com/symphony-developer/docs/overview-of-extension-applications)
backend development
1 change: 1 addition & 0 deletions docs/tech/architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ include(':symphony-bdk-http:symphony-bdk-http-webclient')

include(':symphony-bdk-template:symphony-bdk-template-api')
include(':symphony-bdk-template:symphony-bdk-template-freemarker')
include(':symphony-bdk-template:symphony-bdk-template-handlebars')

include(':symphony-bdk-spring:symphony-bdk-core-spring-boot-starter')
include(':symphony-bdk-spring:symphony-bdk-app-spring-boot-starter')

include(':symphony-bdk-examples:bdk-core-examples')
include(':symphony-bdk-examples:bdk-spring-boot-example')
include(':symphony-bdk-examples:bdk-template-examples')
4 changes: 2 additions & 2 deletions symphony-bdk-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ jacocoTestCoverageVerification {
}

dependencies {
implementation project(':symphony-bdk-http:symphony-bdk-http-api')
implementation project(':symphony-bdk-template:symphony-bdk-template-api')
api project(':symphony-bdk-http:symphony-bdk-http-api')
api project(':symphony-bdk-template:symphony-bdk-template-api')

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import com.symphony.bdk.http.api.ApiException;

import com.symphony.bdk.template.api.TemplateEngine;

import org.apiguardian.api.API;

/**
Expand All @@ -49,13 +51,15 @@ class ServiceFactory {
private final ApiClient agentClient;
private final AuthSession authSession;
private final BdkConfig config;
private final RetryWithRecoveryBuilder retryBuilder;
private final TemplateEngine templateEngine;
private final RetryWithRecoveryBuilder<?> retryBuilder;

public ServiceFactory(ApiClientFactory apiClientFactory, AuthSession authSession, BdkConfig config) {
this.podClient = apiClientFactory.getPodClient();
this.agentClient = apiClientFactory.getAgentClient();
this.authSession = authSession;
this.config = config;
this.templateEngine = TemplateEngine.getDefaultImplementation();
this.retryBuilder = new RetryWithRecoveryBuilder<>()
.retryConfig(config.getRetry())
.recoveryStrategy(ApiException::isUnauthorized, authSession::refresh);
Expand Down Expand Up @@ -108,8 +112,17 @@ public DatafeedService getDatafeedService() {
* @return an new {@link MessageService} instance.
*/
public MessageService getMessageService() {
return new MessageService(new MessagesApi(agentClient), new MessageApi(podClient),
new MessageSuppressionApi(podClient), new StreamsApi(podClient), new PodApi(podClient),
new AttachmentsApi(agentClient), new DefaultApi(podClient), authSession, retryBuilder);
return new MessageService(
new MessagesApi(this.agentClient),
new MessageApi(this.podClient),
new MessageSuppressionApi(this.podClient),
new StreamsApi(this.podClient),
new PodApi(this.podClient),
new AttachmentsApi(this.agentClient),
new DefaultApi(this.podClient),
this.authSession,
this.templateEngine,
this.retryBuilder
);
}
}
Loading