SlideShare ist ein Scribd-Unternehmen logo
1 von 65
Downloaden Sie, um offline zu lesen
VICTORIA SKALRUD | SENIOR DEVELOPMENT TL | ATLASSIAN
Practical Patterns for Developing a Cross-
product Cross-version App
Lessons from working on the
Atlassian Troubleshooting &Support Tools
(ATST)
Developing
cross
version
Developing
cross
product
Developing
DC features
Q & A
Agenda
Developing
cross
version
Developing
cross
product
Developing
DC features
Q & A
Agenda
Developing
cross
version
Developing
cross
product
Developing
DC features
Q & A
Agenda
Developing
cross
version
Developing
cross
product
Developing
DC features
Q & A
Agenda
Developing cross version
Why developing to support multiple versions of a product is a good idea
Why developing to support multiple versions of
a product is a good idea
Why developing to support multiple versions of
a product is a good idea
Platform version (aka Major
release)
Contain features and API breaking changes.
Feature version(aka Minor
release)
Contain features but no API breaking changes
Bugfix version
Primarily intended to fix problems without
altering behaviour
Versioning @
Atlassian
Server
Platform version (aka Major
release)
Contain features and API breaking changes.
Feature version(aka Minor
release)
Contain features but no API breaking changes
Bugfix version
Primarily intended to fix problems without
altering behaviour
Versioning @
Atlassian
Server
Platform version (aka Major
release)
Contain features and API breaking changes.
Feature version(aka Minor
release)
Contains features but no API breaking changes
Bugfix version
Primarily intended to fix problems without
altering behaviour
Versioning @
Atlassian
Server
Platform version (aka Major
release)
Contain features and API breaking changes.
Feature version(aka Minor
release)
Contain features but no API breaking changes
Bugfix version
Primarily intended to fix problems without
altering behaviour.
Versioning @
Atlassian
Server
CHALLENGE #1
I WANT TO INTRODUCE A
FEATURE THAT WILL ONLY
SHOW FOR LATER HOST
PRODUCT VERSIONS
interface Feature {
boolean shouldDisplay();
}
Limiting
features to
version
Feature Flags
Web resource
conditions
interface Feature {
boolean shouldDisplay();
}
public class MyNewFeature implements Feature
{
private static int MIN_SUPPORTED_VERSION = 5;
boolean shouldDisplay() {
return getCurrentVersionOfHostProduct() >= MIN_SUPPORTED_VERSION &&
isEnabled("myNewFeature");
}
}
// In another class somewhere
// Gets current version of the host product
// - does not rely on version plugin was compiled with
getCurrentVersionOfHostProduct()
Limiting
features to
version
Feature Flags
Web resource
conditions
// In Confluence, in atlassian-plugin.xml
<condition
class="com.atlassian.confluence.plugin.descriptor.web.conditions.BuildNumberCondition">
<param name="minBuildNumber">8200</param>
</condition>
Limiting
features to
version
Feature Flags
Web resource
conditions
// In Confluence, in atlassian-plugin.xml
<condition
class="com.atlassian.confluence.plugin.descriptor.web.conditions.BuildNumberCondition">
<param name="minBuildNumber">8200</param>
</condition>
// In Bitbucket, in atlassian-plugin.xml
<condition
class=“com.atlassian.bitbucket.web.conditions.IsApplicationVersionCondition">
<param name=“operator">gte</param>
<param name=“version”>6.4</param>
</condition>
Limiting
features to
version
Web resource
conditions
Feature Flags
CHALLENGE #2
I WANT TO WRITE MY
FEATURE TO BE RESILIENT
ACROSS API CHANGES
public interface JiraApi {
// doing useful stuff
// @since 6.4
String someMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
public interface JiraApi {
// doing useful stuff
// @since 6.4
String someMethod();
}
public void myFunction(){
jiraApi.someMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
// Newer version of Jira
public interface JiraApi {
@deprecated
String someMethod();
String shinyNewUsefulMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
// Newer version of Jira
public interface JiraApi {
@deprecated
String someMethod();
String shinyNewUsefulMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
// Even newer version of Jira
public interface JiraApi {
String someMethod();
String shinyNewUsefulMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
// Even newer version of Jira
public interface JiraApi {
String someMethod();
String shinyNewUsefulMethod();
}
// Will only work in newer versions
public void myFunction(){
jiraApi.shinyNewUsefulMethod();
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
// Even newer version of Jira
public interface JiraApi {
String someMethod();
String shinyNewUsefulMethod();
}
// Do not fear failure but rather fear not trying
public void myFunction() {
try {
jiraApi.shinyNewUsefulMethod();
} catch (final NoSuchMethodError nsme) {
// fallback
}
}
Version
Resilience
Jira API
Using the API
Ch Ch Change
Trouble in paradise
Try
You can build a
bridge!
BETTER WAY
1 Create a clear separation of concerns
Building bridges
Your app that does
cool things and
accesses API
1 Create a clear separation of concerns
Building bridges
Your business
logic
COM.MYSTUFF
1 Create a clear separation of concerns
Building bridges
Your business
logic
COM.MYSTUFF
Things you need
that you get via API
COM.MYSTUFF.ACCESS
1 Create a clear separation of concerns
Building bridges
2 Define your bridge blueprint
1 Create a clear separation of concerns
Building bridges
2 Define your bridge blueprint
public interface SearchServiceBridge {
Collection<Issue> search(Query query) throws PlatformException;
}
1 Create a clear separation of concerns
Building bridges
2 Define your bridge blueprint
3 Build out your bridges
1 Create a clear separation of concerns
Building bridges
2 Define your bridge blueprint
3 Build out your bridges
1 Create a clear separation of concerns
Building bridges
2 Define your bridge blueprint
3 Build out your bridges
1 Create a clear separation of concerns
Building bridges
@SupportedVersions(minimumInclusive = "7.4.0")
final class SearchServiceBridge74 implements SearchServiceBridge {
public Collection<Issue> search(Query query){
// Access the Jira APIs here - 7.4 specific code
}
}
@SupportedVersions(minimumInclusive = "7.12.0")
final class SearchServiceBridge712 implements SearchServiceBridge {
public Collection<Issue> search(Query query){
// Access the Jira APIs here - 7.12 specific code
}
}
2 Define your bridge blueprint
3 Build out your bridges
Building bridges
1 Create a clear separation of concerns
2 Define your bridge blueprint
3 Build out your bridges
4 Build a way to select which bridge should be used
Building
bridges
@Retention(RetentionPolicy.RUNTIME)
public @interface SupportedVersions {
String minimumInclusive() default “0.0.0";
String maximumExclusive() default "99999.99999.99999";
}
Versioning
Manager
Bridges
Using the bridge
Building
bridges
final class BridgeManager<Bridge> {
public Optional<Bridge> getSupportedBridge(Version version) {
return bridgeBeans.stream()
.filter(bridgeBean ->
isSupported(bridgeBean, version)).findFirst();
}
}
Versioning
Manager
Bridges
Using the bridge
Building
bridges
final class BridgeManager<Bridge> {
public Optional<Bridge> getSupportedBridge(Version version) {
return bridgeBeans.stream()
.filter(bridgeBean ->
isSupported(bridgeBean, version)).findFirst();
}
private boolean isSupported(Bridge bridgeBean, Version version) {
return Stream.of(bridgeBean.getClass()
.getAnnotation(SUPPORTED_VERSIONS_ANNOTATION))
.anyMatch(annotation ->
isSupported(annotation, version));
}
private boolean isSupported(SupportedVersions supportedVersions, Version version)
final Version minimumInclusive = parse(supportedVersions.minimumInclusive());
final Version maximumExclusive = parse(supportedVersions.maximumExclusive());
return minimumInclusive.isLessThanOrEqualTo(version) &&
maximumExclusive.isGreaterThan(version);
}
}
Versioning
Manager
Bridges
Using the bridge
Building
bridges
public interface SearchServiceBridge {
Collection<Issue> search(Query query) throws PlatformException;
}
Versions
Manager
Bridges
Using the bridge
Building
bridges
public interface SearchServiceBridge {
Collection<Issue> search(Query query) throws PlatformException;
}
@ExportAsService({SearchServiceBridge.class})
@Named("com.atlassian.bridges.search.SearchServiceBridge74")
@SupportedVersions(minimumInclusive = "7.4.0", maximumExclusive = “7.12.0")
final class SearchServiceBridge74 implements SearchServiceBridge {
@Override
public Collection<Issue> search(Query query)
throws PlatformException {
…
}
}
Versions
Manager
Bridges
Using the bridge
Building
bridges
public interface SearchServiceBridge {
Collection<Issue> search(Query query) throws PlatformException;
}
@ExportAsService({SearchServiceBridge.class})
@Named("com.atlassian.bridges.search.SearchServiceBridge74")
@SupportedVersions(minimumInclusive = "7.4.0", maximumExclusive = “7.12.0")
final class SearchServiceBridge74 implements SearchServiceBridge {
@Override
public Collection<Issue> search(Query query)
throws PlatformException {
…
}
}
@ExportAsService({SearchServiceBridge.class})
@Named("com.atlassian.bridges.search.SearchServiceBridge712")
@SupportedVersions(minimumInclusive = "7.12.0", maximumExclusive = "8.0")
final class SearchServiceBridge712 implements SearchServiceBridge {
@Override
public Collection<Issue> search(Query query)
throws PlatformException {
…
}
}
Versions
Manager
Bridges
Using the bridge
Building
bridges
Versions
Manager
public class MyCode {
Supplier<SearchServiceBridge> searchService;
void doMyThing() {
searchService.get().search(query);
}
}
Bridges
Using the bridge
Building a bridge
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>7.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<version>7.12.0</version>
<scope>provided</scope>
</dependency>
BRIDGES 7.12
BRIDGES 7.6
BRIDGE INTERFACES
pom
APP
pom
Don’t depend
on core/
internal if you
can help it
Developing cross product
ATST Product & Version supported matrix
ATST Project structure
API COMMON
ATST
ATST Project structure
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<scope>provided</scope>
</dependency>
PLUGIN-JIRA
API
pom
COMMON
ATST
ATST Project structure
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.confluence</groupId>
<artifactId>confluence-api</artifactId>
<scope>provided</scope>
</dependency>
PLUGIN-CONF
PLUGIN-JIRA
API
pom
pom
COMMON
ATST
Introducing a feature
1 Introduce required API in the ATST api module
Introducing a feature
1 Introduce required API in the ATST api module
2 If implementation is shared, add it to ATST common module
Introducing a feature
1 Introduce required API in the ATST api module
2 If implementation is shared, add it to ATST common module
3 If implementation is product specific, add it to the corresponding
product module
Introducing a feature
1 Introduce required API in the ATST api module
2 If implementation is shared, add it to ATST common module
3 If implementation is product specific, add it to the corresponding
product module
4 If a feature is not required for a particular product, include a
NoOp implementation
Tips for cross product development
1 Use of SAL (Shared Access Layer) APIs to simplify development
Tips for cross product development
1
<dependency>
<groupId>com.atlassian.sal</groupId>
<artifactId>sal-api</artifactId>
<version>2.0.17</version>
<!-- Uses the application's SAL instead
of bundling it into the plugin. -->
<scope>provided</scope>
</dependency>
Use of SAL (Shared Access Layer) APIs to simplify development
Tips for cross product development
1 Use of SAL (Shared Access Layer) APIs to simplify development
2 Use provided scope to use the host product’s libraries instead
of bundling own
Developing for Data Centre
Developing for Data Centre
1 Keep the concepts of ‘licenced for data-center’,
‘clustering available’ and ‘clustering active’ as
separate and do not mix
Developing for Data Centre
Keep the concepts of ‘licenced for data-center’,
‘clustering available’ and ‘clustering active’ as
separate and do not mix
2 Every time you introduce a new feature, consider if this feature
needs to operate per cluster or per node
1
Developing for Data Centre
1 Keep the concepts of ‘licenced for data-center’,
‘clustering available’ and ‘clustering active’ as
separate and do not mix
2 Every time you introduce a new feature, consider if this feature
needs to operate per cluster or per node
3 Take a look at the Atlassian documentation for developing data
centre applications
Thank you!
VICTORIA SKALRUD | SENIOR DEVELOPMENT TL | ATLASSIAN

Weitere ähnliche Inhalte

Was ist angesagt?

The New & Improved Confluence Server and Data Center
The New & Improved Confluence Server and Data CenterThe New & Improved Confluence Server and Data Center
The New & Improved Confluence Server and Data CenterAtlassian
 
How to Build a Better JIRA Add-on
How to Build a Better JIRA Add-onHow to Build a Better JIRA Add-on
How to Build a Better JIRA Add-onAtlassian
 
Designing and Running a GraphQL API
Designing and Running a GraphQL APIDesigning and Running a GraphQL API
Designing and Running a GraphQL APIAtlassian
 
What's New in Jira Cloud for Developers
What's New in Jira Cloud for DevelopersWhat's New in Jira Cloud for Developers
What's New in Jira Cloud for DevelopersAtlassian
 
What Does Jira Next-Gen Mean for Cloud Apps?
What Does Jira Next-Gen Mean for Cloud Apps?What Does Jira Next-Gen Mean for Cloud Apps?
What Does Jira Next-Gen Mean for Cloud Apps?Atlassian
 
The User Who Must Not be Named: GDPR and Your Jira App
The User Who Must Not be Named: GDPR and Your Jira AppThe User Who Must Not be Named: GDPR and Your Jira App
The User Who Must Not be Named: GDPR and Your Jira AppAtlassian
 
4 Changes We're Making to Help you be Successful in the Cloud
4 Changes We're Making to Help you be Successful in the Cloud4 Changes We're Making to Help you be Successful in the Cloud
4 Changes We're Making to Help you be Successful in the CloudAtlassian
 
Creating Your Own Server Add-on that Customizes Confluence or JIRA
Creating Your Own Server Add-on that Customizes Confluence or JIRACreating Your Own Server Add-on that Customizes Confluence or JIRA
Creating Your Own Server Add-on that Customizes Confluence or JIRAAtlassian
 
Atlassian Connect on Serverless Platforms: Low Cost Add-Ons
Atlassian Connect on Serverless Platforms: Low Cost Add-OnsAtlassian Connect on Serverless Platforms: Low Cost Add-Ons
Atlassian Connect on Serverless Platforms: Low Cost Add-OnsAtlassian
 
Integrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudIntegrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudAtlassian
 
Serverless Analytics and Monitoring For Your Cloud App
Serverless Analytics and Monitoring For Your Cloud AppServerless Analytics and Monitoring For Your Cloud App
Serverless Analytics and Monitoring For Your Cloud AppAtlassian
 
Access to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAccess to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAtlassian
 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastAtlassian
 
Server Add-ons for Front-end Developers
Server Add-ons for Front-end DevelopersServer Add-ons for Front-end Developers
Server Add-ons for Front-end DevelopersAtlassian
 
Preparing for Data Residency and Custom Domains
Preparing for Data Residency and Custom DomainsPreparing for Data Residency and Custom Domains
Preparing for Data Residency and Custom DomainsAtlassian
 
Integrating Jira Software Cloud With the AWS Code Suite
Integrating Jira Software Cloud With the AWS Code SuiteIntegrating Jira Software Cloud With the AWS Code Suite
Integrating Jira Software Cloud With the AWS Code SuiteAtlassian
 
Meet the Forge Runtime
Meet the Forge RuntimeMeet the Forge Runtime
Meet the Forge RuntimeAtlassian
 
Ten Battle-Tested Tips for Atlassian Connect Add-ons
Ten Battle-Tested Tips for Atlassian Connect Add-onsTen Battle-Tested Tips for Atlassian Connect Add-ons
Ten Battle-Tested Tips for Atlassian Connect Add-onsAtlassian
 
Discover the Possibilities of the Jira Cloud Asset API
Discover the Possibilities of the Jira Cloud Asset APIDiscover the Possibilities of the Jira Cloud Asset API
Discover the Possibilities of the Jira Cloud Asset APIAtlassian
 
Forge: Under the Hood
Forge: Under the HoodForge: Under the Hood
Forge: Under the HoodAtlassian
 

Was ist angesagt? (20)

The New & Improved Confluence Server and Data Center
The New & Improved Confluence Server and Data CenterThe New & Improved Confluence Server and Data Center
The New & Improved Confluence Server and Data Center
 
How to Build a Better JIRA Add-on
How to Build a Better JIRA Add-onHow to Build a Better JIRA Add-on
How to Build a Better JIRA Add-on
 
Designing and Running a GraphQL API
Designing and Running a GraphQL APIDesigning and Running a GraphQL API
Designing and Running a GraphQL API
 
What's New in Jira Cloud for Developers
What's New in Jira Cloud for DevelopersWhat's New in Jira Cloud for Developers
What's New in Jira Cloud for Developers
 
What Does Jira Next-Gen Mean for Cloud Apps?
What Does Jira Next-Gen Mean for Cloud Apps?What Does Jira Next-Gen Mean for Cloud Apps?
What Does Jira Next-Gen Mean for Cloud Apps?
 
The User Who Must Not be Named: GDPR and Your Jira App
The User Who Must Not be Named: GDPR and Your Jira AppThe User Who Must Not be Named: GDPR and Your Jira App
The User Who Must Not be Named: GDPR and Your Jira App
 
4 Changes We're Making to Help you be Successful in the Cloud
4 Changes We're Making to Help you be Successful in the Cloud4 Changes We're Making to Help you be Successful in the Cloud
4 Changes We're Making to Help you be Successful in the Cloud
 
Creating Your Own Server Add-on that Customizes Confluence or JIRA
Creating Your Own Server Add-on that Customizes Confluence or JIRACreating Your Own Server Add-on that Customizes Confluence or JIRA
Creating Your Own Server Add-on that Customizes Confluence or JIRA
 
Atlassian Connect on Serverless Platforms: Low Cost Add-Ons
Atlassian Connect on Serverless Platforms: Low Cost Add-OnsAtlassian Connect on Serverless Platforms: Low Cost Add-Ons
Atlassian Connect on Serverless Platforms: Low Cost Add-Ons
 
Integrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software CloudIntegrate CI/CD Pipelines with Jira Software Cloud
Integrate CI/CD Pipelines with Jira Software Cloud
 
Serverless Analytics and Monitoring For Your Cloud App
Serverless Analytics and Monitoring For Your Cloud AppServerless Analytics and Monitoring For Your Cloud App
Serverless Analytics and Monitoring For Your Cloud App
 
Access to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIsAccess to User Activities - Activity Platform APIs
Access to User Activities - Activity Platform APIs
 
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fastHow Bitbucket Pipelines Loads Connect UI Assets Super-fast
How Bitbucket Pipelines Loads Connect UI Assets Super-fast
 
Server Add-ons for Front-end Developers
Server Add-ons for Front-end DevelopersServer Add-ons for Front-end Developers
Server Add-ons for Front-end Developers
 
Preparing for Data Residency and Custom Domains
Preparing for Data Residency and Custom DomainsPreparing for Data Residency and Custom Domains
Preparing for Data Residency and Custom Domains
 
Integrating Jira Software Cloud With the AWS Code Suite
Integrating Jira Software Cloud With the AWS Code SuiteIntegrating Jira Software Cloud With the AWS Code Suite
Integrating Jira Software Cloud With the AWS Code Suite
 
Meet the Forge Runtime
Meet the Forge RuntimeMeet the Forge Runtime
Meet the Forge Runtime
 
Ten Battle-Tested Tips for Atlassian Connect Add-ons
Ten Battle-Tested Tips for Atlassian Connect Add-onsTen Battle-Tested Tips for Atlassian Connect Add-ons
Ten Battle-Tested Tips for Atlassian Connect Add-ons
 
Discover the Possibilities of the Jira Cloud Asset API
Discover the Possibilities of the Jira Cloud Asset APIDiscover the Possibilities of the Jira Cloud Asset API
Discover the Possibilities of the Jira Cloud Asset API
 
Forge: Under the Hood
Forge: Under the HoodForge: Under the Hood
Forge: Under the Hood
 

Ähnlich wie Practical Patterns for Developing a Cross-product Cross-version App

Spring Cloud Function — Going Serverless
Spring Cloud Function — Going ServerlessSpring Cloud Function — Going Serverless
Spring Cloud Function — Going ServerlessGlobalLogic Ukraine
 
Cloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan GasimovCloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan GasimovGlobalLogic Ukraine
 
Spring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsugSpring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsugToshiaki Maki
 
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptx
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptxNew features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptx
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptxMuralidharan Deenathayalan
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code lessAnton Novikau
 
Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Bram Adams
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsJim Jeffers
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundryrajdeep
 
Big Bang And Beyond: Migrating Between Server and Cloud
Big Bang And Beyond: Migrating Between Server and CloudBig Bang And Beyond: Migrating Between Server and Cloud
Big Bang And Beyond: Migrating Between Server and CloudAtlassian
 
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1Rodolfo Finochietti
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyMark Proctor
 
내꺼내꺼
내꺼내꺼내꺼내꺼
내꺼내꺼misty915
 
Dropwizard Introduction
Dropwizard IntroductionDropwizard Introduction
Dropwizard IntroductionAnthony Chen
 
Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Rafał Leszko
 
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Rafał Leszko
 
AUG NYC - Atlassian Server Updates
AUG NYC - Atlassian Server UpdatesAUG NYC - Atlassian Server Updates
AUG NYC - Atlassian Server UpdatesAUGNYC
 
Project Presentation on Advance Java
Project Presentation on Advance JavaProject Presentation on Advance Java
Project Presentation on Advance JavaVikas Goyal
 
Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Matt Raible
 

Ähnlich wie Practical Patterns for Developing a Cross-product Cross-version App (20)

Spring Cloud Function — Going Serverless
Spring Cloud Function — Going ServerlessSpring Cloud Function — Going Serverless
Spring Cloud Function — Going Serverless
 
Cloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan GasimovCloud Native Serverless Java — Orkhan Gasimov
Cloud Native Serverless Java — Orkhan Gasimov
 
Spring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsugSpring Cloud Function & Project riff #jsug
Spring Cloud Function & Project riff #jsug
 
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptx
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptxNew features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptx
New features of Minimal APIs in .NET 7 -Muralidharan Deenathayalan.pptx
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 
Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!Modern Release Engineering in a Nutshell - Why Researchers should Care!
Modern Release Engineering in a Nutshell - Why Researchers should Care!
 
Building Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in RailsBuilding Mobile Friendly APIs in Rails
Building Mobile Friendly APIs in Rails
 
Play Support in Cloud Foundry
Play Support in Cloud FoundryPlay Support in Cloud Foundry
Play Support in Cloud Foundry
 
Big Bang And Beyond: Migrating Between Server and Cloud
Big Bang And Beyond: Migrating Between Server and CloudBig Bang And Beyond: Migrating Between Server and Cloud
Big Bang And Beyond: Migrating Between Server and Cloud
 
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1
Que hay de nuevo en Visual Studio 2013 y ASP.NET 5.1
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
 
내꺼내꺼
내꺼내꺼내꺼내꺼
내꺼내꺼
 
Dropwizard Introduction
Dropwizard IntroductionDropwizard Introduction
Dropwizard Introduction
 
Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016Continuous Delivery - Devoxx Morocco 2016
Continuous Delivery - Devoxx Morocco 2016
 
Scala at Netflix
Scala at NetflixScala at Netflix
Scala at Netflix
 
Griffon Presentation
Griffon PresentationGriffon Presentation
Griffon Presentation
 
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
Continuous Delivery - Voxxed Days Thessaloniki 21.10.2016
 
AUG NYC - Atlassian Server Updates
AUG NYC - Atlassian Server UpdatesAUG NYC - Atlassian Server Updates
AUG NYC - Atlassian Server Updates
 
Project Presentation on Advance Java
Project Presentation on Advance JavaProject Presentation on Advance Java
Project Presentation on Advance Java
 
Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019Get Hip with JHipster - GIDS 2019
Get Hip with JHipster - GIDS 2019
 

Mehr von Atlassian

International Women's Day 2020
International Women's Day 2020International Women's Day 2020
International Women's Day 2020Atlassian
 
10 emerging trends that will unbreak your workplace in 2020
10 emerging trends that will unbreak your workplace in 202010 emerging trends that will unbreak your workplace in 2020
10 emerging trends that will unbreak your workplace in 2020Atlassian
 
Forge App Showcase
Forge App ShowcaseForge App Showcase
Forge App ShowcaseAtlassian
 
Let's Build an Editor Macro with Forge UI
Let's Build an Editor Macro with Forge UILet's Build an Editor Macro with Forge UI
Let's Build an Editor Macro with Forge UIAtlassian
 
Forge UI: A New Way to Customize the Atlassian User Experience
Forge UI: A New Way to Customize the Atlassian User ExperienceForge UI: A New Way to Customize the Atlassian User Experience
Forge UI: A New Way to Customize the Atlassian User ExperienceAtlassian
 
Observability and Troubleshooting in Forge
Observability and Troubleshooting in ForgeObservability and Troubleshooting in Forge
Observability and Troubleshooting in ForgeAtlassian
 
Trusted by Default: The Forge Security & Privacy Model
Trusted by Default: The Forge Security & Privacy ModelTrusted by Default: The Forge Security & Privacy Model
Trusted by Default: The Forge Security & Privacy ModelAtlassian
 
Designing Forge UI: A Story of Designing an App UI System
Designing Forge UI: A Story of Designing an App UI SystemDesigning Forge UI: A Story of Designing an App UI System
Designing Forge UI: A Story of Designing an App UI SystemAtlassian
 
Design Your Next App with the Atlassian Vendor Sketch Plugin
Design Your Next App with the Atlassian Vendor Sketch PluginDesign Your Next App with the Atlassian Vendor Sketch Plugin
Design Your Next App with the Atlassian Vendor Sketch PluginAtlassian
 
Tear Up Your Roadmap and Get Out of the Building
Tear Up Your Roadmap and Get Out of the BuildingTear Up Your Roadmap and Get Out of the Building
Tear Up Your Roadmap and Get Out of the BuildingAtlassian
 
Nailing Measurement: a Framework for Measuring Metrics that Matter
Nailing Measurement: a Framework for Measuring Metrics that MatterNailing Measurement: a Framework for Measuring Metrics that Matter
Nailing Measurement: a Framework for Measuring Metrics that MatterAtlassian
 
Building Apps With Color Blind Users in Mind
Building Apps With Color Blind Users in MindBuilding Apps With Color Blind Users in Mind
Building Apps With Color Blind Users in MindAtlassian
 
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...Atlassian
 
Beyond Diversity: A Guide to Building Balanced Teams
Beyond Diversity: A Guide to Building Balanced TeamsBeyond Diversity: A Guide to Building Balanced Teams
Beyond Diversity: A Guide to Building Balanced TeamsAtlassian
 
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed Team
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed TeamThe Road(map) to Las Vegas - The Story of an Emerging Self-Managed Team
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed TeamAtlassian
 
Building Apps With Enterprise in Mind
Building Apps With Enterprise in MindBuilding Apps With Enterprise in Mind
Building Apps With Enterprise in MindAtlassian
 
Shipping With Velocity and Confidence Using Feature Flags
Shipping With Velocity and Confidence Using Feature FlagsShipping With Velocity and Confidence Using Feature Flags
Shipping With Velocity and Confidence Using Feature FlagsAtlassian
 
Build With Heart and Balance, Remote Work Edition
Build With Heart and Balance, Remote Work EditionBuild With Heart and Balance, Remote Work Edition
Build With Heart and Balance, Remote Work EditionAtlassian
 
How to Grow an Atlassian App Worthy of Top Vendor Status
How to Grow an Atlassian App Worthy of Top Vendor StatusHow to Grow an Atlassian App Worthy of Top Vendor Status
How to Grow an Atlassian App Worthy of Top Vendor StatusAtlassian
 
Monitoring As Code: How to Integrate App Monitoring Into Your Developer Cycle
Monitoring As Code: How to Integrate App Monitoring Into Your Developer CycleMonitoring As Code: How to Integrate App Monitoring Into Your Developer Cycle
Monitoring As Code: How to Integrate App Monitoring Into Your Developer CycleAtlassian
 

Mehr von Atlassian (20)

International Women's Day 2020
International Women's Day 2020International Women's Day 2020
International Women's Day 2020
 
10 emerging trends that will unbreak your workplace in 2020
10 emerging trends that will unbreak your workplace in 202010 emerging trends that will unbreak your workplace in 2020
10 emerging trends that will unbreak your workplace in 2020
 
Forge App Showcase
Forge App ShowcaseForge App Showcase
Forge App Showcase
 
Let's Build an Editor Macro with Forge UI
Let's Build an Editor Macro with Forge UILet's Build an Editor Macro with Forge UI
Let's Build an Editor Macro with Forge UI
 
Forge UI: A New Way to Customize the Atlassian User Experience
Forge UI: A New Way to Customize the Atlassian User ExperienceForge UI: A New Way to Customize the Atlassian User Experience
Forge UI: A New Way to Customize the Atlassian User Experience
 
Observability and Troubleshooting in Forge
Observability and Troubleshooting in ForgeObservability and Troubleshooting in Forge
Observability and Troubleshooting in Forge
 
Trusted by Default: The Forge Security & Privacy Model
Trusted by Default: The Forge Security & Privacy ModelTrusted by Default: The Forge Security & Privacy Model
Trusted by Default: The Forge Security & Privacy Model
 
Designing Forge UI: A Story of Designing an App UI System
Designing Forge UI: A Story of Designing an App UI SystemDesigning Forge UI: A Story of Designing an App UI System
Designing Forge UI: A Story of Designing an App UI System
 
Design Your Next App with the Atlassian Vendor Sketch Plugin
Design Your Next App with the Atlassian Vendor Sketch PluginDesign Your Next App with the Atlassian Vendor Sketch Plugin
Design Your Next App with the Atlassian Vendor Sketch Plugin
 
Tear Up Your Roadmap and Get Out of the Building
Tear Up Your Roadmap and Get Out of the BuildingTear Up Your Roadmap and Get Out of the Building
Tear Up Your Roadmap and Get Out of the Building
 
Nailing Measurement: a Framework for Measuring Metrics that Matter
Nailing Measurement: a Framework for Measuring Metrics that MatterNailing Measurement: a Framework for Measuring Metrics that Matter
Nailing Measurement: a Framework for Measuring Metrics that Matter
 
Building Apps With Color Blind Users in Mind
Building Apps With Color Blind Users in MindBuilding Apps With Color Blind Users in Mind
Building Apps With Color Blind Users in Mind
 
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...
Creating Inclusive Experiences: Balancing Personality and Accessibility in UX...
 
Beyond Diversity: A Guide to Building Balanced Teams
Beyond Diversity: A Guide to Building Balanced TeamsBeyond Diversity: A Guide to Building Balanced Teams
Beyond Diversity: A Guide to Building Balanced Teams
 
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed Team
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed TeamThe Road(map) to Las Vegas - The Story of an Emerging Self-Managed Team
The Road(map) to Las Vegas - The Story of an Emerging Self-Managed Team
 
Building Apps With Enterprise in Mind
Building Apps With Enterprise in MindBuilding Apps With Enterprise in Mind
Building Apps With Enterprise in Mind
 
Shipping With Velocity and Confidence Using Feature Flags
Shipping With Velocity and Confidence Using Feature FlagsShipping With Velocity and Confidence Using Feature Flags
Shipping With Velocity and Confidence Using Feature Flags
 
Build With Heart and Balance, Remote Work Edition
Build With Heart and Balance, Remote Work EditionBuild With Heart and Balance, Remote Work Edition
Build With Heart and Balance, Remote Work Edition
 
How to Grow an Atlassian App Worthy of Top Vendor Status
How to Grow an Atlassian App Worthy of Top Vendor StatusHow to Grow an Atlassian App Worthy of Top Vendor Status
How to Grow an Atlassian App Worthy of Top Vendor Status
 
Monitoring As Code: How to Integrate App Monitoring Into Your Developer Cycle
Monitoring As Code: How to Integrate App Monitoring Into Your Developer CycleMonitoring As Code: How to Integrate App Monitoring Into Your Developer Cycle
Monitoring As Code: How to Integrate App Monitoring Into Your Developer Cycle
 

Kürzlich hochgeladen

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 

Kürzlich hochgeladen (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 

Practical Patterns for Developing a Cross-product Cross-version App

  • 1. VICTORIA SKALRUD | SENIOR DEVELOPMENT TL | ATLASSIAN Practical Patterns for Developing a Cross- product Cross-version App
  • 2. Lessons from working on the Atlassian Troubleshooting &Support Tools (ATST)
  • 7. Developing cross version Why developing to support multiple versions of a product is a good idea
  • 8. Why developing to support multiple versions of a product is a good idea
  • 9. Why developing to support multiple versions of a product is a good idea
  • 10. Platform version (aka Major release) Contain features and API breaking changes. Feature version(aka Minor release) Contain features but no API breaking changes Bugfix version Primarily intended to fix problems without altering behaviour Versioning @ Atlassian Server
  • 11. Platform version (aka Major release) Contain features and API breaking changes. Feature version(aka Minor release) Contain features but no API breaking changes Bugfix version Primarily intended to fix problems without altering behaviour Versioning @ Atlassian Server
  • 12. Platform version (aka Major release) Contain features and API breaking changes. Feature version(aka Minor release) Contains features but no API breaking changes Bugfix version Primarily intended to fix problems without altering behaviour Versioning @ Atlassian Server
  • 13. Platform version (aka Major release) Contain features and API breaking changes. Feature version(aka Minor release) Contain features but no API breaking changes Bugfix version Primarily intended to fix problems without altering behaviour. Versioning @ Atlassian Server
  • 14.
  • 15. CHALLENGE #1 I WANT TO INTRODUCE A FEATURE THAT WILL ONLY SHOW FOR LATER HOST PRODUCT VERSIONS
  • 16. interface Feature { boolean shouldDisplay(); } Limiting features to version Feature Flags Web resource conditions
  • 17. interface Feature { boolean shouldDisplay(); } public class MyNewFeature implements Feature { private static int MIN_SUPPORTED_VERSION = 5; boolean shouldDisplay() { return getCurrentVersionOfHostProduct() >= MIN_SUPPORTED_VERSION && isEnabled("myNewFeature"); } } // In another class somewhere // Gets current version of the host product // - does not rely on version plugin was compiled with getCurrentVersionOfHostProduct() Limiting features to version Feature Flags Web resource conditions
  • 18. // In Confluence, in atlassian-plugin.xml <condition class="com.atlassian.confluence.plugin.descriptor.web.conditions.BuildNumberCondition"> <param name="minBuildNumber">8200</param> </condition> Limiting features to version Feature Flags Web resource conditions
  • 19. // In Confluence, in atlassian-plugin.xml <condition class="com.atlassian.confluence.plugin.descriptor.web.conditions.BuildNumberCondition"> <param name="minBuildNumber">8200</param> </condition> // In Bitbucket, in atlassian-plugin.xml <condition class=“com.atlassian.bitbucket.web.conditions.IsApplicationVersionCondition"> <param name=“operator">gte</param> <param name=“version”>6.4</param> </condition> Limiting features to version Web resource conditions Feature Flags
  • 20.
  • 21. CHALLENGE #2 I WANT TO WRITE MY FEATURE TO BE RESILIENT ACROSS API CHANGES
  • 22. public interface JiraApi { // doing useful stuff // @since 6.4 String someMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 23. public interface JiraApi { // doing useful stuff // @since 6.4 String someMethod(); } public void myFunction(){ jiraApi.someMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 24. // Newer version of Jira public interface JiraApi { @deprecated String someMethod(); String shinyNewUsefulMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 25. // Newer version of Jira public interface JiraApi { @deprecated String someMethod(); String shinyNewUsefulMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 26. // Even newer version of Jira public interface JiraApi { String someMethod(); String shinyNewUsefulMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 27. // Even newer version of Jira public interface JiraApi { String someMethod(); String shinyNewUsefulMethod(); } // Will only work in newer versions public void myFunction(){ jiraApi.shinyNewUsefulMethod(); } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 28. // Even newer version of Jira public interface JiraApi { String someMethod(); String shinyNewUsefulMethod(); } // Do not fear failure but rather fear not trying public void myFunction() { try { jiraApi.shinyNewUsefulMethod(); } catch (final NoSuchMethodError nsme) { // fallback } } Version Resilience Jira API Using the API Ch Ch Change Trouble in paradise Try
  • 29. You can build a bridge! BETTER WAY
  • 30. 1 Create a clear separation of concerns Building bridges Your app that does cool things and accesses API
  • 31. 1 Create a clear separation of concerns Building bridges Your business logic COM.MYSTUFF
  • 32. 1 Create a clear separation of concerns Building bridges Your business logic COM.MYSTUFF Things you need that you get via API COM.MYSTUFF.ACCESS
  • 33. 1 Create a clear separation of concerns Building bridges 2 Define your bridge blueprint
  • 34. 1 Create a clear separation of concerns Building bridges 2 Define your bridge blueprint public interface SearchServiceBridge { Collection<Issue> search(Query query) throws PlatformException; }
  • 35. 1 Create a clear separation of concerns Building bridges 2 Define your bridge blueprint 3 Build out your bridges
  • 36. 1 Create a clear separation of concerns Building bridges 2 Define your bridge blueprint 3 Build out your bridges
  • 37. 1 Create a clear separation of concerns Building bridges 2 Define your bridge blueprint 3 Build out your bridges
  • 38. 1 Create a clear separation of concerns Building bridges @SupportedVersions(minimumInclusive = "7.4.0") final class SearchServiceBridge74 implements SearchServiceBridge { public Collection<Issue> search(Query query){ // Access the Jira APIs here - 7.4 specific code } } @SupportedVersions(minimumInclusive = "7.12.0") final class SearchServiceBridge712 implements SearchServiceBridge { public Collection<Issue> search(Query query){ // Access the Jira APIs here - 7.12 specific code } } 2 Define your bridge blueprint 3 Build out your bridges
  • 39. Building bridges 1 Create a clear separation of concerns 2 Define your bridge blueprint 3 Build out your bridges 4 Build a way to select which bridge should be used
  • 40. Building bridges @Retention(RetentionPolicy.RUNTIME) public @interface SupportedVersions { String minimumInclusive() default “0.0.0"; String maximumExclusive() default "99999.99999.99999"; } Versioning Manager Bridges Using the bridge
  • 41. Building bridges final class BridgeManager<Bridge> { public Optional<Bridge> getSupportedBridge(Version version) { return bridgeBeans.stream() .filter(bridgeBean -> isSupported(bridgeBean, version)).findFirst(); } } Versioning Manager Bridges Using the bridge
  • 42. Building bridges final class BridgeManager<Bridge> { public Optional<Bridge> getSupportedBridge(Version version) { return bridgeBeans.stream() .filter(bridgeBean -> isSupported(bridgeBean, version)).findFirst(); } private boolean isSupported(Bridge bridgeBean, Version version) { return Stream.of(bridgeBean.getClass() .getAnnotation(SUPPORTED_VERSIONS_ANNOTATION)) .anyMatch(annotation -> isSupported(annotation, version)); } private boolean isSupported(SupportedVersions supportedVersions, Version version) final Version minimumInclusive = parse(supportedVersions.minimumInclusive()); final Version maximumExclusive = parse(supportedVersions.maximumExclusive()); return minimumInclusive.isLessThanOrEqualTo(version) && maximumExclusive.isGreaterThan(version); } } Versioning Manager Bridges Using the bridge
  • 43. Building bridges public interface SearchServiceBridge { Collection<Issue> search(Query query) throws PlatformException; } Versions Manager Bridges Using the bridge
  • 44. Building bridges public interface SearchServiceBridge { Collection<Issue> search(Query query) throws PlatformException; } @ExportAsService({SearchServiceBridge.class}) @Named("com.atlassian.bridges.search.SearchServiceBridge74") @SupportedVersions(minimumInclusive = "7.4.0", maximumExclusive = “7.12.0") final class SearchServiceBridge74 implements SearchServiceBridge { @Override public Collection<Issue> search(Query query) throws PlatformException { … } } Versions Manager Bridges Using the bridge
  • 45. Building bridges public interface SearchServiceBridge { Collection<Issue> search(Query query) throws PlatformException; } @ExportAsService({SearchServiceBridge.class}) @Named("com.atlassian.bridges.search.SearchServiceBridge74") @SupportedVersions(minimumInclusive = "7.4.0", maximumExclusive = “7.12.0") final class SearchServiceBridge74 implements SearchServiceBridge { @Override public Collection<Issue> search(Query query) throws PlatformException { … } } @ExportAsService({SearchServiceBridge.class}) @Named("com.atlassian.bridges.search.SearchServiceBridge712") @SupportedVersions(minimumInclusive = "7.12.0", maximumExclusive = "8.0") final class SearchServiceBridge712 implements SearchServiceBridge { @Override public Collection<Issue> search(Query query) throws PlatformException { … } } Versions Manager Bridges Using the bridge
  • 46. Building bridges Versions Manager public class MyCode { Supplier<SearchServiceBridge> searchService; void doMyThing() { searchService.get().search(query); } } Bridges Using the bridge
  • 48. Don’t depend on core/ internal if you can help it
  • 50. ATST Product & Version supported matrix
  • 54. Introducing a feature 1 Introduce required API in the ATST api module
  • 55. Introducing a feature 1 Introduce required API in the ATST api module 2 If implementation is shared, add it to ATST common module
  • 56. Introducing a feature 1 Introduce required API in the ATST api module 2 If implementation is shared, add it to ATST common module 3 If implementation is product specific, add it to the corresponding product module
  • 57. Introducing a feature 1 Introduce required API in the ATST api module 2 If implementation is shared, add it to ATST common module 3 If implementation is product specific, add it to the corresponding product module 4 If a feature is not required for a particular product, include a NoOp implementation
  • 58. Tips for cross product development 1 Use of SAL (Shared Access Layer) APIs to simplify development
  • 59. Tips for cross product development 1 <dependency> <groupId>com.atlassian.sal</groupId> <artifactId>sal-api</artifactId> <version>2.0.17</version> <!-- Uses the application's SAL instead of bundling it into the plugin. --> <scope>provided</scope> </dependency> Use of SAL (Shared Access Layer) APIs to simplify development
  • 60. Tips for cross product development 1 Use of SAL (Shared Access Layer) APIs to simplify development 2 Use provided scope to use the host product’s libraries instead of bundling own
  • 62. Developing for Data Centre 1 Keep the concepts of ‘licenced for data-center’, ‘clustering available’ and ‘clustering active’ as separate and do not mix
  • 63. Developing for Data Centre Keep the concepts of ‘licenced for data-center’, ‘clustering available’ and ‘clustering active’ as separate and do not mix 2 Every time you introduce a new feature, consider if this feature needs to operate per cluster or per node 1
  • 64. Developing for Data Centre 1 Keep the concepts of ‘licenced for data-center’, ‘clustering available’ and ‘clustering active’ as separate and do not mix 2 Every time you introduce a new feature, consider if this feature needs to operate per cluster or per node 3 Take a look at the Atlassian documentation for developing data centre applications
  • 65. Thank you! VICTORIA SKALRUD | SENIOR DEVELOPMENT TL | ATLASSIAN