Building add-ons using
add-ons
DANIEL WESTER • CO-FOUNDER • WITTIFIED • @DWESTER42A
Building add-ons using
add-ons
DANIEL WESTER • CO-FOUNDER • WITTIFIED • @DWESTER42A
About me
20%
Web Fragment Finder
My button
ACTIVE OBJECTS
p2 addon
ADDING A WEB ITEM
WEB RESOURCES
EVENTS
GETTING STARTED
ACTIVE OBJECTS
GETTING STARTED
p2 addon
ADDING A WEB ITEM
WEB RESOURCES
EVENTS
BASIC DESCRIPTOR
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}"
plugins-version="2">
<plugin-info>
<description>${project.description}</description>
<version>${project.version}</version>
<vendor name="${project.organization.name}" url="${project.organization.url}" />
<param name="plugin-icon">images/pluginIcon.png</param>
<param name="plugin-logo">images/pluginLogo.png</param>
</plugin-info>
<component-import key="applicationProperties"
interface="com.atlassian.sal.api.ApplicationProperties" />
<component-import key="eventPublisher"
interface="com.atlassian.event.api.EventPublisher"/>
<component-import key="ao" name="Active Objects service"
interface="com.atlassian.activeobjects.external.ActiveObjects">
<description>Active Objects functionality from the plugin</description>
</component-import>
<ao key="ao-module">
<description>Active Objects entries</description>
<entity>com.wittified.pres.DashView</entity>
</ao>
<component key="dash-tracker-service"
class="com.wittified.pres.DashTrackerServiceImpl">
<interface>com.wittified.pres.DashTrackerService</interface>
</component>
<rest key="rest-end-points" path="/wittified/dashboards" version="1.0">
<description>REST interface to integrate with things</description>
</rest>
<resource type="i18n" name="i18n" location="dashboard-tracker"/>
<web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp-
dashboard-tracker Web Resources">
<dependency>com.atlassian.auiplugin:ajs</dependency>
<dependency>com.atlassian.auiplugin:dialog2</dependency>
<resource type="download" name="dashboard-tracker.css" location="/css/dashboard-
tracker.css"/>
<resource type="download" name="dashboard-tracker.js" location="/js/dashboard-
tracker.js"/>
<resource type="download" name="images/" location="/images"/>
<transformation extension="soy">
<transformer key="soyTransformer"/>
</transformation>
<resource type="download" name="dashboard-counter.soy.js" location="/soy/
TabularData.soy"/>
<context>atl.general</context>
</web-resource>
</atlassian-plugin>
ACTIVE OBJECTS ENTITY
package com.wittified.pres;

import net.java.ao.Entity;

import net.java.ao.schema.PrimaryKey;

public interface DashView extends Entity

{

public Long getDashboard();

public void setDashboard(Long dashboard);

public Long getViews();

public void setViews( Long count);

}
ACTIVE OBJECTS SERVICE
@Override

@Transactional

public void trackThis(long dashboard)

{

DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARDS = ? ", dashboard) );

DashView dashView = null;

if(dashViews.length==0)

{

dashView = this.activeObjects.create( DashView.class);

dashView.setDashboard( dashboard);

dashView.setViews(0L);

}

else

{

dashView = dashViews[0];

}

dashView.setViews(dashView.getViews() + 1);

dashView.save();

}
REST
@GET

@Produces({MediaType.APPLICATION_JSON})

@Path("/all")

public Response getAll()

