Spring Usage Guidelines

These are guidelines related to the development of Confluence. The guidelines mainly apply to Atlassian employees, but reading them should provide insight for third-party plugin developers as well, so we decided to make them public.

All new Spring component code should follow these guidelines. If you come across existing code that doesn't follow them, consider refactoring it to do so.

For an overview of how Spring is used in Confluence, see Spring IoC in Confluence.

General Rules

  • Autowiring should only be used for transient, programatically constructed objects like actions and plugins. Never autowire anything that's defined in a config file.
  • For singleton components, prefer constructor-based injection with final fields for dependencies.
    • Always specify indexes for constructor arguments.
    • If you have too many components to fit comfortably in a constructor, that's a sign the design is broken.
  • If a component is rarely used (i.e. the upgrade manager), consider giving it prototype scope instead of singleton.
  • Avoid circular dependencies. If you see a circular dependency, ask yourself:
    • Can this problem be solved using events?
    • Can this problem be solved by having one party register a callback?

Why use explicit constructor injection?

  • It fails fast. If a dependency is added, removed, missing, renamed, misspelled or the wrong type, you find out with a clear error message during system startup not a NullPointerException much later.
  • With the amount of components in our Spring context, the introspection required to perform autowiring (or even to resolve the order of components in a constructor) contributes significantly to the startup time of the application.

Transaction Management

  • Transactions should be wrapped around the manager layer.
  • Use the old-style Spring 1 transaction configuration syntax with explicit proxies - the Spring 2 pointcut syntax seems to slow down container startup (and thus test-running) by a factor of ten

Profiling

  • Managers and DAOs should be wrapped by the profiling interceptor
  • If you're wondering whether a bean should be profiled or not, veer towards yes

Notes

Could we use some kind of funky XML Spring extension so we could declare a bean like this and have the extension apply the relevant interceptors?

<bean name="blahManager" class="com.example.BlahManager" atl:txn="defaultManagerTxn" atl:profile="yes"/>
Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport