Skip to content

Commit

Permalink
APP-3073: Enhancements on MessageService (#277)
Browse files Browse the repository at this point in the history
* Add internal dependencies version to bom module

* Update missing dependencies

* Adding plugin to http and template submodule

* Ability to directly set privateKey and certificate content

User can set the privateKey and certificate content in bytes array to BdkConfig
for bot and app authentication.

Only one of path or content should be configured. If user configure both of them,
an AuthInitializationException will be thrown. The exception should be thrown at the step of
initializing the Authenticator instead of loading config because the BdkConfig can be set programmatically.

Unittest added

* Fix typo and add documentation

* Update documentation

* Enhancements on message service

Move MessageService to package com.symphony.bdk.core.service.message

Make the TemplateException extends RuntimeException -> Remove all the throws TemplateException.

Rename MessageService#send(streamId, template, Object) -> MessageService#sendWithTemplate
Provide MessageService#send(streamId, template) to send a templated message without passing any parameter instead of passing null to the existing method.

Provide method MessageService#send(streamId, message, data, attachment) to send a message with data and attachment (streamId can be replaced by a V4Stream instance)

Small fix on webclient api to perform multipart/form-data request.

Unittest added

* Create message and attachment model to use in MessageService

Adding two methods to send message passing a Message instance instead of many parameters
Adding ComplexMessageExampleMain.java to show the usage of the Message model.

These methods and example is under reviewing. The code will be refactored after review.

* Refactor MessageService and update unittest

* Provide MessageService#builder to build a message instance from MessageService

* Update handling attachments
  • Loading branch information
symphony-hong authored Oct 9, 2020
1 parent fb8f0d1 commit 4e33973
Show file tree
Hide file tree
Showing 30 changed files with 491 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.symphony.bdk.core.client.ApiClientFactory;
import com.symphony.bdk.core.config.model.BdkConfig;
import com.symphony.bdk.core.retry.RetryWithRecoveryBuilder;
import com.symphony.bdk.core.service.MessageService;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.SessionService;
import com.symphony.bdk.core.service.datafeed.DatafeedService;
import com.symphony.bdk.core.service.datafeed.DatafeedVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import com.symphony.bdk.core.auth.exception.AuthUnauthorizedException;
import com.symphony.bdk.core.client.ApiClientFactory;
import com.symphony.bdk.core.config.model.BdkConfig;
import com.symphony.bdk.core.service.MessageService;
import com.symphony.bdk.core.service.message.MessageService;
import com.symphony.bdk.core.service.SessionService;
import com.symphony.bdk.core.service.datafeed.DatafeedService;
import com.symphony.bdk.core.service.stream.StreamService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private PrivateKey loadPrivateKeyFromAuthenticationConfig(BdkAuthenticationConfi
try {
String privateKey;
if (isNotEmpty(config.getPrivateKeyContent())) {
privateKey = new String(config.getPrivateKeyContent());
privateKey = new String(config.getPrivateKeyContent(), StandardCharsets.UTF_8);
} else {
String privateKeyPath = config.getPrivateKeyPath();
log.debug("Loading RSA privateKey from path : {}", privateKeyPath);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.symphony.bdk.core.service;
package com.symphony.bdk.core.service.message;


import com.symphony.bdk.core.auth.AuthSession;
import com.symphony.bdk.core.retry.RetryWithRecovery;
import com.symphony.bdk.core.retry.RetryWithRecoveryBuilder;
import com.symphony.bdk.core.service.message.exception.MessageCreationException;
import com.symphony.bdk.core.service.message.model.Attachment;
import com.symphony.bdk.core.service.message.model.Message;
import com.symphony.bdk.core.service.message.model.MessageBuilder;
import com.symphony.bdk.core.service.pagination.PaginatedApi;
import com.symphony.bdk.core.service.pagination.PaginatedService;
import com.symphony.bdk.core.service.stream.constant.AttachmentSort;
Expand All @@ -27,12 +31,15 @@
import com.symphony.bdk.gen.api.model.V4Stream;
import com.symphony.bdk.http.api.util.ApiUtils;
import com.symphony.bdk.template.api.TemplateEngine;
import com.symphony.bdk.template.api.TemplateException;
import com.symphony.bdk.template.api.TemplateResolver;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apiguardian.api.API;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.time.Instant;
import java.util.List;
import java.util.stream.Stream;
Expand Down Expand Up @@ -93,6 +100,15 @@ public TemplateEngine templates() {
return templateEngine;
}

/**
* Returns the {@link MessageBuilder} that can be used to build a {@link Message} to be sent.
*
* @return the message builder
*/
public MessageBuilder builder() {
return new MessageBuilder(this);
}

/**
* Get messages from an existing stream. Additionally returns any attachments associated with the message.
*
Expand Down Expand Up @@ -164,47 +180,23 @@ public Stream<V4Message> getMessagesStream(@Nonnull String streamId, @Nonnull In
* @param message the message payload in MessageML
* @return a {@link V4Message} object containing the details of the sent message
* @see <a href="https://developers.symphony.com/restapi/reference#create-message-v4">Create Message v4</a>
* @deprecated this method will be replaced by {@link MessageService#send(V4Stream, Message)}
*/
@Deprecated
public V4Message send(@Nonnull V4Stream stream, @Nonnull String message) {
return send(stream.getStreamId(), message);
}

/**
* Sends a templated to the stream ID of the passed {@link V4Stream} object.
*
* @param stream the stream to send the message to
* @param template the template name to be used to produce the message
* @param parameters the parameters to pass to the template to produce the message to be sent
* @return a {@link V4Message} object containing the details of the sent message
* @see <a href="https://developers.symphony.com/restapi/reference#create-message-v4">Create Message v4</a>
*/
public V4Message send(@Nonnull V4Stream stream, @Nonnull String template, Object parameters)
throws TemplateException {
return send(stream.getStreamId(), templateResolver.resolve(template).process(parameters));
}

/**
* Sends a templated to the stream ID passed in parameter.
*
* @param streamId the ID of the stream to send the message to
* @param template the template name to be used to produce the message
* @param parameters the parameters to pass to the template to produce the message to be sent
* @return a {@link V4Message} object containing the details of the sent message
* @throws TemplateException
*/
public V4Message send(@Nonnull String streamId, @Nonnull String template, Object parameters)
throws TemplateException {
return send(streamId, templateResolver.resolve(template).process(parameters));
}

/**
* Sends a message to the stream ID passed in parameter.
*
* @param streamId the ID of the stream to send the message to
* @param message the message payload in MessageML
* @return a {@link V4Message} object containing the details of the sent message
* @see <a href="https://developers.symphony.com/restapi/reference#create-message-v4">Create Message v4</a>
* @deprecated this method will be replaced by {@link MessageService#send(String, Message)}
*/
@Deprecated
public V4Message send(@Nonnull String streamId, @Nonnull String message) {
return executeAndRetry("send", () -> messagesApi.v4StreamSidMessageCreatePost(
streamId,
Expand All @@ -218,6 +210,49 @@ public V4Message send(@Nonnull String streamId, @Nonnull String message) {
));
}

/**
* Sends a message to the stream ID passed in parameter.
*
* @param streamId the ID of the stream to send the message to
* @param message the message to send to the stream
* @return a {@link V4Message} object containing the details of the sent message
* @see <a href="https://developers.symphony.com/restapi/reference#create-message-v4">Create Message v4</a>
*/
public V4Message send(@Nonnull String streamId, @Nonnull Message message) {
File tempFile = this.createTemporaryAttachmentFile(message.getAttachment());
try {
return executeAndRetry("send", () -> messagesApi.v4StreamSidMessageCreatePost(
streamId,
authSession.getSessionToken(),
authSession.getKeyManagerToken(),
message.getContent(),
message.getData(),
message.getVersion(),
tempFile,
null
)
);
} finally {
try {
Files.deleteIfExists(tempFile.toPath());
} catch (IOException ignored) {

}
}
}

/**
* Sends a message to the stream ID passed in parameter.
*
* @param stream the stream to send the message to
* @param message the message to send to the stream
* @return a {@link V4Message} object containing the details of the sent message
* @see <a href="https://developers.symphony.com/restapi/reference#create-message-v4">Create Message v4</a>
*/
public V4Message send(@Nonnull V4Stream stream, @Nonnull Message message) {
return send(stream.getStreamId(), message);
}

/**
* Downloads the attachment body by the stream ID, message ID and attachment ID.
*
Expand Down Expand Up @@ -386,4 +421,18 @@ private static Long getEpochMillis(Instant instant) {
private <T> T executeAndRetry(String name, SupplierWithApiException<T> supplier) {
return RetryWithRecovery.executeAndRetry(retryBuilder, name, supplier);
}

private File createTemporaryAttachmentFile(Attachment attachment) {
if (attachment == null) {
return null;
}
try {
String tempDir = System.getProperty("java.io.tmpdir");
File tempFile = new File(tempDir + File.separator + attachment.getFilename());
FileUtils.copyInputStreamToFile(attachment.getInputStream(), tempFile);
return tempFile;
} catch (IOException e) {
throw new MessageCreationException("Cannot create attachment.", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.symphony.bdk.core.service.message.exception;

import org.apiguardian.api.API;

/**
* Exception thrown when a {@link com.symphony.bdk.core.service.message.model.Message} is failed to create.
*/
@API(status = API.Status.STABLE)
public class MessageCreationException extends RuntimeException {

public MessageCreationException(String message, Exception e) {
super(message, e);
}

public MessageCreationException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.symphony.bdk.core.service.message.model;

import com.symphony.bdk.core.service.message.exception.MessageCreationException;

import lombok.Getter;
import org.apiguardian.api.API;

import java.io.InputStream;

/**
* Attachment model to be used in {@link MessageBuilder} to attach a file to a {@link Message}
*/
@Getter
@API(status = API.Status.EXPERIMENTAL)
public class Attachment {

private final InputStream inputStream;
private final String filename;

public Attachment(InputStream inputStream, String filename) {
this.inputStream = inputStream;
if (filename.split("\\.").length < 2 ) {
throw new MessageCreationException("Invalid attachment's file name.");
}
this.filename = filename;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.symphony.bdk.core.service.message.model;

import com.symphony.bdk.gen.api.model.V4Stream;

import lombok.Getter;
import org.apiguardian.api.API;

/**
* Message model to be used in {@link com.symphony.bdk.core.service.message.MessageService#send(V4Stream, Message)}
*/
@Getter
@API(status = API.Status.EXPERIMENTAL)
public class Message {

// The version of the MessageML format
private final String version;
private final String content;
private final String data;
private final Attachment attachment;

protected Message(MessageBuilder builder) {
this.version = builder.version();
this.content = builder.content();
this.data = builder.data();
this.attachment = builder.attachment();
}

}
Loading

0 comments on commit 4e33973

Please sign in to comment.