Last updatedApr 30, 2020

Rate this page:

Background

Server app developers have traditionally had several ways to configure their app components:

  • declare them in atlassian-plugin.xml via <component> and <component-import> elements,
  • declare them in Spring XML files via the <beans> and <osgi> XML namespaces, or
  • annotate them with @Component and Spring Scanner annotations such as @ExportAsService, and rely on the Spring Scanner runtime to generate the Spring bean definitions.

There is now a fourth way, namely Spring Java configuration, that solves many of the shortcomings of the approaches listed above:

  • uses code instead of XML, providing more power and better tooling
  • uses a simpler, more reliable toolchain requiring little experience with Atlassian products
  • allows components to be created conditionally
  • keeps business logic free of dependency injection concerns

Supported products

Spring Java configuration is supported by all Atlassian Server products that have not yet reached their end-of-life.

How it works (high-level)

Here's an overview of how to use Spring Java configuration in your app (full details are linked below):

  1. Add dependencies on a few standard Spring & OSGi libraries and (optionally) a small Atlassian helper library.
  2. Add three packages to your Import-Package instructions (done automatically by the helper library).
  3. Create one or more classes annotated with Spring’s @Configuration annotation.
  4. Populate your configuration classes with @Bean methods, one for every component in your app. If you wish, use our helper library to more easily write the @Bean methods that import or export OSGi services, or that define new module types.
  5. Register your @Configuration classes as beans in your Spring XML file (create one if necessary).
  6. If converting an existing plugin, remove all the XML and annotations you had before.

Example

Here’s what a configuration class might look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Configuration
public class MySpringBeans {

    // An app component
    @Bean
    public FooService fooService() {
        return new FooServiceImpl();
    }
    
    // The above component, exported to OSGi
    // The "exportOsgiService" method comes from our helper library
    @Bean
    public FactoryBean<ServiceRegistration> exportFooService(FooService fooService) {
        return exportOsgiService(fooService, ExportOptions.as(FooService.class));
    }
    
    // A component imported from OSGi
    // The "importOsgiService" method comes from our helper library
    @Bean
    public ApplicationProperties applicationProperties() {
        return importOsgiService(ApplicationProperties.class);
    }
    
    // A component imported from OSGi, with an LDAP filter applied
    // Only a service with the "foo" property set to "bar" will be imported
    // Again, the "importOsgiService" method comes from our helper library (0.2.0 and later)
    @Bean
    public ApplicationProperties applicationProperties() {
        String ldapFilter = "(foo=bar)";
        return importOsgiService(ApplicationProperties.class, ImportOptions.defaultOptions().withFilter(ldapFilter));
    }
}

Detailed instructions

Useful links

Rate this page: