The internet of things: connecting technologies to connect with customers
Connecting Connect with Spring Boot
-
Upload
vincent-kok -
Category
Technology
-
view
374 -
download
0
Transcript of Connecting Connect with Spring Boot
S TA R T E R S
S P R I N G B O O T
C O N N E C T S TA R T E R
I N C E P T I O N
Agenda
S P R I N G B O O T
http://geek-and-poke.com/geekandpoke/2014/1/2/games-for-the-real-geeks-part-2
A “vanilla” Spring web app
1. Dependencies Setup the right Maven dependencies
web.xml Setup your web.xml
A “vanilla” Spring web app
1. Dependencies Setup the right Maven dependencies
application-context.xml Enable component scanning and mvc annotation driven
web.xml Setup your web.xml
A “vanilla” Spring web app
1. Dependencies Setup the right Maven dependencies
4. The actual controller What you actually care about
application-context.xml Enable component scanning and mvc annotation driven
web.xml Setup your web.xml
A “vanilla” Spring web app
5. Install Tomcat And configure it as well
1. Dependencies Setup the right Maven dependencies
4. The actual controller What you actually care about
application-context.xml Enable component scanning and mvc annotation driven
web.xml Setup your web.xml
A “vanilla” Spring web app
5. Install Tomcat And configure it as well
6. It might work You probably made a typo
1. Dependencies Setup the right Maven dependencies
4. The actual controller What you actually care about
application-context.xml Enable component scanning and mvc annotation driven
web.xml Setup your web.xml
• Big cool statistic
• 2,569
• Add-Ons in Marketplace
Repeatable pattern
https://flic.kr/p/8ykpkW
Example: Hello world
e
<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>
<groupId>com.atlassian.connect.lighthing</groupId> <artifactId>lightingdemo</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>
Example: Hello world
e
<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>
<groupId>com.atlassian.connect.lighthing</groupId> <artifactId>lightingdemo</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent>
Example: Hello world
e
<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>
<groupId>com.atlassian.connect.lighthing</groupId> <artifactId>lightingdemo</artifactId> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Example: Hello world
e
package hello;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;
@SpringBootApplicationpublic class HelloApplication {
public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); }}
Example: Hello world
e
package hello;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;
@SpringBootApplicationpublic class HelloApplication {
public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); }}
@SpringBootApplicationpublic class HelloApplication {
Example: Hello world
e
package hello;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;
@SpringBootApplicationpublic class HelloApplication {
public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); }}
public static void main(String[] args) {SpringApplication.run(HelloApplication.class, args);
}
Example: Hello world
e
package hello;
import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;
@RestControllerpublic class HelloController {
@RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; }}
Example: Hello world
e
package hello;
import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;
@RestControllerpublic class HelloController {
@RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; }}
@RestControllerpublic class HelloController {
Example: Hello world
e
package hello;
import org.springframework.web.bind.annotation.RestController;import org.springframework.web.bind.annotation.RequestMapping;
@RestControllerpublic class HelloController {
@RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; }}
@RequestMapping("/") public String index() { return "Greetings from Spring Boot!"; }
Example: Hello world
e
$> mvn spring-boot:run
$> curl http://localhost:8080/
Greetings from Spring Boot!
Provides production ready features Think health checks, metrics, security and externalised configuration
S TA R T E R S
S P R I N G B O O T
C O N N E C T S TA R T E R
I N C E P T I O N
Agenda
S TA R T E R S
Example: Consume a starter
e
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependencies>
Example: Consume a starter
e
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Example: Consume a starter
e
$> mvn spring-boot:run
$> curl http://localhost:8080/health
{”status”:”UP”}
S TA R T E R S
S P R I N G B O O T
C O N N E C T S TA R T E R
I N C E P T I O N
Agenda
C O N N E C T S TA R T E R
1: /atlassian-connect.json
2: Descriptor JSON
3: /install
5: Install OK / not OK
4. Store tenant data
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
"name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" },
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
"lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
"modules": {}
Lifecycle
e
{ "key": “com.atlassian.connect.atlascamp.inception”, "clientKey": "Confluence:5358671948", "publicKey": "MIGf....ZRWzwIDAQAB", "sharedSecret": "fda9e230-ba1b-4e8d-a76e-c9e4e6c28ea8", "serverVersion": "6437", "pluginsVersion": "1.1.81", "baseUrl": “http://vincentkok.atlassian.net", "productType": "confluence", "description": "Atlassian Confluene at https://example.atlassian.net", "eventType": "INSTALLED"}
Lifecycle
e
{ "key": “com.atlassian.connect.atlascamp.inception”, "clientKey": "Confluence:5358671948", "publicKey": "MIGf....ZRWzwIDAQAB", "sharedSecret": "fda9e230-ba1b-4e8d-a76e-c9e4e6c28ea8", "serverVersion": "6437", "pluginsVersion": "1.1.81", "baseUrl": “http://vincentkok.atlassian.net", "productType": "confluence", "description": "Atlassian Confluene at https://example.atlassian.net", "eventType": "INSTALLED"}
"key": “com.atlassian.connect.atlascamp.inception”, "clientKey": "Confluence:5358671948",
Lifecycle
e
{ "key": “com.atlassian.connect.atlascamp.inception”, "clientKey": "Confluence:5358671948", "publicKey": "MIGf....ZRWzwIDAQAB", "sharedSecret": "fda9e230-ba1b-4e8d-a76e-c9e4e6c28ea8", "serverVersion": "6437", "pluginsVersion": "1.1.81", "baseUrl": “http://vincentkok.atlassian.net", "productType": "confluence", "description": "Atlassian Confluene at https://example.atlassian.net", "eventType": "INSTALLED"}
"sharedSecret": "fda9e230-ba1b-4e8d-a76e-c9e4e6c28ea8",
Lifecycle
e
{ "key": “com.atlassian.connect.atlascamp.inception”, "clientKey": "Confluence:5358671948", "publicKey": "MIGf....ZRWzwIDAQAB", "sharedSecret": "fda9e230-ba1b-4e8d-a76e-c9e4e6c28ea8", "serverVersion": "6437", "pluginsVersion": "1.1.81", "baseUrl": “http://vincentkok.atlassian.net", "productType": "confluence", "description": "Atlassian Confluene at https://example.atlassian.net", "eventType": "INSTALLED"} “eventType": "INSTALLED",
JWT
e
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEzODY4OTkxMzEsImlzcyI6ImppcmE6MTU0ODk1OTUiLCJxc2giOiI4MDYzZmY0Y2ExZTQxZGY3YmM5MGM4YWI2ZDBmNjIwN2Q0OTFjZjZkYWQ3YzY2ZWE3OTdiNDYxNGI3MTkyMmU5IiwiaWF0IjoxMzg2ODk4OTUxfQ.uKqU9dTB6gKwG6jQCuXYAiMNdfNRw98Hw_IWuA5MaMo
JWT
e
{ "typ":"JWT", "alg":"HS256"}
{ "iss": "confluence:1314039", "iat": 1300819370, "exp": 1300819380, "qsh": "8063ff4ca1e41df7bc90c8ab6d0f6207d491cf6dad7c66ea797b4614b71922e9", "sub": "alana", "context": { "user": { "userKey": "alana", "username": "aaware", "displayName": "Bruce Wayne" } }}
JWT
e
{ "typ":"JWT", "alg":"HS256"}
{ "iss": "confluence:1314039", "iat": 1300819370, "exp": 1300819380, "qsh": "8063ff4ca1e41df7bc90c8ab6d0f6207d491cf6dad7c66ea797b4614b71922e9", "sub": "alana", "context": { "user": { "userKey": "alana", "username": "aaware", "displayName": "Bruce Wayne" } }}
{ "typ":"JWT", "alg":"HS256"}
JWT
e
{ "typ":"JWT", "alg":"HS256"}
{ "iss": "confluence:1314039", "iat": 1300819370, "exp": 1300819380, "qsh": "8063ff4ca1e41df7bc90c8ab6d0f6207d491cf6dad7c66ea797b4614b71922e9", "sub": "alana", "context": { "user": { "userKey": "alana", "username": "aaware", "displayName": "Bruce Wayne" } }}
"iss": "confluence:1314039", "iat": 1300819370, "exp": 1300819380, "qsh": “8063ff4…2e9”, "sub": "alana",
Authenticated requests
e"Authorization" : "JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJl..."
/inception-macro?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJl…
• Big cool statistic
• 2,569
• Add-Ons in Marketplace
DRY
https://flic.kr/p/qkUpu
S TA R T E R S
S P R I N G B O O T
C O N N E C T S TA R T E R
I N U N D E R 3 M I N U T E S
Agenda
I N C E P T I O N
• Big cool statistic
• 2,569
• Add-Ons in Marketplace
Let’s build a Connect add-on from scratch
https://flic.kr/p/rtmnT2
• Big cool statistic
• 2,569
• Add-Ons in Marketplace
A page in a page
https://flic.kr/p/216z4i
1: inception-macro?pageId=5&jwt=eyJhbGciOiJIUz
2:/rest/api/content/5?expand=body.export_view
3: Page content as JSON
1: inception-macro?pageId=5&jwt=eyJhbGciOiJIUz
2:/rest/api/content/5?expand=body.export_view
3: Page content as JSON
4: Rendered macro HTML
Create a project
e
$> mvn archetype:generate -DgroupId=com.atlassian.labs.atlascamp -DartifactId=inception -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Add dependencies
e
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.atlassian.labs.atlascamp</groupId> <artifactId>inception</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies></project>
Add dependencies
e
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.atlassian.labs.atlascamp</groupId> <artifactId>inception</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies></project>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> </parent>
Add dependencies
e
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.atlassian.labs.atlascamp</groupId> <artifactId>inception</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.3.RELEASE</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies></project>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.atlassian.connect</groupId> <artifactId>atlassian—spring-boot-starter</artifactId> <version>1.0.0-beta-1</version> </dependency></dependencies>
Create the application
e
package com.atlassian.connect.atlascamp;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class InceptionApplication { public static void main( String[] args ) { SpringApplication.run(InceptionApplication.class, args); }}
Create the application
e
package com.atlassian.connect.atlascamp;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class InceptionApplication { public static void main( String[] args ) { SpringApplication.run(InceptionApplication.class, args); }}
@SpringBootApplicationpublic class InceptionApplication {
Create the application
e
package com.atlassian.connect.atlascamp;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class InceptionApplication { public static void main( String[] args ) { SpringApplication.run(InceptionApplication.class, args); }}public static void main(String[] args) {SpringApplication.run(InceptionApplication.class, args);
}
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
"name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “https://1c12a2cd.ngrok.io”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" },
Descriptor
e
{ "name": "Inception", "description": “A page in a page", "key": “com.atlassian.connect.atlascamp.inception”, "baseUrl": “http://localhost:8080”, "vendor": { "name": "Atlassian", "url": "http://www.atlassian.com" }, "authentication": { "type": "jwt" }, "lifecycle": { "installed": "/installed", "uninstalled": "/uninstalled", "enabled": "/enabled", "disabled": "/disabled" }, "apiVersion": 1, "scopes": [ "read" ], "modules": { }}
"modules": {}
Descriptor
e
"modules": { "dynamicContentMacros": [ { "url": "/inception-macro?pageId={page.id}", "description": { "value": "A page in a page" }, "name": { "value": "Inception" }, "categories": [ "visuals" ], "outputType": "block", "bodyType": "none", "aliases": [ "inception" ], "featured": true, "parameters": [], "key": "inception-macro" } ] }
Descriptor
e
"modules": { "dynamicContentMacros": [ { "url": "/inception-macro?pageId={page.id}", "description": { "value": "A page in a page" }, "name": { "value": "Inception" }, "categories": [ "visuals" ], "outputType": "block", "bodyType": "none", "aliases": [ "inception" ], "featured": true, "parameters": [], "key": "inception-macro" } ] }
"dynamicContentMacros": [ { "url": "/inception-macro?pageId={page.id}", "description": { "value": "A page in a page" },
Tenant storage
e
spring.jpa.database=POSTGRESQL
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:postgresql://localhost:5432/springbootdb
Macro template
e
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.atlassian.connect</groupId> <artifactId>atlassian-connect-spring-boot-starter</artifactId> <version>0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
Macro template
e
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.atlassian.connect</groupId> <artifactId>atlassian-connect-spring-boot-starter</artifactId> <version>0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Macro template
e
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui.min.css" media="all"/> <script th:src=“${js-all-url}” type="text/javascript"></script></head><body> <section id="content" class="ac-content"> <p th:utext="${body}"/> </section></body></html>
Macro template
e
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui.min.css" media="all"/> <script th:src=“${js-all-url}” type="text/javascript"></script></head><body> <section id="content" class="ac-content"> <p th:utext="${body}"/> </section></body></html>
<script th:src=“${js-all-url}” type="text/javascript"></script>
Macro template
e
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui.min.css" media="all"/> <script th:src=“${js-all-url}” type="text/javascript"></script></head><body> <section id="content" class="ac-content"> <p th:utext="${body}"/> </section></body></html>
<section id="content" class="ac-content"> <p th:utext="${body}"/> </section>
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
@Controllerpublic class InceptionController {
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
private static final String PAGE_URL private static final String JS_URL
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
@Autowired private RestTemplate restTemplate;
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl();
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
Controller
e
package com.atlassian.connect.atlascamp;
@Controllerpublic class InceptionController {
private static final String PAGE_URL = "%s/rest/api/content/%s?expand=body.export_view"; private static final String JS_URL = "%s/atlassian-connect/all.js";
@Autowired private RestTemplate restTemplate;
@RequestMapping(value = "/inception-macro") public String render(@RequestParam long pageId,
@AuthenticationPrincipal AtlassianHostUser hostUser, Model model) { final String baseURL = hostUser.getHost().getBaseUrl(); final String contentUrl = String.format(PAGE_URL, baseURL, pageId); final String pageContent = restTemplate.getForObject(contentUrl, String.class); final String pageBody = extractPageBody(pageContent);
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro"; }
private String extractPageBody(String response) {
model.addAttribute("body", pageBody); model.addAttribute("jsurl", String.format(JS_URL, baseURL));
return "inception-macro";
Install
e
$> npm install -g ngrok
$> ngrok http 8080
Forwarding Forwarding https://1c12a2cd.ngrok.io -> localhost:8080
Executed requests
e
HTTP Requests
-------------
GET /inception-macro 200 OK
POST /installed 204 No Content
GET /atlassian-connect.json 200 OK