{

List<DashBoardEntity> dashBoardEntityList = new ArrayList<DashBoardEntity>();

for(DashView dashView: this.dashTrackerService.getAll())

{

PortalPage page = this.portalPageManager.getPortalPageById( dashView.getDashboard());

DashBoardEntity dashBoardEntity = new DashBoardEntity();

dashBoardEntity.setName( page.getName());

dashBoardEntity.setCount( dashView.getViews());

dashBoardEntity.setId( dashView.getDashboard());

if(page.getOwner()==null)

{

dashBoardEntity.setOwner("None");

}

else {

dashBoardEntity.setOwner(page.getOwner().getDisplayName());

}

dashBoardEntityList.add( dashBoardEntity);

}

return Response.ok( dashBoardEntityList).build();
EVENT LISTENER
public class DashBoardEventListener implements InitializingBean, DisposableBean

{

private final EventPublisher eventPublisher;

private final DashTrackerService dashTrackerService;

public DashBoardEventListener( final EventPublisher eventPublisher,

final DashTrackerService dashTrackerService)

{

this.eventPublisher = eventPublisher;

this.dashTrackerService = dashTrackerService;

}

@Override

public void destroy() throws Exception

{

this.eventPublisher.unregister( this);

}

@Override

public void afterPropertiesSet() throws Exception

{

this.eventPublisher.register( this);

}

}
ACTIVE OBJECTS
EVENTS
p2 addon
ADDING A WEB ITEM
WEB RESOURCES
GETTING STARTED
EVENT LISTENER
@EventListener

public void onDashboardViewEvent( DashboardViewEvent dashboardViewEvent)

{

this.dashTrackerService.trackThis( dashboardViewEvent.getId() );

}
EVENTS
ACTIVE OBJECTS
p2 addon
ADDING A WEB ITEM
WEB RESOURCES
GETTING STARTED
ACTIVE OBJECT SERVICE ERROR
ACTIVE OBJECT SERVICE ERROR
DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARDS
= ? ", dashboard) );
ACTIVE OBJECT SERVICE FIXED
DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARD
= ? ", dashboard) );
ACTIVE OBJECTS
ADDING A WEB ITEM
p2 addon
EVENTS
WEB RESOURCES
GETTING STARTED
TEMPLATEIZED WEB-ITEM
<web-item key="web-item-example" name="My Web Item"
section="gadgets.dashboard.menu" weight=“200">

<description key="my-web-item-desc">General description</description>

<label key="my-web-item-label" />

<link linkId=“my-web-item-link”>/my-web-item</link>

</web-item>
FLUSHED OUT WEB-ITEM
<web-item key="web-item-dashboard-usage" name="DashBoard Usage"
section="gadgets.dashboard.menu" weight="200">

<description key="my-web-item-desc">General description</
description>

<label key="Dashboard usage" />

<link linkId=“dashboard-usagelink">/</link>

</web-item>
ACTIVE OBJECTS
WEB RESOURCES
p2 addon
EVENTS
ADDING A WEB ITEM
GETTING STARTED
WEB RESOURCE ENTY: GENERAL
<web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp-dashboard-tracker Web
Resources">

<dependency>com.atlassian.auiplugin:ajs</dependency>

<dependency>com.atlassian.auiplugin:dialog2</dependency>



<resource type="download" name="dashboard-tracker.css" location="/css/dashboard-tracker.css"/>

<resource type="download" name="dashboard-tracker.js" location="/js/dashboard-tracker.js"/>

<resource type="download" name="images/" location="/images"/>

<transformation extension="soy">

<transformer key="soyTransformer"/>

</transformation>

<resource type="download" name="dashboard-counter.soy.js" location="/soy/TabularData.soy"/>

<context>atl.general</context>

</web-resource>
WEB RESOURCE ENTY: SPECIFIC
<web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp-dashboard-tracker Web
Resources">

<dependency>com.atlassian.auiplugin:ajs</dependency>

<dependency>com.atlassian.auiplugin:dialog2</dependency>



<resource type="download" name="dashboard-tracker.css" location="/css/dashboard-tracker.css"/>

<resource type="download" name="dashboard-tracker.js" location="/js/dashboard-tracker.js"/>

<resource type="download" name="images/" location="/images"/>

<transformation extension="soy">

<transformer key="soyTransformer"/>

</transformation>

<resource type="download" name="dashboard-counter.soy.js" location="/soy/TabularData.soy"/>

<context>atl.dashboard</context>

</web-resource>
ACTIVE OBJECTS
p2 addon
EVENTS
ADDING A WEB ITEM
GETTING STARTED
WEB RESOURCES
Web Fragment Finder functionality
• Identify Web Items/Panels/Sections/Resource locations
• Click to copy xml
• Active Objects Inspector
• Event inspector
But what about Atlassian Connect?
SOMEBODY FROM ATLASSIAN
”“
BASIC WEB ITEMS
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
INSTALL ATLASSIAN CONNECT
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
NORMAL STARTING OF AC ENABLED JIRA
atlas-run-standalone --product jira --version 6.5-OD-03-002 --bundled-plugins
com.atlassian.bundles:json-schema-validator-atlassian-bundle:
1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:2.0.0,com.atlassian.jwt:jwt-
plugin:1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19-
D20150321T001323,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs -
Datlassian.upm.on.demand=true
(as of May 5th 2015)
STARTING OF AC ENABLED JIRA WITH WEBFRAGS
atlas-run-standalone --product jira
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
BASIC WEB-ITEM FRAGMENT
{

"url": "/my-web-item",

"location": "system.top.navigation.bar",

"context": "addon",

"weight": 200,

"target": {

"type": "page"

},

"styleClasses": [

"webitem",

"system-present-webitem"

],

"tooltip": {

"value": "Example tooltip"

},

"icon": {

"width": 16,

"height": 16,

"url": "/maps/icon.png"

},

"key": "web-item-example",

"name": {

"value": "My Web Item"

}

}
BASIC WEB ITEMS
WORKING WITH P2 ADD ONS
Atlassian Connect
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
MANAGING AC ADDONS
Atlassian Connect
WORKING WITH P2 ADD ONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
HTTP
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
ADDING WEB PANELS
ISSUE PROPERTIES
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
ADDING WEB PANELS
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ISSUE PROPERTIES
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
ISSUE PROPERTIES
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ADVANCED WEB ITEMS
INSTALL ATLASSIAN CONNECT
BASIC WEB ITEMS
ADVANCED WEB ITEMS
Atlassian Connect
WORKING WITH P2 ADD ONS
MANAGING AC ADDONS
HTTP
ADDING WEB PANELS
ISSUE PROPERTIES
INSTALL ATLASSIAN CONNECT
Web Fragment Finder functionality
• Identify Web Items/Panels/Sections/Resource locations
• Click to copy xml
• Active Objects Inspector
• Event inspector
Web Fragment Finder functionality
• Identify Web Items/Panels/
Sections/Resource locations
• Click to copy xml
• Active Objects Inspector
• Event inspector
• Identify Web Items/Panels/
Sections/Resource locations
• Click to copy json
• Manage Descriptors
• Start node applications
• HTTP traffic analyser
• Inspect properties
p2 AC
FINDING THE LOCATIONS
for (WebItemModuleDescriptor w : 

this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebItemModuleDescriptor.class))

