Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Building Microsoft Teams Tabs Apps with Java Part 3: Creating a Conversational Tab App

0.00/5 (No votes)
16 Nov 2021 2  
In this article we'll explore creating a conversational tab app.
Here we'll demonstrate how to create a Spring Boot web app in Java that replicates the functionality of the Create conversational tab sample app on GitHub.

This is the final article in a three-part series demonstrating using the Microsoft Teams sample library to jump-start building your own Teams applications. First, I created a personal tab and a channel tab with a single sign-on (SSO). For this article, I’ll build a conversational tab app.

Microsoft provides an excellent overview of Teams apps and conversational tabs. These tabs are associated with a channel and provide a place for side conversations related to the primary tab. For example, if the channel discusses building Teams apps, a conversational tab might be for discussing a targeted sub-topic like how to use SSO.

Conversational tab apps are always associated with a channel, so these apps need a configuration page to select the associated channel. In this article, I'll build an application with an example configuration page and control page that you can use to create, continue, delete, and pin conversational tabs. You should know some Java to follow along, and I’ll show you how to use Teams.

Creating the Application Using Spring Initializr

I used the Spring Boot Initializr to build the initial application package and included these dependencies:

  • Spring Web
  • Thymeleaf
  • Spring Boot DevTools

Click Generate to create a ZIP file that provides the complete Maven infrastructure and initial runtime class. Unzip the resources into your project directory and import the directory as an existing Maven project into Eclipse.

In Eclipse, select File > Import to display this dialog:

Select Existing Maven Projects and click Next to display this dialog:

Select the directory to which you unzipped the file downloaded from Spring Initializr, check the box next to your project and click Finish.

I didn’t add Bootstrap to this application, but if you would like to, add the dependency below to the pom.xml file after you import the project; I will discuss the required HTML changes when I cover web pages.

XML
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.0.0-2</version>
</dependency>

Although I’ll show some pieces of the code in this article, you can find the complete source on GitHub.

Preparing the Core Java Code

This application is a basic Spring Boot web app. The conversion from the C# MVC application is direct. The following Java classes derive from the corresponding C# files:

Java Class File C# Class Source File
AppConfiguration.java Startup.cs
ConversationaltabApplication.java Program.cs
HomeController.java HomeController.cs

When Spring Boot starts our application, it runs main in the ConversationaltabApplication class. This class uses the default class implementation that the Spring Boot starter provides.

The AppConfiguration class configures the Spring Boot engine.

We must remember that Teams launches our application in an iframe, and Azure App Service’s web application server enforces cross-frame scripting security. So, I need to add some code to allow my application to run. The entire class is below:

Java
package com.contentlab.teams.java.conversationaltab; 
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
@Configuration
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.headers()
.contentSecurityPolicy( "frame-ancestors 'self' https://*.microsoftonline.com  https://*.microsoft.com https://*.azurewebsites.net;"
);
}
}

Mozilla states that the content-security-policy header obsoletes the X-FRAME-OPTIONS header, so I implement the newer method in this application. You need to change https://*.azurewebsites.net to match your hosting domain.

The HomeController provides direct mappings and handlers for the index, configure, and conversation tab pages. I annotate this class with @Controller because the response contains web pages.

Preparing Web Pages and Their Supporting JavaScript

Three web pages provide the client implementation. These are almost direct copies of the .cshtml pages in the C# sample, with only minor changes for Thymeleaf.

Java Application HTML File C# HTML Source File
index.html index.cshtml
configure.html configure.cshtml
conversationTab.html conversation-tab.cshtml

I use the Microsoft sample application’s style sets. But, if you want to use Bootstrap, I made these HTML changes to enable Bootstrap in my other articles.

First, add this link and script to the <head> section:

JavaScript
<link th:rel="stylesheet" 
th:href="@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css}"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
</script>

Then, add these scripts to the end of the <body> section:

JavaScript
<script th:src="@{/webjars/jquery/3.0.0/jquery.min.js}"></script>
<script th:src="@{/webjars/popper.js/1.12.9-1/umd/popper.min.js}"></script>
<script th:src="@{/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js}"></script>
 
</body>
</html>

If you add the code above to your web page, make sure to add the Bootstrap dependency to your pom.xml file to include the WebJars.

The index page is a placeholder. The application needs to have one, and you’ll want to provide some interesting content about your application there. However, its content isn’t part of this application’s primary function.

Teams loads the configure page when you add the application. There’s not much HTML, but the page’s JavaScript provides the following functions: register an onSave handler, provide an onChange handler, and create a URL for the selected tab.

The application calls the onSave handler when the user clicks on the page’s Save button. This handler’s key code is:

