Plugins on OnDemand withRemote AppsDon BrownArchitect, Atlassian
Five years ago. . .
And now. . .• Over 12k active, 9k paid OnDemand accounts• 5 out of 10 add Greenhopper• 1.5 out of 10 add Bonfire• 1 out of...
The Fine Print
But isn‟t it just a copy?
Plugin Problems: Security<% String eid = request.getParameter("eid"); %>...Employee ID: <%= eid %>
Plugin Problems: Performancejava.lang.OutOfMemoryError: Java heap space   at org.apache.xerces.dom.DeferredDocumentImpl.cr...
Plugin Problems: Upgrades
Product DevQA        Everyone‟s Angry                    Admins Plugin Dev
Introducing Remote Apps
This is a Remote App             key: app1                                 name: Remote App - app1                        ...
Examples: General PagePlugin Steps                      Remote App Steps 1. Add web-item config            1. Add general-...
Examples: React to EventPlugin Steps                   Remote App Steps 1. Add component config        1. Add web-hook con...
Examples: Custom Macro EditorPlugin Steps                      Remote App Steps 1. Add web-resource and rest      1. Add c...
Shipping….Now.
Apps: Dropbox by AppFusions• Share your documents• Written in Java, deployed  at Contegix• Provides a custom page  macro, ...
Apps: TFS4JIRA by Spartez• Integrate JIRA with your  Team Foundation Server• Written in Java, deployed  at Heroku• Uses pr...
Apps: Lucidchart by . . .
Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
Establish Trust
Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
Register the app• Receive from OnDemand as Request params: • OAuth consumer key • OAuth RSA public key • Base URL
Register the app• Return to OnDemand description of the remote app • Can be in XML, JSON or YAML
Provide OAuth consumer key andRSA public key<remote-app key=“xxxxxxx"    name="Lucidchart"    version="1"    icon-url="htt...
Request permissions...<permissions>  <permission scope="read_users_and_groups" />  <permission scope="read_content" />  <p...
General Page...<general-page    section="system.content.add/space"    key="lucidAppGeneral"    link-name="Lucidchart Diagr...
General Page...<general-page   section="system.content.add/space"    key="lucidAppGeneral"    link-name="Lucidchart Diagra...
General Page...<general-page    section="system.content.add/space"    key="lucidAppGeneral"    link-name="Lucidchart Diagr...
General Page...<general-page    section="system.content.add/space"    key="lucidAppGeneral"    link-name="Lucidchart Diagr...
Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none">  <description>Create a Lucidchart Diagr...
Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none">  <description>Create a Lucidchart Diagr...
Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none">  <description>Create a Lucidchart Diagr...
Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none">  <description>Create a Lucidchart Diagr...
Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
Any language can be used• Lucidchart is using PHP
Add Diagram (general page)function doclist() {  if (!$this->_hasValidOAuthSignature()) {    $this->set("oauthValid", false...
Add Diagram (general page)function doclist() {    if (!$this->_hasValidOAuthSignature()) {      $this->set("oauthValid", f...
Add Diagram (general page)function doclist() {  if (!$this->_hasValidOAuthSignature()) {    $this->set("oauthValid", false...
Add Diagram (general page)function doclist() {  if (!$this->_hasValidOAuthSignature()) {    $this->set("oauthValid", false...
Make API calls to attach diagramfunction attachDocument() {...    $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; ...
Make API calls to attach diagramfunction attachDocument() {...      $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId...
Make API calls to attach diagramfunction attachDocument() {...    $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; ...
Make API calls to attach diagramfunction attachDocument() {...    $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; ...
Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
Macro• Receive macro params• Return HTML • Will be cached (caching header can be returned) • No CSS, inline styles or Java...
Macro : Receive macro paramsfunction macro() {  $userId = $_REQUEST[user_id];  $name = $_REQUEST[name];  $pageId = $_REQUE...
Macro: Return HTML<div style="float: “ . $align . "; margin: 0 auto; width: " . (intVal($width)+ 2) . "px;">    <img      ...
That‟s it!Straightforward approach to get your    app available for OnDemand
We‟re taking Apps to the next level
What if you could . . .• Tap into our 12k+  OnDemand customer base• Register your app with one  click• Have full control o...
If you want to integrate, call us!• Currently targeted towards  SaaS integrations• Feature set in early stages   Diagram h...
You can finally integrate your site into OnDemandwith Remote Apps     #summit12
Thank you!
Getting started    https://remoteapps.jira.com
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Plugins on OnDemand with Remote Apps - Atlassian Summit 2012
Upcoming SlideShare
Loading in …5
×

Plugins on OnDemand with Remote Apps - Atlassian Summit 2012

2,936 views
2,812 views

Published on

Published in: Technology
1 Comment
1 Like
Statistics
Notes
No Downloads
Views
Total views
2,936
On SlideShare
0
From Embeds
0
Number of Embeds
267
Actions
Shares
0
Downloads
5
Comments
1
Likes
1
Embeds 0
No embeds

No notes for slide

Plugins on OnDemand with Remote Apps - Atlassian Summit 2012

  1. 1. Plugins on OnDemand withRemote AppsDon BrownArchitect, Atlassian
  2. 2. Five years ago. . .
  3. 3. And now. . .• Over 12k active, 9k paid OnDemand accounts• 5 out of 10 add Greenhopper• 1.5 out of 10 add Bonfire• 1 out of 10 add Team Calendars . . . Instances
  4. 4. The Fine Print
  5. 5. But isn‟t it just a copy?
  6. 6. Plugin Problems: Security<% String eid = request.getParameter("eid"); %>...Employee ID: <%= eid %>
  7. 7. Plugin Problems: Performancejava.lang.OutOfMemoryError: Java heap space at org.apache.xerces.dom.DeferredDocumentImpl.createChunk(Unknown Source) at org.apache.xerces.dom.DeferredDocumentImpl.ensureCapacity(Unknown Source) at org.apache.xerces.dom.DeferredDocumentImpl.createNode(Unknown Source) at org.apache.xerces.dom.DeferredDocumentImpl.createDeferredEntityReference(Unknown Source) at org.apache.xerces.parsers.AbstractDOMParser.startGeneralEntity(Unknown Source) at org.apache.xerces.impl.dtd.XMLDTDValidator.startGeneralEntity(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.startEntity(Unknown Source) at org.apache.xerces.impl.XMLDocumentScannerImpl.startEntity(Unknown Source) at org.apache.xerces.impl.XMLEntityManager.startEntity(Unknown Source) at org.apache.xerces.impl.XMLEntityManager.startEntity(Unknown Source
  8. 8. Plugin Problems: Upgrades
  9. 9. Product DevQA Everyone‟s Angry Admins Plugin Dev
  10. 10. Introducing Remote Apps
  11. 11. This is a Remote App key: app1 name: Remote App - app1 version: 1• A single descriptor file display-url: http://example.com description: This app vendor:• Can be in XML, YAML, or JSON name: Atlassian url: http://atlassian.com• Contains permissions: permission: • App metadata - scope: browse_projects • Permissions general-page: - key: first • Extension points name: First url: /first
  12. 12. Examples: General PagePlugin Steps Remote App Steps 1. Add web-item config 1. Add general-page config 2. Add servlet config 2. Implement URL 3. Code servlet 4. Try to get output decorated
  13. 13. Examples: React to EventPlugin Steps Remote App Steps 1. Add component config 1. Add web-hook config 2. Dig through code to find 2. Implement URL event to listen for 3. Register for events 4. Handle event 5. Make sure to unregister
  14. 14. Examples: Custom Macro EditorPlugin Steps Remote App Steps 1. Add web-resource and rest 1. Add custom-macro-editor config config 2. Find and call JavaScript 2. Implement URL API to override edit button 3. Create AUI dialog 4. Implement REST resources
  15. 15. Shipping….Now.
  16. 16. Apps: Dropbox by AppFusions• Share your documents• Written in Java, deployed at Contegix• Provides a custom page macro, and macro editor with MS Office edit
  17. 17. Apps: TFS4JIRA by Spartez• Integrate JIRA with your Team Foundation Server• Written in Java, deployed at Heroku• Uses project and issue tabs, and an admin page
  18. 18. Apps: Lucidchart by . . .
  19. 19. Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
  20. 20. Establish Trust
  21. 21. Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
  22. 22. Register the app• Receive from OnDemand as Request params: • OAuth consumer key • OAuth RSA public key • Base URL
  23. 23. Register the app• Return to OnDemand description of the remote app • Can be in XML, JSON or YAML
  24. 24. Provide OAuth consumer key andRSA public key<remote-app key=“xxxxxxx" name="Lucidchart" version="1" icon-url="http://www.lucidchart.com/favicon.ico" display-url="https://www.lucidchart.com/ondemand"> <vendor name="Lucidchart" url="http://www.lucidchart.com" /> <description>Lucidchart example</description> <oauth …> <public-key>yyyyyy</public-key> </oauth>...
  25. 25. Request permissions...<permissions> <permission scope="read_users_and_groups" /> <permission scope="read_content" /> <permission scope="modify_attachments" /> <permission scope="modify_content" /></permissions>...
  26. 26. General Page...<general-page section="system.content.add/space" key="lucidAppGeneral" link-name="Lucidchart Diagram" name="Select or create a diagram" url="/doclist" width="1200" height="800" icon-url="/icon"> <description>Insert or Create a Lucidchart Diagram</description> <context-param name="page_id" /></general-page>...
  27. 27. General Page...<general-page section="system.content.add/space" key="lucidAppGeneral" link-name="Lucidchart Diagram" name="Select or create a diagram" url="/doclist" width="1200" height="800" icon-url="/icon"> <description>Insert or Create a Lucidchart Diagram</description> <context-param name="page_id" /></general-page>...
  28. 28. General Page...<general-page section="system.content.add/space" key="lucidAppGeneral" link-name="Lucidchart Diagram" name="Select or create a diagram" url="/doclist" width="1200" height="800" icon-url="/icon"> <description>Insert or Create a Lucidchart Diagram</description> <context-param name="page_id" /></general-page>...
  29. 29. General Page...<general-page section="system.content.add/space" key="lucidAppGeneral" link-name="Lucidchart Diagram" name="Select or create a diagram" url="/doclist" width="1200" height="800" icon-url="/icon"> <description>Insert or Create a Lucidchart Diagram</description> <context-param name="page_id" /></general-page>...
  30. 30. Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none"> <description>Create a Lucidchart Diagram</description> <category name="development" /> <image-placeholder url="/imagePlaceHolder" width="140" height="140" apply-chrome="true"/> <parameters> <parameter name="width" title="Width" type="string" default=“700"/> <parameter name="height" title="Height (if blank, image ratio ispreserved)" type="string" /> <parameter name="align" type="enum" default="Left"> <value name="Left"/> <value name="Right" /> </parameter> </parameters></macro>
  31. 31. Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none"> <description>Create a Lucidchart Diagram</description> <category name="development" /> <image-placeholder url="/imagePlaceHolder" width="140" height="140" apply-chrome="true"/> <parameters> <parameter name="width" title="Width" type="string" default=“700"/> <parameter name="height" title="Height (if blank, image ratio ispreserved)" type="string" /> <parameter name="align" type="enum" default="Left"> <value name="Left"/> <value name="Right" /> </parameter> </parameters></macro>
  32. 32. Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none"> <description>Create a Lucidchart Diagram</description> <category name="development" /> <image-placeholder url="/imagePlaceHolder" width="140" height="140"apply-chrome="true"/> <parameters> <parameter name="width" title="Width" type="string" default=“700"/> <parameter name="height" title="Height (if blank, image ratio ispreserved)" type="string" /> <parameter name="align" type="enum" default="Left"> <value name="Left"/> <value name="Right" /> </parameter> </parameters></macro>
  33. 33. Macro...<macro key="lucidchart" url="/macro" output-type="block" body-type="none"> <description>Create a Lucidchart Diagram</description> <category name="development" /> <image-placeholder url="/imagePlaceHolder" width="140" height="140"/> <parameters> <parameter name="width" title="Width" type="string"default=“700"/> <parameter name="height" title="Height" type="string" /> <parameter name="align" type="enum" default="Left"> <value name="Left"/> <value name="Right" /> </parameter> </parameters></macro>
  34. 34. Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
  35. 35. Any language can be used• Lucidchart is using PHP
  36. 36. Add Diagram (general page)function doclist() { if (!$this->_hasValidOAuthSignature()) { $this->set("oauthValid", false); return; } $userId = @$_REQUEST[user_id]; $pageId = @$_REQUEST[page_id]; $redirectURL = "https://" . $_SERVER[SERVER_NAME] ./ondemand/attachDocument?page_id= . $pageId . "&user_id=" . $userId; $this->layout = „ondemand; $this->set("baseUrl", $this->_getBaseURL()); $this->set("callback", urlencode($redirectURL));}
  37. 37. Add Diagram (general page)function doclist() { if (!$this->_hasValidOAuthSignature()) { $this->set("oauthValid", false); return; } $userId = @$_REQUEST[user_id]; $pageId = @$_REQUEST[page_id]; $redirectURL = "https://" . $_SERVER[SERVER_NAME] ./ondemand/attachDocument?page_id= . $pageId . "&user_id=" . $userId; $this->layout = „ondemand; $this->set("baseUrl", $this->_getBaseURL()); $this->set("callback", urlencode($redirectURL));}
  38. 38. Add Diagram (general page)function doclist() { if (!$this->_hasValidOAuthSignature()) { $this->set("oauthValid", false); return; } $userId = @$_REQUEST[user_id]; $pageId = @$_REQUEST[page_id]; $redirectURL = "https://" . $_SERVER[SERVER_NAME] ./ondemand/attachDocument?page_id= . $pageId . "&user_id=" . $userId; $this->layout = „ondemand; $this->set("baseUrl", $this->_getBaseURL()); $this->set("callback", urlencode($redirectURL));}
  39. 39. Add Diagram (general page)function doclist() { if (!$this->_hasValidOAuthSignature()) { $this->set("oauthValid", false); return; } $userId = @$_REQUEST[user_id]; $pageId = @$_REQUEST[page_id]; $redirectURL = "https://" . $_SERVER[SERVER_NAME] ./ondemand/attachDocument?page_id= . $pageId . "&user_id=" . $userId; $this->layout = „ondemand; $this->set("baseUrl", $this->_getBaseURL()); $this->set("callback", urlencode($redirectURL));}
  40. 40. Make API calls to attach diagramfunction attachDocument() {... $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; $auth_header = $this->_getAuthHeader($fullUrl); xmlrpc_set_type($imageBytes, "base64"); $attachmentMetaData = array("fileName"=>$attachmentName, "contentType"=>"image/png", "comment"=>"Imported from Lucidchart (do not deleted)"); $addAttachmentBody= xmlrpc_encode_request( "confluence2.addAttachment", array("", $pageId, $attachmentMetaData ,$imageBytes)); $this->_sendXMLRPCRequest($fullUrl, array( "Content-Type: text/xml", $auth_header), $addAttachmentBody);...}
  41. 41. Make API calls to attach diagramfunction attachDocument() {... $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; $auth_header = $this->_getAuthHeader($fullUrl); xmlrpc_set_type($imageBytes, "base64"); $attachmentMetaData = array("fileName"=>$attachmentName, "contentType"=>"image/png", "comment"=>"Imported from Lucidchart (do not deleted)"); $addAttachmentBody= xmlrpc_encode_request( "confluence2.addAttachment", array("", $pageId, $attachmentMetaData ,$imageBytes)); $this->_sendXMLRPCRequest($fullUrl, array( "Content-Type: text/xml", $auth_header), $addAttachmentBody);...}
  42. 42. Make API calls to attach diagramfunction attachDocument() {... $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; $auth_header = $this->_getAuthHeader($fullUrl); xmlrpc_set_type($imageBytes, "base64"); $attachmentMetaData = array("fileName"=>$attachmentName, "contentType"=>"image/png", "comment"=>"Imported from Lucidchart (do not deleted)"); $addAttachmentBody= xmlrpc_encode_request( "confluence2.addAttachment", array("", $pageId, $attachmentMetaData ,$imageBytes)); $this->_sendXMLRPCRequest($fullUrl, array( "Content-Type: text/xml", $auth_header), $addAttachmentBody);...}
  43. 43. Make API calls to attach diagramfunction attachDocument() {... $fullUrl = $baseURL . "/rpc/xmlrpc?user_id=" . $userId; $auth_header = $this->_getAuthHeader($fullUrl); xmlrpc_set_type($imageBytes, "base64"); $attachmentMetaData = array("fileName"=>$attachmentName, "contentType"=>"image/png", "comment"=>"Imported from Lucidchart (do not deleted)"); $addAttachmentBody= xmlrpc_encode_request( "confluence2.addAttachment", array("", $pageId, $attachmentMetaData ,$imageBytes)); $this->_sendXMLRPCRequest($fullUrl, array( "Content-Type: text/xml", $auth_header), $addAttachmentBody);...}
  44. 44. Steps to create Lucidchart app• Establish Trust• Register App• Implement General Page• Implement macro
  45. 45. Macro• Receive macro params• Return HTML • Will be cached (caching header can be returned) • No CSS, inline styles or JavaScript
  46. 46. Macro : Receive macro paramsfunction macro() { $userId = $_REQUEST[user_id]; $name = $_REQUEST[name]; $pageId = $_REQUEST[pageId]; $docId = $_REQUEST[id]; $width= $_REQUEST[width]; $height = $_REQUEST[height]; $align = $_REQUEST[align]; $outputType = $_REQUEST[ctx_output_type];...
  47. 47. Macro: Return HTML<div style="float: “ . $align . "; margin: 0 auto; width: " . (intVal($width)+ 2) . "px;"> <img src=“$pageAttachment[url]” width=“$width” height=“$height”/> <div style="text-align: center"> <a href=sign://"$host/editDocument/$docId?attachment= $name>EditDiagram</a> | <a href=$baseUrl/plugins/servlet/remoteapps/lucidchart-app/lucidAppRemove?page_id=$pageId&doc_id=$docId&attachment=$name>RemoveDiagram</a> </div></div>
  48. 48. That‟s it!Straightforward approach to get your app available for OnDemand
  49. 49. We‟re taking Apps to the next level
  50. 50. What if you could . . .• Tap into our 12k+ OnDemand customer base• Register your app with one click• Have full control over your app
  51. 51. If you want to integrate, call us!• Currently targeted towards SaaS integrations• Feature set in early stages Diagram here• Working on solution for “extensions”
  52. 52. You can finally integrate your site into OnDemandwith Remote Apps #summit12
  53. 53. Thank you!
  54. 54. Getting started https://remoteapps.jira.com

×