{

	 	 …

}

for (WebSectionModuleDescriptor w : 

this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebSectionModuleDescriptor.class))

{

	 	 …

}

for (WebPanelModuleDescriptor w : 

this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebPanelModuleDescriptor.class))

{

…

}
GENERATING THE PLUGIN
File file = File.createTempFile("plugin-generator",".jar");
FileOutputStream fos = new FileOutputStream(file);
ZipOutputStream zipOut = new ZipOutputStream( fos );
Map<String, String> resourceJS = this.generateWebResources();
for (String item: resourceJS.keySet())
{
zipOut.putNextEntry( new ZipEntry( String.format( "web-resources/%s.js", item)) );
zipOut.write( resourceJS.get( item).getBytes());
}
zipOut.putNextEntry(new ZipEntry("atlassian-plugin.xml"));
zipOut.write(this.generatePluginXml().getBytes());
zipOut.putNextEntry(new ZipEntry("com/wittified/fragfinder/conditions/WebItemCondition.class"));
IOUtils.copy(this.getClass().getClassLoader().getResourceAsStream(
"com/wittified/fragfinder/conditions/WebItemCondition.class"), zipOut);
…
PluginArtifact pluginArtifact = this.pluginArtifactFactory.create(file.toURI());
this.pluginController.installPlugins(pluginArtifact);
FINDING EVENTS
@EventListener
public void onAllEvents( Object eventObject)
{
String className = eventObject.getClass().getName();
….
}
PROXY SERVER BUILT IN
public class PluginEnablingListener implements LifecycleAware, DisposableBean
{
public void onStart()
{
this.httpProxyService.start();
}
public void destroy()
{
this.httpProxyService.stop();
}
}
ATLASSIAN CONNECT INSTALLATION
{"validFrom":"2015-05-05T04:02:59.097Z","validTo":"OPEN","environment":{"dev":
{"connectVersion":"1.1.29","jiraCommand":"atlas-run-standalone --product jira --version 6.5-OD-03-003 --bundled-plugins
com.atlassian.bundles:json-schema-validator-atlassian-bundle:1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:
2.0.0,com.atlassian.jwt:jwt-plugin:1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19-
D20150504T170409,com.atlassian.plugins:atlassian-connect-plugin:1.1.29 --jvmargs -
Datlassian.upm.on.demand=true","confluenceCommand":"atlas-run-standalone --product confluence --version 5.8-
OD-51-005 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle:
1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:1.0.6,com.atlassian.jwt:jwt-plugin:
1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19-
D20150504T170409,com.atlassian.plugins:atlassian-connect-plugin:1.1.29 --jvmargs -
Datlassian.upm.on.demand=true"},"prd":{"connectVersion":"1.1.27","jiraCommand":"atlas-run-standalone --product jira --
version 6.5-OD-03-002 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle:
1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:2.0.0,com.atlassian.jwt:jwt-plugin:
1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19-
D20150321T001323,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs -
Datlassian.upm.on.demand=true","confluenceCommand":"atlas-run-standalone --product confluence --version 5.8-
OD-50-011 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle:
1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:1.0.6,com.atlassian.jwt:jwt-plugin:
1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19-
D20150422T024538,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs -Datlassian.upm.on.demand=true"}}}
source: https://developer.atlassian.com/static/connect/commands/connect-versions.json
* Sorry Crowd
Available for almost all apps*
Dig into the resources
Use Web Fragment Finder
Thank you!
DANIEL WESTER • CO-FOUNDER • WITTIFIED • @DWESTER42A

AtlasCamp 2015: Using add-ons to build add-ons

  • 1.
    Building add-ons using add-ons DANIELWESTER • CO-FOUNDER • WITTIFIED • @DWESTER42A
  • 2.
    Building add-ons using add-ons DANIELWESTER • CO-FOUNDER • WITTIFIED • @DWESTER42A
  • 3.
  • 4.
  • 6.
  • 8.
  • 12.
    ACTIVE OBJECTS p2 addon ADDINGA WEB ITEM WEB RESOURCES EVENTS GETTING STARTED
  • 13.
    ACTIVE OBJECTS GETTING STARTED p2addon ADDING A WEB ITEM WEB RESOURCES EVENTS
  • 14.
    BASIC DESCRIPTOR <atlassian-plugin key="${project.groupId}.${project.artifactId}"name="${project.name}" plugins-version="2"> <plugin-info> <description>${project.description}</description> <version>${project.version}</version> <vendor name="${project.organization.name}" url="${project.organization.url}" /> <param name="plugin-icon">images/pluginIcon.png</param> <param name="plugin-logo">images/pluginLogo.png</param> </plugin-info> <component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" /> <component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/> <component-import key="ao" name="Active Objects service" interface="com.atlassian.activeobjects.external.ActiveObjects"> <description>Active Objects functionality from the plugin</description> </component-import> <ao key="ao-module"> <description>Active Objects entries</description> <entity>com.wittified.pres.DashView</entity> </ao> <component key="dash-tracker-service" class="com.wittified.pres.DashTrackerServiceImpl"> <interface>com.wittified.pres.DashTrackerService</interface> </component> <rest key="rest-end-points" path="/wittified/dashboards" version="1.0"> <description>REST interface to integrate with things</description> </rest> <resource type="i18n" name="i18n" location="dashboard-tracker"/> <web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp- dashboard-tracker Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <dependency>com.atlassian.auiplugin:dialog2</dependency> <resource type="download" name="dashboard-tracker.css" location="/css/dashboard- tracker.css"/> <resource type="download" name="dashboard-tracker.js" location="/js/dashboard- tracker.js"/> <resource type="download" name="images/" location="/images"/> <transformation extension="soy"> <transformer key="soyTransformer"/> </transformation> <resource type="download" name="dashboard-counter.soy.js" location="/soy/ TabularData.soy"/> <context>atl.general</context> </web-resource> </atlassian-plugin>
  • 15.
    ACTIVE OBJECTS ENTITY packagecom.wittified.pres; import net.java.ao.Entity; import net.java.ao.schema.PrimaryKey; public interface DashView extends Entity { public Long getDashboard(); public void setDashboard(Long dashboard); public Long getViews(); public void setViews( Long count); }
  • 16.
    ACTIVE OBJECTS SERVICE @Override @Transactional publicvoid trackThis(long dashboard) { DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARDS = ? ", dashboard) ); DashView dashView = null; if(dashViews.length==0) { dashView = this.activeObjects.create( DashView.class); dashView.setDashboard( dashboard); dashView.setViews(0L); } else { dashView = dashViews[0]; } dashView.setViews(dashView.getViews() + 1); dashView.save(); }
  • 17.
    REST @GET @Produces({MediaType.APPLICATION_JSON}) @Path("/all") public Response getAll() { List<DashBoardEntity>dashBoardEntityList = new ArrayList<DashBoardEntity>(); for(DashView dashView: this.dashTrackerService.getAll()) { PortalPage page = this.portalPageManager.getPortalPageById( dashView.getDashboard()); DashBoardEntity dashBoardEntity = new DashBoardEntity(); dashBoardEntity.setName( page.getName()); dashBoardEntity.setCount( dashView.getViews()); dashBoardEntity.setId( dashView.getDashboard()); if(page.getOwner()==null) { dashBoardEntity.setOwner("None"); } else { dashBoardEntity.setOwner(page.getOwner().getDisplayName()); } dashBoardEntityList.add( dashBoardEntity); } return Response.ok( dashBoardEntityList).build();
  • 18.
    EVENT LISTENER public classDashBoardEventListener implements InitializingBean, DisposableBean { private final EventPublisher eventPublisher; private final DashTrackerService dashTrackerService; public DashBoardEventListener( final EventPublisher eventPublisher, final DashTrackerService dashTrackerService) { this.eventPublisher = eventPublisher; this.dashTrackerService = dashTrackerService; } @Override public void destroy() throws Exception { this.eventPublisher.unregister( this); } @Override public void afterPropertiesSet() throws Exception { this.eventPublisher.register( this); } }
  • 19.
    ACTIVE OBJECTS EVENTS p2 addon ADDINGA WEB ITEM WEB RESOURCES GETTING STARTED
  • 21.
    EVENT LISTENER @EventListener public voidonDashboardViewEvent( DashboardViewEvent dashboardViewEvent) { this.dashTrackerService.trackThis( dashboardViewEvent.getId() ); }
  • 22.
    EVENTS ACTIVE OBJECTS p2 addon ADDINGA WEB ITEM WEB RESOURCES GETTING STARTED
  • 24.
  • 27.
    ACTIVE OBJECT SERVICEERROR DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARDS = ? ", dashboard) );
  • 28.
    ACTIVE OBJECT SERVICEFIXED DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARD = ? ", dashboard) );
  • 30.
    ACTIVE OBJECTS ADDING AWEB ITEM p2 addon EVENTS WEB RESOURCES GETTING STARTED
  • 32.
    TEMPLATEIZED WEB-ITEM <web-item key="web-item-example"name="My Web Item" section="gadgets.dashboard.menu" weight=“200"> <description key="my-web-item-desc">General description</description> <label key="my-web-item-label" /> <link linkId=“my-web-item-link”>/my-web-item</link> </web-item>
  • 33.
    FLUSHED OUT WEB-ITEM <web-itemkey="web-item-dashboard-usage" name="DashBoard Usage" section="gadgets.dashboard.menu" weight="200"> <description key="my-web-item-desc">General description</ description> <label key="Dashboard usage" /> <link linkId=“dashboard-usagelink">/</link> </web-item>
  • 34.
    ACTIVE OBJECTS WEB RESOURCES p2addon EVENTS ADDING A WEB ITEM GETTING STARTED
  • 35.
    WEB RESOURCE ENTY:GENERAL <web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp-dashboard-tracker Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <dependency>com.atlassian.auiplugin:dialog2</dependency> <resource type="download" name="dashboard-tracker.css" location="/css/dashboard-tracker.css"/> <resource type="download" name="dashboard-tracker.js" location="/js/dashboard-tracker.js"/> <resource type="download" name="images/" location="/images"/> <transformation extension="soy"> <transformer key="soyTransformer"/> </transformation> <resource type="download" name="dashboard-counter.soy.js" location="/soy/TabularData.soy"/> <context>atl.general</context> </web-resource>
  • 38.
    WEB RESOURCE ENTY:SPECIFIC <web-resource key="atlascamp-dashboard-tracker-resources" name="atlascamp-dashboard-tracker Web Resources"> <dependency>com.atlassian.auiplugin:ajs</dependency> <dependency>com.atlassian.auiplugin:dialog2</dependency> <resource type="download" name="dashboard-tracker.css" location="/css/dashboard-tracker.css"/> <resource type="download" name="dashboard-tracker.js" location="/js/dashboard-tracker.js"/> <resource type="download" name="images/" location="/images"/> <transformation extension="soy"> <transformer key="soyTransformer"/> </transformation> <resource type="download" name="dashboard-counter.soy.js" location="/soy/TabularData.soy"/> <context>atl.dashboard</context> </web-resource>
  • 39.
    ACTIVE OBJECTS p2 addon EVENTS ADDINGA WEB ITEM GETTING STARTED WEB RESOURCES
  • 41.
    Web Fragment Finderfunctionality • Identify Web Items/Panels/Sections/Resource locations • Click to copy xml • Active Objects Inspector • Event inspector
  • 42.
    But what aboutAtlassian Connect? SOMEBODY FROM ATLASSIAN ”“
  • 43.
    BASIC WEB ITEMS AtlassianConnect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 44.
    BASIC WEB ITEMS INSTALLATLASSIAN CONNECT Atlassian Connect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS
  • 45.
    NORMAL STARTING OFAC ENABLED JIRA atlas-run-standalone --product jira --version 6.5-OD-03-002 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle: 1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:2.0.0,com.atlassian.jwt:jwt- plugin:1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19- D20150321T001323,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs - Datlassian.upm.on.demand=true (as of May 5th 2015)
  • 46.
    STARTING OF ACENABLED JIRA WITH WEBFRAGS atlas-run-standalone --product jira
  • 50.
    INSTALL ATLASSIAN CONNECT BASICWEB ITEMS Atlassian Connect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS
  • 52.
    BASIC WEB-ITEM FRAGMENT { "url":"/my-web-item", "location": "system.top.navigation.bar", "context": "addon", "weight": 200, "target": { "type": "page" }, "styleClasses": [ "webitem", "system-present-webitem" ], "tooltip": { "value": "Example tooltip" }, "icon": { "width": 16, "height": 16, "url": "/maps/icon.png" }, "key": "web-item-example", "name": { "value": "My Web Item" } }
  • 53.
    BASIC WEB ITEMS WORKINGWITH P2 ADD ONS Atlassian Connect MANAGING AC ADDONS HTTP ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 56.
    BASIC WEB ITEMS MANAGINGAC ADDONS Atlassian Connect WORKING WITH P2 ADD ONS HTTP ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 60.
    BASIC WEB ITEMS HTTP AtlassianConnect WORKING WITH P2 ADD ONS MANAGING AC ADDONS ADDING WEB PANELS ISSUE PROPERTIES ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 62.
    BASIC WEB ITEMS ADDINGWEB PANELS Atlassian Connect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ISSUE PROPERTIES ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 66.
    BASIC WEB ITEMS ISSUEPROPERTIES Atlassian Connect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ADDING WEB PANELS ADVANCED WEB ITEMS INSTALL ATLASSIAN CONNECT
  • 68.
    BASIC WEB ITEMS ADVANCEDWEB ITEMS Atlassian Connect WORKING WITH P2 ADD ONS MANAGING AC ADDONS HTTP ADDING WEB PANELS ISSUE PROPERTIES INSTALL ATLASSIAN CONNECT
  • 72.
    Web Fragment Finderfunctionality • Identify Web Items/Panels/Sections/Resource locations • Click to copy xml • Active Objects Inspector • Event inspector
  • 73.
    Web Fragment Finderfunctionality • Identify Web Items/Panels/ Sections/Resource locations • Click to copy xml • Active Objects Inspector • Event inspector • Identify Web Items/Panels/ Sections/Resource locations • Click to copy json • Manage Descriptors • Start node applications • HTTP traffic analyser • Inspect properties p2 AC
  • 74.
    FINDING THE LOCATIONS for(WebItemModuleDescriptor w : 
 this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebItemModuleDescriptor.class)) { … } for (WebSectionModuleDescriptor w : this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebSectionModuleDescriptor.class)) { … } for (WebPanelModuleDescriptor w : 
 this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebPanelModuleDescriptor.class)) { … }
  • 75.
    GENERATING THE PLUGIN Filefile = File.createTempFile("plugin-generator",".jar"); FileOutputStream fos = new FileOutputStream(file); ZipOutputStream zipOut = new ZipOutputStream( fos ); Map<String, String> resourceJS = this.generateWebResources(); for (String item: resourceJS.keySet()) { zipOut.putNextEntry( new ZipEntry( String.format( "web-resources/%s.js", item)) ); zipOut.write( resourceJS.get( item).getBytes()); } zipOut.putNextEntry(new ZipEntry("atlassian-plugin.xml")); zipOut.write(this.generatePluginXml().getBytes()); zipOut.putNextEntry(new ZipEntry("com/wittified/fragfinder/conditions/WebItemCondition.class")); IOUtils.copy(this.getClass().getClassLoader().getResourceAsStream( "com/wittified/fragfinder/conditions/WebItemCondition.class"), zipOut); … PluginArtifact pluginArtifact = this.pluginArtifactFactory.create(file.toURI()); this.pluginController.installPlugins(pluginArtifact);
  • 76.
    FINDING EVENTS @EventListener public voidonAllEvents( Object eventObject) { String className = eventObject.getClass().getName(); …. }
  • 77.
    PROXY SERVER BUILTIN public class PluginEnablingListener implements LifecycleAware, DisposableBean { public void onStart() { this.httpProxyService.start(); } public void destroy() { this.httpProxyService.stop(); } }
  • 78.
    ATLASSIAN CONNECT INSTALLATION {"validFrom":"2015-05-05T04:02:59.097Z","validTo":"OPEN","environment":{"dev": {"connectVersion":"1.1.29","jiraCommand":"atlas-run-standalone--product jira --version 6.5-OD-03-003 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle:1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin: 2.0.0,com.atlassian.jwt:jwt-plugin:1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19- D20150504T170409,com.atlassian.plugins:atlassian-connect-plugin:1.1.29 --jvmargs - Datlassian.upm.on.demand=true","confluenceCommand":"atlas-run-standalone --product confluence --version 5.8- OD-51-005 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle: 1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:1.0.6,com.atlassian.jwt:jwt-plugin: 1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19- D20150504T170409,com.atlassian.plugins:atlassian-connect-plugin:1.1.29 --jvmargs - Datlassian.upm.on.demand=true"},"prd":{"connectVersion":"1.1.27","jiraCommand":"atlas-run-standalone --product jira -- version 6.5-OD-03-002 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle: 1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:2.0.0,com.atlassian.jwt:jwt-plugin: 1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19- D20150321T001323,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs - Datlassian.upm.on.demand=true","confluenceCommand":"atlas-run-standalone --product confluence --version 5.8- OD-50-011 --bundled-plugins com.atlassian.bundles:json-schema-validator-atlassian-bundle: 1.0.4,com.atlassian.webhooks:atlassian-webhooks-plugin:1.0.6,com.atlassian.jwt:jwt-plugin: 1.2.2,com.atlassian.upm:atlassian-universal-plugin-manager-plugin:2.19- D20150422T024538,com.atlassian.plugins:atlassian-connect-plugin:1.1.27 --jvmargs -Datlassian.upm.on.demand=true"}}} source: https://developer.atlassian.com/static/connect/commands/connect-versions.json
  • 79.
    * Sorry Crowd Availablefor almost all apps*
  • 80.
    Dig into theresources
  • 82.
  • 83.
    Thank you! DANIEL WESTER• CO-FOUNDER • WITTIFIED • @DWESTER42A