Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

create bot-integration-spring6 module that will work with spring 6.x #1522

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
83 changes: 83 additions & 0 deletions libraries/bot-integration-spring6/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.microsoft.bot</groupId>
<artifactId>bot-java</artifactId>
<version>4.15.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

<artifactId>bot-integration-spring6</artifactId>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
<description>Bot Framework Integration Spring 6.x</description>
<url>https://dev.botframework.com/</url>

<licenses>
<license>
<name>MIT License</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
</license>
</licenses>

<developers>
<developer>
<name>Bot Framework Development</name>
<email></email>
<organization>Microsoft</organization>
<organizationUrl>https://dev.botframework.com/</organizationUrl>
</developer>
</developers>

<scm>
<connection>scm:git:https://github.com/Microsoft/botbuilder-java</connection>
<developerConnection>scm:git:https://github.com/Microsoft/botbuilder-java</developerConnection>
<url>https://github.com/Microsoft/botbuilder-java</url>
</scm>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.deploy.skip>false</maven.deploy.skip>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>6.0.13</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.bot</groupId>
<artifactId>bot-integration-core</artifactId>
</dependency>
</dependencies>

<profiles>
<profile>
<id>build</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
</build>
</profile>
</profiles>
</project>
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>
* 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.
* </p>
*/
@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.
*
* <p>
* The Bot application should define class that implements {@link Bot} and
* annotate it with @Component.
* </p>
*
* @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<ResponseEntity<Object>> 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);
}
});
}
}
Original file line number Diff line number Diff line change
@@ -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.
*
* <p>
* This class should be subclassed by a class with the
* {@link org.springframework.context.annotation.Configuration} annotation (or
* SpringBootApplication annotation).
* </p>
*
* <p>
* The Bot should be annotated with @Component, possibly including @AutoWired to
* indicate which constructor to use.
* </p>
*/
public abstract class BotDependencyConfiguration {
/**
* Returns an ExecutorService.
*
* <p>
* 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.
* </p>
*
* @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);
}
}
Loading