Understanding the Atlassian Platform
Tim Pettersen, Atlassian
Atlassian
Plugin
Development
Platform
Targeted at You!
Features
Dedicated Team
Documentation
Focus on Backwards
Compatibil...
Overview...
Atlassian
Plugin
DEMO
src - http://bit.ly/hovers-svn
Have you ever?
... needed to communicate with a remote
application?
... wanted an easy way to provide JSON data for
an AJA...
REST
Atlassian
Plugin
Depending on REST ...
<dependency>
<groupId>com.atlassian.plugins.rest</groupId>
<artifactId>atlassian-rest-common</artifa...
Quick departure - versioning
Easy - Dependency Management POM
Custom - Specify versions per module
more info: http://bit.l...
Depending on REST ...
<atlassian-plugin>
<rest
key="some-key"
path="/some-path"
version="1.0"
description="Initialise REST...
Using REST ... creating a resource
@Path("/hello/")
@Consumes(APPLICATION_XML, APPLICATION_JSON)
@Produces(APPLICATION_XML...
Using REST ... creating an entity
@XmlAccessorType(FIELD)
@XmlRootElement(name = "message")
public class MessageEntity {
p...
Using REST ... generating a resource URL
public class MyClient {
public void doGet() {
String baseUrl = "http://jira.atlas...
Using REST ... unmarshalling an entity
Request request = requestFactory
.createRequest(MethodType.GET, restUrl);
request.e...
Using REST ... marshalling an entity
Request request = requestFactory.createRequest(PUT, restUrl);
MessageEntity entity = ...
Have you ever?
... wanted to launch a modal dialog from your
plugin?
... wanted to add rich tooltips to your content?
... ...
User Interface
Atlassian
Plugin
Depending on AUI ...
public class MyServlet extends HttpServlet {
public void doGet() {
webResourceManager
.requireResourc...
Depending on AUI ...
<atlassian-plugin>
<web-resource key="some-web-resource">
<resource name="my-script.js" ... />
<resou...
Using AUI ... dropdowns
Using AUI ... dropdowns
<script type="text/javascript">
// create drop-down
AJS.$("#my-dropdown")
.dropDown("standard", {a...
Using AUI ... tooltips
Using AUI ... tooltips
<script type="text/javascript">
// assign URL for retrieving AJAX content
var contentUrl = AJS.para...
Using AUI ... more!
Have you ever?
... wanted to include a piece of javascript or CSS
on every page in Confluence?
... wanted to make your plu...
Plugins Framework
Atlassian
Depending on plugins ...
<dependency>
<groupId>com.atlassian.plugins</groupId>
<artifactId>atlassian-plugins-webresource</...
Using plugins ... web-resource contexts
<atlassian-plugin>
<web-resource key="some-web-resource">
<context>atl.general</co...
Custom Plugin Modules
Using plugins ... custom module types
public class MyDescriptor extends AbstractModuleDescriptor<MyModule> {
public void i...
Using plugins ... custom module types
public class MyService {
private PluginAccessor pluginAccessor;
public MyService(Plu...
Using plugins ... descriptor application scopes
<atlassian-plugin>
<web-resource key="some-web-resource" application="conf...
Have you ever?
... needed to render HTML outside of a JIRA or
Confluence action?
... needed to pass back rendered HTML to ...
Template Renderer
Atlassian
Depending on ATR ...
<dependency>
<groupId>com.atlassian.templaterenderer</groupId>
<artifactId>atlassian-template-rendere...
Using ATR ...
public class MyServlet extends HttpServlet {
private TemplateRenderer templateRenderer; // constructor-injec...
Have you ever?
... needed to persist some simple data for your
plugin?
... wanted to i18n your plugin?
... needed to write...
Shared Application Layer
Atlassian
Plugin
Depending on SAL ...
<dependency>
<groupId>com.atlassian.sal</groupId>
<artifactId>sal-api</artifactId>
<version>${sal.ver...
Depending on SAL ...
<atlassian-plugin>
<component-import
key="[someSalComponent]"
interface="com.atlassian.sal.api.[someS...
Using SAL ... upgrade tasks
public interface PluginUpgradeTask {
int getNumber();
String getShortDescription();
Collection...
Using SAL ... i18n
<atlassian-plugin>
<component-import
key="i18nResolver"
interface="com.atlassian.sal.api.message.I18nRe...
Using SAL ... i18n
Map<String, Object> context = new HashMap<String, Object>();
context.put("i18n", i18nResolver);
templat...
Using SAL ... job scheduling
// simple very-contrived job
public class MyPluginJob implements PluginJob {
public void exec...
Using SAL ... job scheduling
public class MyComponent implements LifecycleAware {
private PluginScheduler scheduler; // au...
Targeted at You!
Features
Dedicated Team
Documentation
Backwards Compatibility
Open Source :D
Go use it!
Shared Application Layer
Unified Application Links
Template Renderer
Plugins Framework
Atlassian User Interface...
Questions?
more info - http://bit.ly/best-thing-ever
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen
Upcoming SlideShare
Loading in...5
×

AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen

3,259

Published on

Published in: Technology, Art & Photos
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,259
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
35
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

AtlasCamp 2010: Understanding the Atlassian Platform - Tim Pettersen

  1. 1. Understanding the Atlassian Platform Tim Pettersen, Atlassian
  2. 2. Atlassian Plugin Development Platform Targeted at You! Features Dedicated Team Documentation Focus on Backwards Compatibility
  3. 3. Overview...
  4. 4. Atlassian Plugin DEMO src - http://bit.ly/hovers-svn
  5. 5. Have you ever? ... needed to communicate with a remote application? ... wanted an easy way to provide JSON data for an AJAXy UI? ... wanted to expose your plugin's data via web services?
  6. 6. REST Atlassian Plugin
  7. 7. Depending on REST ... <dependency> <groupId>com.atlassian.plugins.rest</groupId> <artifactId>atlassian-rest-common</artifactId> <version>${rest.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.atlassian.plugins.rest</groupId> <artifactId>atlassian-rest-module</artifactId> <version>${rest.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> Atlassian annotations & utilities JAX-RS annotations & jersey JAXB annotations
  8. 8. Quick departure - versioning Easy - Dependency Management POM Custom - Specify versions per module more info: http://bit.ly/platform-versions
  9. 9. Depending on REST ... <atlassian-plugin> <rest key="some-key" path="/some-path" version="1.0" description="Initialise REST resources for my plugin" /> <component-import key="restUrlBuilder" interface="com.atlassian.plugins.rest.common.util.RestUrlBuilder" /> </atlassian-plugin> http://jira.atlassian.com/REST/some-path/1.0/
  10. 10. Using REST ... creating a resource @Path("/hello/") @Consumes(APPLICATION_XML, APPLICATION_JSON) @Produces(APPLICATION_XML, APPLICATION_JSON) public class MyResource { @Path("/my-name-is/{name}") @GET @AnonymousAllowed public Response hello(@PathParam("name") String name) { return ok( new MessageEntity("Hello, " + name + "!") ); } } http://.../REST/some-path/1.0/hello http://.../REST/some-path/1.0/hello/my-name-is/tim
  11. 11. Using REST ... creating an entity @XmlAccessorType(FIELD) @XmlRootElement(name = "message") public class MessageEntity { private String body; public MessageEntity(String body) { this.body = body; } } http://.../REST/some-path/1.0/hello/my-name-is/Tim.xml <message> <body>Hello, Tim!</body> </message> http://.../REST/some-path/1.0/hello/my-name-is/Tim.json {body:"Hello, world!"} Poster: http://bit.ly/poster-ff
  12. 12. Using REST ... generating a resource URL public class MyClient { public void doGet() { String baseUrl = "http://jira.atlassian.com"; String restUrl = restUrlBuilder .getUrlFor(baseUrl, MyResource.class) .hello("Tim") .toString(); ... } } // generated restUrl = "http://.../REST/some-path/1.0/hello/my-name-is/Tim"
  13. 13. Using REST ... unmarshalling an entity Request request = requestFactory .createRequest(MethodType.GET, restUrl); request.execute(new ResponseHandler<Response>() { public void handle(Response response) { if (response.isSuccessful()) { } } }); // unmarshall the entity MessageEntity m = response.getEntity(MessageEntity.class);
  14. 14. Using REST ... marshalling an entity Request request = requestFactory.createRequest(PUT, restUrl); MessageEntity entity = new MessageEntity("some-value"); request.setEntity(entity); request.execute(); @PUT public Response submit(MessageEntity message) { System.out.println("Received: " + message.getBody()); } Client Server
  15. 15. Have you ever? ... wanted to launch a modal dialog from your plugin? ... wanted to add rich tooltips to your content? ... wished someone else would write your CSS and javascript for you? ... wanted your plugin to look and behave a little bit more like the host application?
  16. 16. User Interface Atlassian Plugin
  17. 17. Depending on AUI ... public class MyServlet extends HttpServlet { public void doGet() { webResourceManager .requireResource("com.atlassian.auiplugin:ajs"); } } <html> <head> #webResourceManager.getRequiredResources() </head> <body ... /> </html>
  18. 18. Depending on AUI ... <atlassian-plugin> <web-resource key="some-web-resource"> <resource name="my-script.js" ... /> <resource name="my-styles.css" ... /> <dependency>com.atlassian.auiplugin:ajs</dependency> </web-resource> </atlassian-plugin> public class MyServlet extends HttpServlet { public void doGet() { webResourceManager .requireResource("com.my.plugin:some-web-resource"); } }
  19. 19. Using AUI ... dropdowns
  20. 20. Using AUI ... dropdowns <script type="text/javascript"> // create drop-down AJS.$("#my-dropdown") .dropDown("standard", {alignment: "right"}); </script> <!-- the list to display as a dropdown --> <ul id="my-dropdown"> <li class="paper-clip">Item One</li> <li class="clock">Item Two</li> <li class="envelope">Item Three</li> </ul>
  21. 21. Using AUI ... tooltips
  22. 22. Using AUI ... tooltips <script type="text/javascript"> // assign URL for retrieving AJAX content var contentUrl = AJS.params.baseUrl + "/rest/myplugin/1.0/tooltip"; // bind hovers to DOM elements AJS.InlineDialog(".tooltip-link", "tooltip", contentUrl, { onHover: true, width: 300, cacheContent: true }); </script> <!-- an anchor that the tooltip will be applied to --> <a class='.hover-link'>Hover over me!</a>
  23. 23. Using AUI ... more!
  24. 24. Have you ever? ... wanted to include a piece of javascript or CSS on every page in Confluence? ... wanted to make your plugin, pluggable? ... wanted to build a single plugin that can be deployed in multiple applications?
  25. 25. Plugins Framework Atlassian
  26. 26. Depending on plugins ... <dependency> <groupId>com.atlassian.plugins</groupId> <artifactId>atlassian-plugins-webresource</artifactId> <version>${atlassian.plugins.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.atlassian.plugins</groupId> <artifactId>atlassian-plugins-core</artifactId> <version>${atlassian.plugins.version}</version> <scope>provided</scope> </dependency> <atlassian-plugin> <!-- Unnecessary! --> <component-import ... /> </atlassian-plugin>
  27. 27. Using plugins ... web-resource contexts <atlassian-plugin> <web-resource key="some-web-resource"> <context>atl.general</context> <resource name="my-script.js" ... /> <resource name="my-styles.css" ... /> </web-resource> </atlassian-plugin> atl.general atl.admin atl.userprofile
  28. 28. Custom Plugin Modules
  29. 29. Using plugins ... custom module types public class MyDescriptor extends AbstractModuleDescriptor<MyModule> { public void init(Plugin plugin, Element element); public MyModule getModule() { // initialize the module specified by the descriptor's class attribute return moduleFactory.createModule(moduleClassName, this); } } <atlassian-plugin> <module-type key="my-descriptor" class="com.myplugin.MyDescriptor" /> <my-descriptor class="com.myplugin.ModuleOne" /> <my-descriptor class="com.myplugin.ModuleTwo" /> </atlassian-plugin>
  30. 30. Using plugins ... custom module types public class MyService { private PluginAccessor pluginAccessor; public MyService(PluginAccessor pluginAccessor) { this.pluginAccessor = pluginAccessor; } public void executeInstalledModules() { for (MyModule module : pluginAccessor.getEnabledModulesByClass(MyModule.class)) { module.execute(); } } }
  31. 31. Using plugins ... descriptor application scopes <atlassian-plugin> <web-resource key="some-web-resource" application="confluence"> <context>atl.general</context> <resource name="page-integration.js" ... /> </web-resource> <web-resource key="some-web-resource" application="jira"> <context>atl.general</context> <resource name="issue-integration.js" ... /> </web-resource> <!-- depends on Confluence's API --> <component key="some-component" application="confluence" class="com.myplugin.PageHandler" /> <!-- depends on JIRA's API --> <component key="some-component" application="jira" class="com.myplugin.IssueHandler" /> </atlassian-plugin>
  32. 32. Have you ever? ... needed to render HTML outside of a JIRA or Confluence action? ... needed to pass back rendered HTML to use in an AJAX UI? ... wished you could use something a little more modern than Velocity 1.4 in JIRA?
  33. 33. Template Renderer Atlassian
  34. 34. Depending on ATR ... <dependency> <groupId>com.atlassian.templaterenderer</groupId> <artifactId>atlassian-template-renderer-api</artifactId> <version>${template.renderer.version}</version> <scope>provided</scope> </dependency> <atlassian-plugin> <component-import key="templateRenderer" interface="com.atlassian.templaterenderer.TemplateRenderer" /> </atlassian-plugin>
  35. 35. Using ATR ... public class MyServlet extends HttpServlet { private TemplateRenderer templateRenderer; // constructor-injected public void doGet(HttpServletRequest req, HttpServletResponse resp) { Map<String, Object> context = createContext(); templateRenderer.render("templates/view.vm", context, resp.getWriter() ); } }
  36. 36. Have you ever? ... needed to persist some simple data for your plugin? ... wanted to i18n your plugin? ... needed to write an upgrade task? ... wanted to schedule a recurring job?
  37. 37. Shared Application Layer Atlassian Plugin
  38. 38. Depending on SAL ... <dependency> <groupId>com.atlassian.sal</groupId> <artifactId>sal-api</artifactId> <version>${sal.version}</version> <scope>provided</scope> </dependency>
  39. 39. Depending on SAL ... <atlassian-plugin> <component-import key="[someSalComponent]" interface="com.atlassian.sal.api.[someSalComponent]" /> </atlassian-plugin> AuthenticationControlle r LoginUriProvider ComponentLocator I18nResolver LocaleResolver RequestFactory SearchProvider PluginUpgradeManage r UserManager ApplicationProperties PluginSettingsFactory ProjectManager PluginScheduler More!
  40. 40. Using SAL ... upgrade tasks public interface PluginUpgradeTask { int getNumber(); String getShortDescription(); Collection<Message> doUpgrade(); String getPluginKey(); } <atlassian-plugin> <component key="my-upgrade-task" public="true" class="com.myplugin.MyUpgradeTask"> <interface>com.atlassian.sal.api.upgrade.PluginUpgradeTask</interface> </component> </atlassian-plugin>
  41. 41. Using SAL ... i18n <atlassian-plugin> <component-import key="i18nResolver" interface="com.atlassian.sal.api.message.I18nResolver" /> <resource key="my-i18n" type="i18n" location="i18n" /> </atlassian-plugin> hello.world = Hello World! (i18n.properties) hello.world: Hola a todos! (i18n_es.properties) hello.world Hallo Welt! (i18n_de.properties)
  42. 42. Using SAL ... i18n Map<String, Object> context = new HashMap<String, Object>(); context.put("i18n", i18nResolver); templateRenderer.render("templates/view.vm", context, writer); <html> <head> <title>#i18n.getText('hello.world')</title> </head> <body ... /> </html>
  43. 43. Using SAL ... job scheduling // simple very-contrived job public class MyPluginJob implements PluginJob { public void execute(Map<String, Object> data) { int count = data.get("jobExecutionCount"); count++; data.put("jobExecutionCount", count); } }
  44. 44. Using SAL ... job scheduling public class MyComponent implements LifecycleAware { private PluginScheduler scheduler; // autowired public void onStart() { scheduler.scheduleJob( "my-plugin-job", MyPluginJob.class, new HashMap<String, Object>(), new Date(), 10000 // milliseconds ); } }
  45. 45. Targeted at You! Features Dedicated Team Documentation Backwards Compatibility Open Source :D
  46. 46. Go use it! Shared Application Layer Unified Application Links Template Renderer Plugins Framework Atlassian User Interface REST
  47. 47. Questions? more info - http://bit.ly/best-thing-ever
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×