Hands-on-Confluence-Cloud-Apps mit Spring Boot und Atlassian Connect (Teil 2)

Nachdem wir im ersten Teil die Basisanwendung und erste Webhooks integriert haben, folgen in diesem zweiten Teil nun weitere Integrationen in unsere Confluence-Cloud-Entwicklungsinstanz.

Dynamisch erstellte Seite in Confluence Cloud verlinken und darstellen

Wir erstellen zunächst einen Spring-Controller, der ein einfaches Template mit der Template-Sprache Thymeleaf rendert und einen Parameter zum Render-Kontext beisteuert:

@Controller
public class InfoController {

  @RequestMapping(value = "/info-page", method = RequestMethod.GET)
  public String infoPage(@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) {
    model.addAttribute("userKey", hostUser.getUserKey());
    return "info-page";
  }
}

In unserem Template geben wir den Parameter aus und stellen ebenfalls alle anderen verfügbaren Parameter unseres Render-Kontexts dar:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <script th:src="@{${atlassianConnectAllJsUrl}}" type="text/javascript"></script>

  <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.0/css/aui.min.css" media="all"/>
  <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.0/css/aui-experimental.min.css" media="all"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
</head>
<body>
<div>
  <h2>//SEIBERT/MEDIA Cloud Application</h2>
  <dl>
    <dt>User-Key</dt>
    <dd th:text="${userKey}"/>
  </dl>
  <hr/>
  <table class="aui">
    <tr th:each="var : ${#vars}">
      <td th:text="${var.key}"></td>
      <td th:text="${var.value}"></td>
    </tr>
  </table>
</div>
</body>
</html>

Nun ergänzen wir den Plugin-Descriptor um das folgende Element, um die Darstellung unserer Seite in der Confluence-Cloud-Instanz zu registrieren:

"modules": {
	"generalPages": [
	  {
		"url": "/info-page",
		"name": {
			"value": "Seibert Media"
		},
		"key": "sm-info-page"
	  }
	]
}

Danach ergänzen wir ein weiteres Element im Descriptor, um im Atlassian-Hilfemenü eine Verknüpfung auf unsere dynamische Seite zu erzeugen:

"modules": {
	"webItems": [
		{
			"key": "info-page-web-item",
			"location": "system.help",
			"weight": 200,
			"url": "/info-page",
			"name": {
				"value": "Seibert Media"
			}
		}
	]
}

Dann müssen wir (wie im ersten Teil des Tutorial demonstriert) unseren Plugin-Descriptor erneut hochladen.

Im Anschluss daran können wir über das Hilfemenü unsere dynamisch und Server-seitig erzeugte Seite aufrufen:

Seiten- und Menüintegration

Seiten- und Menüintegration

Confluence-Cloud-Daten per REST-Client abrufen

Im nächsten Beispiel möchten wir Build-Informationen, die Confluence Cloud über eine REST-Ressource bereitstellt, abrufen.

Dazu werden wir aus unserer Spring-Boot-Anwendung heraus eine OAuth2-authentifizierte Client-Verbindung zu den RESTful Webservices unserer Confluence-Cloud-Instanz aufbauen und die abgerufenen Build-Informationen wiederum unter einer URL verfügbar machen.

Dies ist unser Datentransferobjekt (DTO), das einige der Build-Informationen kapselt:

public class BuildInformation {
  private String versionNumber;
  private String buildTimestamp;
  private String buildNumber;
  private String revisionNumber;

  // getter, setter, tostring...
}

Hier ist unser beispielhafter REST-Client, der mittels AtlassianHostRestClients eine authentifizierte Verbindung zur Confluence-Cloud-Instanz aufbaut:

@Service
public class ConfluenceClientService {
  [..]

  @Autowired
  private AtlassianHostRestClients atlassianHostRestClients;

  public BuildInformation getBuildInformation(String baseUrl) {
    String url = baseUrl + "/rest/prototype/latest/buildInfo";

    log.info("calling confluence host with api-url: {}", url);
    return atlassianHostRestClients.authenticatedAsAddon()
        .getForObject(url, BuildInformation.class);
  }
}

Dies ist ein vereinfachter Controller, der von der ersten ihm bekannten Confluence-Cloud-Instanz die URL ermittelt, sie an den REST-Client übergibt und dann die Ansicht der Build-Informationen darstellt.

In einem Produktivszenario müssten wir natürlich die Tatsache berücksichtigen, dass 0..n Confluence-Cloud-Instanzen mit unserer Spring-Boot-Anwendung verbunden sein können.

@Controller
public class ConnectedHostsAudit {

  @Autowired
  ConfluenceClientService confluenceClientService;

  @Autowired
  AtlassianHostRepository atlassianHostRepository;

  @RequestMapping("/build-info")
  public String buildInformationPage(Model model) {
    AtlassianHost host = atlassianHostRepository.findAll().iterator().next();
    String baseUrl = host.getBaseUrl();
    BuildInformation buildInformation = confluenceClientService.getBuildInformation(baseUrl);
    model.addAttribute("buildInformation", buildInformation);
    model.addAttribute("host", host);
    return "build-info";
  }
}

Das folgende Thymeleaf-Template stellt die abgerufenen Build-Informationen dar:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <script th:src="@{${atlassianConnectAllJsUrl}}" type="text/javascript"></script>

  <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.0/css/aui.min.css" media="all"/>
  <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/6.0.0/css/aui-experimental.min.css"
        media="all"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
  <script src="https:///aui-cdn.atlassian.com/aui-adg/6.0.0/js/aui.min.js"></script>
</head>
<body>
<div>
  <h2>//SEIBERT/MEDIA Cloud Application - Build Information for Host '<span th:text="${host.baseUrl}"/>'</h2>
  <table class="aui">
    <tr>
      <td>versionNumber</td>
      <td th:text="${buildInformation.versionNumber}"></td>
    </tr>
    <tr>
      <td>buildTimestamp</td>
      <td th:text="${buildInformation.buildTimestamp}"></td>
    </tr>
    <tr>
      <td>buildNumber</td>
      <td th:text="${buildInformation.buildNumber}"></td>
    </tr>
    <tr>
      <td>revisionNumber</td>
      <td th:text="${buildInformation.revisionNumber}"></td>
    </tr>
  </table>
</div>
</body>
</html>

Nun lassen sich die Build-Informationen unter der konfigurierten Adresse abrufen, wie im folgenden Screenshot zu sehen ist:

Build Informationen

Build-Informationen

Soweit dieses zweiteilige Tutorial zu Confluence-Cloud-Apps mit Spring Boot und Atlassian Connect. Haben Sie Fragen oder Anmerkungen? Gibt es spezifische Anwendungsfälle oder Herausforderungen im Zusammenhang mit Ihren Atlassian-Systemen, die durch individuelle Add-ons oder Integrationen gelöst werden könnten? Melden Sie sich bei uns: Wir freuen uns darauf, mit Ihnen ins Gespräch zu kommen!

Artikel teilen:Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInEmail this to someonePrint this page