diff --git a/libraries/bot-integration-spring6/pom.xml b/libraries/bot-integration-spring6/pom.xml
new file mode 100644
index 000000000..70e846c02
--- /dev/null
+++ b/libraries/bot-integration-spring6/pom.xml
@@ -0,0 +1,83 @@
+
+
+ 4.0.0
+
+
+ com.microsoft.bot
+ bot-java
+ 4.15.0-SNAPSHOT
+ ../../pom.xml
+
+
+ bot-integration-spring6
+ jar
+
+ ${project.groupId}:${project.artifactId}
+ Bot Framework Integration Spring 6.x
+ https://dev.botframework.com/
+
+
+
+ MIT License
+ http://www.opensource.org/licenses/mit-license.php
+
+
+
+
+
+ Bot Framework Development
+
+ Microsoft
+ https://dev.botframework.com/
+
+
+
+
+ scm:git:https://github.com/Microsoft/botbuilder-java
+ scm:git:https://github.com/Microsoft/botbuilder-java
+ https://github.com/Microsoft/botbuilder-java
+
+
+
+ UTF-8
+ false
+
+
+
+
+
+ org.springframework
+ spring-framework-bom
+ 6.0.13
+ pom
+ import
+
+
+
+
+
+
+ org.springframework
+ spring-web
+
+
+ org.springframework
+ spring-context
+
+
+ com.microsoft.bot
+ bot-integration-core
+
+
+
+
+
+ build
+
+ true
+
+
+
+
+
+
diff --git a/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotController.java b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotController.java
new file mode 100644
index 000000000..57a49ae1d
--- /dev/null
+++ b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotController.java
@@ -0,0 +1,110 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.bot.integration.spring;
+
+import com.microsoft.bot.builder.Bot;
+import com.microsoft.bot.connector.authentication.AuthenticationException;
+import com.microsoft.bot.integration.BotFrameworkHttpAdapter;
+import com.microsoft.bot.schema.Activity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+/**
+ * This is the default controller that will receive incoming Channel Activity
+ * messages.
+ *
+ *
+ * This controller is suitable in most cases. Bots that want to use this
+ * controller should do so by using the @Import({BotController.class})
+ * annotation. See any of the samples Application class for an example.
+ *
+ */
+@RestController
+public class BotController {
+ /**
+ * The slf4j Logger to use. Note that slf4j is configured by providing Log4j
+ * dependencies in the POM, and corresponding Log4j configuration in the
+ * 'resources' folder.
+ */
+ private Logger logger = LoggerFactory.getLogger(BotController.class);
+
+ /**
+ * The BotFrameworkHttpAdapter to use. Note it is provided by dependency
+ * injection via the constructor.
+ */
+ private final BotFrameworkHttpAdapter adapter;
+
+ /**
+ * The Bot to use. Note it is provided by dependency
+ * injection via the constructor.
+ */
+ private final Bot bot;
+
+ /**
+ * Spring will use this constructor for creation.
+ *
+ *
+ * The Bot application should define class that implements {@link Bot} and
+ * annotate it with @Component.
+ *
+ *
+ * @see BotDependencyConfiguration
+ *
+ * @param withAdapter The BotFrameworkHttpAdapter to use.
+ * @param withBot The Bot to use.
+ */
+ public BotController(BotFrameworkHttpAdapter withAdapter, Bot withBot) {
+ adapter = withAdapter;
+ bot = withBot;
+ }
+
+ /**
+ * This will receive incoming Channel Activities.
+ *
+ * @param activity The incoming Activity.
+ * @param authHeader The incoming Authorization header.
+ * @return The request response.
+ */
+ @PostMapping("/api/messages")
+ public CompletableFuture> incoming(
+ @RequestBody Activity activity,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+
+ return adapter.processIncomingActivity(authHeader, activity, bot)
+
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity<>(
+ result.getBody(),
+ HttpStatus.valueOf(result.getStatus())
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+}
diff --git a/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotDependencyConfiguration.java b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotDependencyConfiguration.java
new file mode 100644
index 000000000..025a7de73
--- /dev/null
+++ b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/BotDependencyConfiguration.java
@@ -0,0 +1,175 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.microsoft.bot.integration.spring;
+
+import com.microsoft.bot.builder.ConversationState;
+import com.microsoft.bot.builder.MemoryStorage;
+import com.microsoft.bot.builder.Storage;
+import com.microsoft.bot.builder.UserState;
+import com.microsoft.bot.builder.inspection.InspectionState;
+import com.microsoft.bot.connector.ExecutorFactory;
+import com.microsoft.bot.connector.authentication.AuthenticationConfiguration;
+import com.microsoft.bot.connector.authentication.ChannelProvider;
+import com.microsoft.bot.connector.authentication.CredentialProvider;
+import com.microsoft.bot.integration.BotFrameworkHttpAdapter;
+import com.microsoft.bot.integration.ClasspathPropertiesConfiguration;
+import com.microsoft.bot.integration.Configuration;
+import com.microsoft.bot.integration.ConfigurationChannelProvider;
+import com.microsoft.bot.integration.ConfigurationCredentialProvider;
+import org.springframework.context.annotation.Bean;
+
+import java.util.concurrent.ExecutorService;
+
+/**
+ * This provides the default dependency creation for a Bot application.
+ *
+ *
+ * This class should be subclassed by a class with the
+ * {@link org.springframework.context.annotation.Configuration} annotation (or
+ * SpringBootApplication annotation).
+ *
+ *
+ *
+ * The Bot should be annotated with @Component, possibly including @AutoWired to
+ * indicate which constructor to use.
+ *
+ */
+public abstract class BotDependencyConfiguration {
+ /**
+ * Returns an ExecutorService.
+ *
+ *
+ * For now, return the bot-connector ExecutorService. This is an area of
+ * consideration. The goal here is to have a common ExecutorService to avoid
+ * multiple thread pools.
+ *
+ *
+ * @return An ExecutorService.
+ */
+ @Bean
+ public ExecutorService getExecutorService() {
+ return ExecutorFactory.getExecutor();
+ }
+
+ /**
+ * Returns the Configuration for the application.
+ *
+ * By default, it uses the {@link ClasspathPropertiesConfiguration} class.
+ * Default scope of Singleton.
+ *
+ * @return A Configuration object.
+ */
+ @Bean
+ public Configuration getConfiguration() {
+ return new ClasspathPropertiesConfiguration();
+ }
+
+
+ /**
+ * Returns the AuthenticationConfiguration for the application.
+ *
+ * By default, it uses the {@link AuthenticationConfiguration} class.
+ * Default scope of Singleton.
+ * @param configuration The Configuration object to read from.
+ * @return An AuthenticationConfiguration object.
+ */
+ @Bean
+ public AuthenticationConfiguration getAuthenticationConfiguration(Configuration configuration) {
+ return new AuthenticationConfiguration();
+ }
+
+ /**
+ * Returns the CredentialProvider for the application.
+ *
+ * By default, it uses the {@link ConfigurationCredentialProvider} class.
+ * Default scope of Singleton.
+ *
+ * @param configuration The Configuration object to read from.
+ * @return A CredentialProvider object.
+ *
+ * @see #getConfiguration()
+ */
+ @Bean
+ public CredentialProvider getCredentialProvider(Configuration configuration) {
+ return new ConfigurationCredentialProvider(configuration);
+ }
+
+ /**
+ * Returns the ChannelProvider for the application.
+ *
+ * By default, it uses the {@link ConfigurationChannelProvider} class. Default
+ * scope of Singleton.
+ *
+ * @param configuration The Configuration object to read from.
+ * @return A ChannelProvider object.
+ *
+ * @see #getConfiguration()
+ */
+ @Bean
+ public ChannelProvider getChannelProvider(Configuration configuration) {
+ return new ConfigurationChannelProvider(configuration);
+ }
+
+ /**
+ * Returns the BotFrameworkHttpAdapter for the application.
+ *
+ * By default, it uses the {@link BotFrameworkHttpAdapter} class. Default scope
+ * of Singleton.
+ *
+ * @param configuration The Configuration object to read from.
+ * @return A BotFrameworkHttpAdapter object.
+ *
+ * @see #getConfiguration()
+ */
+ @Bean
+ public BotFrameworkHttpAdapter getBotFrameworkHttpAdaptor(Configuration configuration) {
+ return new BotFrameworkHttpAdapter(configuration);
+ }
+
+ /**
+ * Returns a {@link Storage} object. Default scope of Singleton.
+ *
+ * @return A Storage object.
+ */
+ @Bean
+ public Storage getStorage() {
+ return new MemoryStorage();
+ }
+
+ /**
+ * Returns a ConversationState object. Default scope of Singleton.
+ *
+ * @param storage The Storage object to use.
+ * @return A ConversationState object.
+ */
+ @Bean
+ public ConversationState getConversationState(Storage storage) {
+ return new ConversationState(storage);
+ }
+
+ /**
+ * Returns a UserState object. Default scope of Singleton.
+ *
+ * @param storage The Storage object to use.
+ * @return A UserState object.
+ */
+ @Bean
+ public UserState getUserState(Storage storage) {
+ return new UserState(storage);
+ }
+
+ /**
+ * Creates an InspectionState used by
+ * {@link com.microsoft.bot.builder.inspection.InspectionMiddleware}. Default
+ * scope of Singleton.
+ *
+ * @param storage The Storage to use.
+ * {@link BotDependencyConfiguration#getStorage()}
+ * @return An InspectionState object that uses the specified storage.
+ */
+ @Bean
+ public InspectionState getInspectionState(Storage storage) {
+ return new InspectionState(storage);
+ }
+}
diff --git a/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/ChannelServiceController.java b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/ChannelServiceController.java
new file mode 100644
index 000000000..4ee1fdb1c
--- /dev/null
+++ b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/ChannelServiceController.java
@@ -0,0 +1,546 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MT License.
+
+package com.microsoft.bot.integration.spring;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+import com.microsoft.bot.builder.ChannelServiceHandler;
+import com.microsoft.bot.connector.authentication.AuthenticationException;
+import com.microsoft.bot.schema.Activity;
+import com.microsoft.bot.schema.AttachmentData;
+import com.microsoft.bot.schema.ChannelAccount;
+import com.microsoft.bot.schema.ConversationParameters;
+import com.microsoft.bot.schema.ConversationResourceResponse;
+import com.microsoft.bot.schema.ConversationsResult;
+import com.microsoft.bot.schema.PagedMembersResult;
+import com.microsoft.bot.schema.ResourceResponse;
+import com.microsoft.bot.schema.Transcript;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * A super.class for a skill controller.
+ */
+// Note: this class instanceof marked as abstract to prevent the ASP runtime from registering it as a controller.
+public abstract class ChannelServiceController {
+
+ /**
+ * The slf4j Logger to use. Note that slf4j is configured by providing Log4j
+ * dependencies in the POM, and corresponding Log4j configuration in the
+ * 'resources' folder.
+ */
+ private Logger logger = LoggerFactory.getLogger(BotController.class);
+
+ private final ChannelServiceHandler handler;
+
+ /**
+ * Initializes a new instance of the {@link ChannelServiceController}
+ * class.
+ *
+ * @param handler A {@link ChannelServiceHandler} that will handle
+ * the incoming request.
+ */
+ protected ChannelServiceController(ChannelServiceHandler handler) {
+ this.handler = handler;
+ }
+
+ /**
+ * SendToConversation.
+ *
+ * @param conversationId Conversation Id.
+ * @param activity Activity to send.
+ * @param authHeader Authentication header.
+ *
+ * @return A ResourceResponse.
+ */
+ @PostMapping("v3/conversations/{conversationId}/activities")
+ public CompletableFuture> sendToConversation(
+ @PathVariable String conversationId,
+ @RequestBody Activity activity,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+
+ return handler.handleSendToConversation(authHeader, conversationId, activity)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * ReplyToActivity.
+ *
+ * @param conversationId Conversation Id.
+ * @param activityId activityId the reply is to (OPTONAL).
+ * @param activity Activity to send.
+ * @param authHeader Authentication header.
+ *
+ * @return A ResourceResponse.
+ */
+ @PostMapping("v3/conversations/{conversationId}/activities/{activityId}")
+ public CompletableFuture> replyToActivity(
+ @PathVariable String conversationId,
+ @PathVariable String activityId,
+ @RequestBody Activity activity,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleReplyToActivity(authHeader, conversationId, activityId, activity)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * UpdateActivity.
+ *
+ * @param conversationId Conversation Id.
+ * @param activityId activityId to update.
+ * @param activity replacement Activity.
+ * @param authHeader Authentication header.
+ *
+ * @return A ResourceResponse.
+ */
+ @PutMapping("v3/conversations/{conversationId}/activities/{activityId}")
+ public CompletableFuture> updateActivity(
+ @PathVariable String conversationId,
+ @PathVariable String activityId,
+ @RequestBody Activity activity,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleUpdateActivity(authHeader, conversationId, activityId, activity)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * DeleteActivity.
+ *
+ * @param conversationId Conversation Id.
+ * @param activityId activityId to delete.
+ * @param authHeader Authentication header.
+ *
+ * @return A void result if successful.
+ */
+ @DeleteMapping("v3/conversations/{conversationId}/activities/{activityId}")
+ public CompletableFuture> deleteActivity(
+ @PathVariable String conversationId,
+ @PathVariable String activityId,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleDeleteActivity(authHeader, conversationId, activityId)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * GetActivityMembers.
+ *
+ * Markdown=Content\Methods\GetActivityMembers.getmd().
+ *
+ * @param conversationId Conversation Id.
+ * @param activityId Activity Id.
+ * @param authHeader Authentication header.
+ *
+ * @return A list of ChannelAccount.
+ */
+ @GetMapping("v3/conversations/{conversationId}/activities/{activityId}/members")
+ public CompletableFuture>> getActivityMembers(
+ @PathVariable String conversationId,
+ @PathVariable String activityId,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleGetActivityMembers(authHeader, conversationId, activityId)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity>(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * CreateConversation.
+ *
+ * @param parameters Parameters to create the conversation from.
+ * @param authHeader Authentication header.
+ *
+ * @return A ConversationResourceResponse.
+ */
+ @PostMapping("v3/conversations")
+ public CompletableFuture> createConversation(
+ @RequestBody ConversationParameters parameters,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleCreateConversation(authHeader, parameters)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * GetConversations.
+ *
+ * @param conversationId the conversation id to get conversations for.
+ * @param continuationToken skip or continuation token.
+ * @param authHeader Authentication header.
+ *
+ * @return A ConversationsResult.
+ */
+ @GetMapping("v3/conversations")
+ public CompletableFuture> getConversations(
+ @RequestParam String conversationId,
+ @RequestParam String continuationToken,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleGetConversations(authHeader, conversationId, continuationToken)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * GetConversationMembers.
+ *
+ * @param conversationId Conversation Id.
+ * @param authHeader Authentication header.
+ *
+ * @return A List of ChannelAccount.
+ */
+ @GetMapping("v3/conversations/{conversationId}/members")
+ public CompletableFuture>> getConversationMembers(
+ @PathVariable String conversationId,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleGetConversationMembers(authHeader, conversationId)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity>(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * GetConversationPagedMembers.
+ *
+ * @param conversationId Conversation Id.
+ * @param pageSize Suggested page size.
+ * @param continuationToken Continuation Token.
+ * @param authHeader Authentication header.
+ *
+ * @return A PagedMembersResult.
+ */
+ @GetMapping("v3/conversations/{conversationId}/pagedmembers")
+ public CompletableFuture> getConversationPagedMembers(
+ @PathVariable String conversationId,
+ @RequestParam(name = "pageSize", defaultValue = "-1") int pageSize,
+ @RequestParam(name = "continuationToken") String continuationToken,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleGetConversationPagedMembers(authHeader, conversationId, pageSize, continuationToken)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * DeleteConversationMember.
+ *
+ * @param conversationId Conversation Id.
+ * @param memberId D of the member to delete from this
+ * conversation.
+ * @param authHeader Authentication header.
+ *
+ * @return A void result.
+ */
+ @DeleteMapping("v3/conversations/{conversationId}/members/{memberId}")
+ public CompletableFuture> deleteConversationMember(
+ @PathVariable String conversationId,
+ @PathVariable String memberId,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleDeleteConversationMember(authHeader, conversationId, memberId)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * SendConversationHistory.
+ *
+ * @param conversationId Conversation Id.
+ * @param history Historic activities.
+ * @param authHeader Authentication header.
+ *
+ * @return A ResourceResponse.
+ */
+ @PostMapping("v3/conversations/{conversationId}/activities/history")
+ public CompletableFuture> sendConversationHistory(
+ @PathVariable String conversationId,
+ @RequestBody Transcript history,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleSendConversationHistory(authHeader, conversationId, history)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+
+ /**
+ * UploadAttachment.
+ *
+ * @param conversationId Conversation Id.
+ * @param attachmentUpload Attachment data.
+ * @param authHeader Authentication header.
+ *
+ * @return A ResourceResponse.
+ */
+ @PostMapping("v3/conversations/{conversationId}/attachments")
+ public CompletableFuture> uploadAttachment(
+ @PathVariable String conversationId,
+ @RequestBody AttachmentData attachmentUpload,
+ @RequestHeader(value = "Authorization", defaultValue = "") String authHeader
+ ) {
+ return handler.handleUploadAttachment(authHeader, conversationId, attachmentUpload)
+ .handle((result, exception) -> {
+ if (exception == null) {
+ if (result != null) {
+ return new ResponseEntity(
+ result,
+ HttpStatus.OK
+ );
+ }
+ return new ResponseEntity<>(HttpStatus.ACCEPTED);
+ }
+
+ logger.error("Exception handling message", exception);
+
+ if (exception instanceof CompletionException) {
+ if (exception.getCause() instanceof AuthenticationException) {
+ return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ } else {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ });
+ }
+}
diff --git a/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/package-info.java b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/package-info.java
new file mode 100644
index 000000000..b40602d73
--- /dev/null
+++ b/libraries/bot-integration-spring6/src/main/java/com/microsoft/bot/integration/spring/package-info.java
@@ -0,0 +1,9 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for
+// license information.
+
+/**
+ * This package contains the classes for com.microsoft.bot.integration.spring.
+ */
+@Deprecated
+package com.microsoft.bot.integration.spring;
diff --git a/pom.xml b/pom.xml
index 95c92d755..7e67d14d0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -468,6 +468,7 @@
libraries/bot-applicationinsights
libraries/bot-azure
libraries/bot-integration-spring
+ libraries/bot-integration-spring6