AtlasCamp 2015: Using add-ons to build add-ons
-
Upload
atlassian -
Category
Technology
-
view
775 -
download
2
Transcript of AtlasCamp 2015: Using add-ons to build add-ons
A C T I V E O B J E C T S
p2 addon
A D D I N G A W E B I T E M
W E B R E S O U R C E S
E V E N T S
G E T T I N G S TA R T E D
A C T I V E O B J E C T S
G E T T I N G S TA R T E D
p2 addon
A D D I N G A W E B I T E M
W E B R E S O U R C E S
E V E N T S
B A S I C D E S C R I P TO R
<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>
A C T I V E O B J E C T S E N T I T Y
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);}
A C T I V E O B J E C T S S E RV I C E
@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(); }
R E S T
@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(); }
E V E N T L I S T E N E R
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); }}
A C T I V E O B J E C T S
E V E N T S
p2 addon
A D D I N G A W E B I T E M
W E B R E S O U R C E S
G E T T I N G S TA R T E D
E V E N T L I S T E N E R
@EventListener public void onDashboardViewEvent( DashboardViewEvent dashboardViewEvent) { this.dashTrackerService.trackThis( dashboardViewEvent.getId() ); }
E V E N T S
A C T I V E O B J E C T S
p2 addon
A D D I N G A W E B I T E M
W E B R E S O U R C E S
G E T T I N G S TA R T E D
A C T I V E O B J E C T S E RV I C E E R R O R
DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARDS = ? ", dashboard) );
A C T I V E O B J E C T S E RV I C E F I X E D
DashView[] dashViews = this.activeObjects.find(DashView.class, Query.select().where(" DASHBOARD = ? ", dashboard) );
A C T I V E O B J E C T S
A D D I N G A W E B I T E M
p2 addon
E V E N T S
W E B R E S O U R C E S
G E T T I N G S TA R T E D
T E M P L AT E I Z E D W E B - I T E M
<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>
F L U S H E D O U T W E B - I T E M
<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>
A C T I V E O B J E C T S
W E B R E S O U R C E S
p2 addon
E V E N T S
A D D I N G A W E B I T E M
G E T T I N G S TA R T E D
W E B R E S O U R C E E N T Y: G E N E R A L
<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>
W E B R E S O U R C E E N T Y: S P E C I F I C
<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>
A C T I V E O B J E C T S
p2 addon
E V E N T S
A D D I N G A W E B I T E M
G E T T I N G S TA R T E D
W E B R E S O U R C E S
Web Fragment Finder functionality
• Identify Web Items/Panels/Sections/Resource locations• Click to copy xml• Active Objects Inspector• Event inspector
B A S I C W E B I T E M S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
N O R M A L S TA R T I N G O F A C E N A B L E D J I R A
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)
S TA R T I N G O F A C E N A B L E D J I R A W I T H W E B F R A G S
atlas-run-standalone --product jira
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
B A S I C W E B - I T E M F R A G M E N T
{ "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" }}
B A S I C W E B I T E M S
W O R K I N G W I T H P 2 A D D O N S
Atlassian Connect
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
M A N A G I N G A C A D D O N S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
H T T P
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
A D D I N G W E B PA N E L S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
I S S U E P R O P E R T I E S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
I S S U E P R O P E R T I E S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
A D VA N C E D W E B I T E M S
I N S TA L L AT L A S S I A N C O N N E C T
B A S I C W E B I T E M S
A D VA N C E D W E B I T E M S
Atlassian Connect
W O R K I N G W I T H P 2 A D D O N S
M A N A G I N G A C A D D O N S
H T T P
A D D I N G W E B PA N E L S
I S S U E P R O P E R T I E S
I N S TA L L AT L A S S I A N C O N N E C T
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
F I N D I N G T H E L O C AT I O N S
for (WebItemModuleDescriptor w : this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebItemModuleDescriptor.class)){ …}for (WebSectionModuleDescriptor w :
this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebSectionModuleDescriptor.class)){ …}for (WebPanelModuleDescriptor w : this.pluginAccessor.getEnabledModuleDescriptorsByClass( WebPanelModuleDescriptor.class)){ …}
G E N E R AT I N G T H E P L U G I N
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);
F I N D I N G E V E N T S
@EventListenerpublic void onAllEvents( Object eventObject){ String className = eventObject.getClass().getName(); ….}
P R O X Y S E RV E R B U I LT I N
public class PluginEnablingListener implements LifecycleAware, DisposableBean{
public void onStart(){
this.httpProxyService.start();}
public void destroy(){
this.httpProxyService.stop();}
}
AT L A S S I A N C O N N E C T I N S TA L L AT I O N
{"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