(Originally posted here)
Recently, I’ve been digging deeper into Atlassian Spring Scanner and how to import/export services because I have a program that I wanted to split into several independent modules. Long story short: it’s complicated and gets worse when you have multiple elements that you want to share between apps.
This is how I came across this page, where Atlassian itself recommends using the Java Based Spring Configuration, as also does Spring.
The opportunity to try this approach came when I had to refactor a legacy project that used mixed XML annotations together with static ContainerManager.getComponent() imports. A colleague started the transition to Atlassian Spring Scanner, but there were some problems:
- Not every imported service was properly annotated with @ComponentImport, however the app could still be packaged, and these errors remained unnoticed.
- Some classes (such as com.atlassian.confluence.content.render.xhtml.Renderer) could not be imported this way. The reason for this is still unknown.
At this point, I followed the Spring Java configuration - converting from Spring Scanner page and transformed the old app to its new configuration schema. And these are the conclusions of my experience:
Pros
- Missing imports will trigger a warning in the IDE: For me, this is key, you don’t have to wait until you deploy your app to know that you forgot to declare an external service. You won’t get that with @ComponentImport.
- Detect missing items on install when annotated as a Spring Bean: My advice is to annotate every class declared in your atlassian-plugin.xml file as a @Component, so that when the app is uploaded to your server, any service that can’t be found will throw an exception.
- One place for Importing/Exporting services: everything related to Beans is located in one place, so the business logic is kept separated, and if something is missing you know exactly where to look. Unfortunately, services that are no longer needed don’t show up as unused, so this is similar to having a ComponentImporter class.
- Since it is a standard Spring schema, there is much more documentation and support from a larger community.
Cons
- Classes declared in XML, like servlet-filter modules, need to be annotated with @Component in order to get warnings. However, in my opinion, this makes sense since they are really Spring Beans.
- Extra class(es) to declare Beans import/exports.
- If you are using Arquillian to do integration testing, this module still needs to use the Atlassian Spring Scanner schema.
- Had to declare some elements in the POM section, like com.atlassian.plugin.web.baseconditions, the reason remains unknown.
Finally, I also checked how long it takes to install the application with both schemas, and, at least for this project, I didn’t find any differences.