JavaScript
microsoftTeams.settings.setSettings({
                contentUrl: createTabUrl(),
                entityId: createTabUrl(),
            	);

This code passes the URL to the Teams conversation tab. The createTablUrl function, which maps the selected item in the dropdown to a web page in the application, generates the URL:

JavaScript
// Create the URL that Microsoft Teams will load in the tab. 
// You can compose any URL even with query strings.
function createTabUrl() {
var tabChoice = document.getElementById('tabChoice');
var selectedTab = tabChoice[tabChoice.selectedIndex].value;
 
return (
window.location.protocol
+ '//' + window.location.host + '/'
+ selectedTab
+ "?myQueryStringProp1=1;myQueryStringProp2=2;"
);
}

The conversationTab page lists conversation operations that users can request, and it hosts the conversation tab. Microsoft covers these operations in detail. The start, continue, and deeplink operations refer to a context object that the application obtains by calling a Microsoft Teams SDK function. This application logs the context to the console. I’ve shown a few critical pieces below:

channelId: 19:Utecs0ByuQxaNnA8HhkFrBEz_plbPX0maJnwG_KrJog1@thread.tacv2
entityId: "https://conversationaltab-1634904929775.azurewebsites.net/conversationTab"
groupId: "ce1393cf-aae3-4c01-918e-dedff22e6ab1"
tid: "3f5e2095-387d-4e32-b295-5d460844cd78"

A complete discussion about tab context is available.

Deploying the Application

Maven provides tools to create an Azure App Service plan and deploy the application there. To use the tools, run the commands below. I ran these on Windows, so you’ll need to change the commands if you are running Linux or macOS:

First, open a command prompt (cmd) window. Then, change directory (cd) to the project directory containing the pom.xml file. Finally, execute these commands:

  • az login --tenant 26e17e8f-8a99-44f3-a027-54de7b19f3af
  • mvn com.microsoft.azure:azure-webapp-maven-plugin:2.2.0:config
  • mvn package azure-webapp:deploy

The az login command logs you into Azure so that Maven can create resources. The first mvn command captures the information to make the Azure App Service plan and stores the data in the pom.xml file. The second mvn command deploys the application to this plan. You will run this command every time you update your application and push it to Azure App Service. I provided examples of successful results in the first article in this series.

Testing in Teams

You can use Teams App Studio to create a Manifest, but Microsoft will deprecate that application in 2022 so I won’t demonstrate it here. For this implementation, I copy the AppManifest/manifest.json file from the C# example and modify it. This file’s complete documentation is available on Microsoft’s website.

JavaScript
{
  "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.11/MicrosoftTeams.schema.json",
  "manifestVersion": "1.11",
  "version": "1.0.0",
  "id": "<< You can put any unique ID here >>",
  "packageName": "com.contentlab.teams.java.conversationaltab",
  "developer": {
    "name": "Microsoft",
    "websiteUrl": "https://www.microsoft.com",
    "privacyUrl": "https://www.microsoft.com/privacy",
    "termsOfUseUrl": "https://www.microsoft.com/termsofuse"
  },
  "name": {
    "short": "Java Conversational Tab",
    "full": "Java Conversational Tab"
  },
  "description": {
    "short": "Java - View Tab With Conversations",
    "full": "Java - This sample demos conversational tabs"
  },
  "icons": {
    "outline": "outline.png",
    "color": "color.png"
  },
  "accentColor": "#60A18E",
  "configurableTabs": [
    {
      "configurationUrl": "https://conversationaltab-1634904929775.azurewebsites.net/configure",
      "canUpdateConfiguration": true,
      "scopes": [
        "team"
      ],
      "context": [
        "channelTab"
      ]
    }
  ],
  "permissions": [ "identity", "messageTeamMembers" ],
  "validDomains": [
        "*.azurewebsites.net"
    ]
}

I’ve described this process in my earlier articles, but here’s a reminder: I create a ZIP file containing this manifest file and the outline and color icons that the manifest lists. I then upload the ZIP file to Teams. Then, I add the selected application to a team in Microsoft Teams, like below:

Click Add to a Team. Teams then displays this dialog:

Use the Search tool to select a Team. That action enables the Set up a tab button. Click the button to display our application’s configure page:

The configure page only lists one tab, so select it from the dropdown. This action enables the Save button. Click on it. Teams then opens the conversationTab page using the URL in the configure page, including the query string.

When you click on one of the icons, like the Start Conversation icon, Teams displays the conversation tab.

Note that the query string passes the tab title. You can add content to the conversation in the text entry box at the tab’s bottom right.

Summary

You now have your own Teams app to enable sub-conversations on a channel. I’ve also provided a pattern for using the Microsoft Teams samples library. The library contains many example applications, which provide the infrastructure to make an existing web application accessible in Teams. Teams becomes your personal portal for working with others.

For example, if you create a channel for each task in your sprint backlog, you can attach one of these conversation tabs to each channel. While the mainline conversation about each item happens in the channel, you can discuss related details in the tabs and share them with others as needed. Imagine capturing a whole conversation tree about a complex topic in one place, with a structure that matches the conversations. Try doing that with email.

I’ve cited several Microsoft articles here that provide overviews and details to help you build Teams applications. Microsoft’s documentation is extensive and relevant. Also, because Teams applications are just web applications, all your Java skills are directly applicable. I didn’t explicitly cover it, but the Microsoft Teams API in Microsoft Graph is used throughout this sample, so you’ll want to learn it to fully appreciate what it can do for you when you start creating your own applications. Fortunately, that’s just a new library — not a new language or platform.

Welcome to your new groupware platform for remote work!

Dive in and start developing productivity-boosting Teams apps for your organization, create a handy new app for yourself, or help millions of active daily users through the Microsoft Teams store.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here