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: