This page describes how to convert a plugin from Atlassian Spring Scanner to Spring Java configuration.
spring-scanner
in their name.SpringBeans
, in a new package somewhere under
src/main/java
, for example com.example.myplugin.spring
.@org.springframework.context.annotation.Configuration
.You will currently have a Spring XML file in src/main/resources/META-INF/spring
(it could be called anything ending in
.xml). Modify this file as follows:
atlassian-scanner
namespace from the root element.<atlassian-scanner:scan-indexes/>
element.@Configuration
classes.Replace all usages of Spring Scanner’s @ComponentImport
annotation with methods like this in your Spring config class
(one such method for each service you are importing):
1 2@Bean public FooService fooService() { return importOsgiService(FooService.class); }
… where the importOsgiService
method is statically imported from com.atlassian.plugins.osgi.javaconfig.OsgiServices
.
Replace each usage of Spring Scanner’s @ExportAsService
annotation with a pair of methods like this in your Spring
config class:
1 2@Bean public BarService barService() { // TODO instantiate and return your BarService implementation } @SuppressWarnings("rawtypes") // ServiceRegistration is used as a raw type in the exportOsgiService method @Bean public FactoryBean<ServiceRegistration> exportBarService( final BarService barService) { ExportOptions options = ExportOptions.as(MyPluginComponent.class).withProperty("some_key", "some_value"); // or whatever other properties you want (including none) return exportOsgiService(barService, options); }
… where exportOsgiService
and ExportOptions
are imported via:
1 2import com.atlassian.plugins.osgi.javaconfig.ExportOptions; import static com.atlassian.plugins.osgi.javaconfig.OsgiServices.exportOsgiService;
You can also remove any @Named
or @Component
annotation from the class that implements BarService
(since you’re
now instantiating it programmatically).
Replace each usage of Spring Scanner’s @ModuleType
annotation with a pair of methods like this in your Spring config
class:
1 2@Bean public ListableModuleDescriptorFactory myModuleDescriptorFactory() { return new MyModuleDescriptorFactory(); } @SuppressWarnings("rawtypes") // ServiceRegistration is used as a raw type in the exportAsModuleType method @Bean public FactoryBean<ServiceRegistration> exportMyModuleType( final ListableModuleDescriptorFactory moduleDescriptorFactory) { return exportAsModuleType(moduleDescriptorFactory); }
… where the exportAsModuleType
method is statically imported from com.atlassian.plugins.osgi.javaconfig.OsgiServices
.
If the Spring Scanner plugin configuration that you deleted from your POM contained a scannedDependencies
element,
then it’s highly likely that Spring Scanner was creating beans for (and/or exporting to OSGi) various classes within
those dependencies. You will need to add further @Bean
methods to your new config class to ensure that you are still
creating and/or exporting those beans. You might want to check what Spring beans previously existed in your plugin at
runtime (e.g. using the QuickReload plugin’s REST API), and check them again after the conversion, to be sure you
haven’t missed any.
One of the advantages of Spring Java config is that many beans are created explicitly via their constructor, for example
new FooServiceImpl(…)
. Such classes no longer need any of the following dependency injection annotations:
@Autowired
(from spring-beans
)@Component
(from spring-context
)@Inject
(from javax.inject
)@Named
(from javax.inject
)If your @Configuration
class has become too big or messy, you can easily split it up as follows:
@Configuration
classes, according to whatever categorisation makes
sense (for example put all your web-related beans into MyWebBeans.class
, or split up the beans by feature).@Import
annotation that lists these subsidiary config classes, for
example:1 2@Configuration @Import({ MyPersistenceBeans.class, MyServiceBeans.class, MyWebBeans.class }) public class MainSpringConfig {}
Rate this page: