Skip to content

Spring in Portofino

Alessio Stalla edited this page Sep 25, 2021 · 9 revisions

Portofino 5 includes the Spring dependency injection framework and, from version to version, has integrated Spring progressively more tightly.

Here we document the integration of Spring into Portofino.

Architecture

The following is extracted from PortofinoContextLoaderListener's documentation.

[In Portofino, the Spring application context] is made of 3 layers:

  • Parent context - defines Portofino's own beans and modules. It's created once at application startup and destroyed once at shutdown.
  • User context - defines beans according to the user-provided SpringConfiguration class, if any. Otherwise it's an empty context. This context is reloaded automatically whenever the source code of class annotated with Component, org.springframework.context.annotation.Configuration, @Repository or @Service changes, and it can also be refreshed programmatically, via the refresh() method. Note that such capability is meant to aid development, and NOT as a kind of hotswap for production. Requests will fail during a context reload. In fact, in production it can be deactivated by setting the init parameter reloadContextWhenSourcesChange to false in the deployment descriptor (web.xml).
  • Bridge context - a singleton application context meant to be exposed to outside consumers. It has the user context as a parent and it's created and destroyed only once.

From the above, we learn that:

  • Portofino defines some platform beans in its own context;
  • we, as users, can define additional beans in a user context;
  • both contexts are combined and exposed to the application.

In particular, the "user context" is an optional class (Java or Groovy) named SpringConfiguration in the default package. When written in Groovy, it supports hot reload during development.

Modules

Modules are components of a Portofino application. By themselves, they don't do anything – they only enable capabilities that user code can use. Built-in modules include database persistence, the email subsystem, and Quartz scheduling.

Since Portofino 5, modules are automatically discovered at startup and registered as Spring beans. They can contribute other beans to the context declaring them with the @Bean annotation.

Users can write their own modules if they want to build redistributable components that implement some capability – for example, support for a proprietary database system. The only limitation currently is that modules must be written in Java, or at least compiled ahead of time – they can't be Groovy classes loaded at runtime.

So, in a typical application, it's unnecessary to write a module, as the same result can be obtained more easily by registering beans in the SpringConfiguration class (the user context). We'll want to define a new module only when we desire to package some feature and use it in multiple applications.

Note that modules are activated in an order that Spring computes according to the dependencies among them.

Injection

In actions, modules, and Spring beans (contributed by modules or by the user-defined application context), we can have Spring inject dependencies using the standard @Autowired annotation. Also, these objects can have @PostConstruct and @PreDestroy lifecycle methods, and any other hooks supported by Spring.

Note that Portofino, not Spring, instantiates actions, and then has Spring autowire them. This mechanism does not apply to native JAX-RS resources that are not Portofino ResourceActions. Spring directly instantiates all other beans that are not resource-actions. This shouldn't make any practical difference apart from the fact that, comprehensibly, actions are not beans in the Spring context (they're not singletons anyway).

Using XML Instead

Spring in Portofino is configured using annotations. However, it's possible to use XML alongside the annotations, for example to reuse some legacy context, or to leverage some feature that is more easily expressed in XML. For that, we can add an @ImportResource annotation on the SpringConfiguration class. That's standard Spring practice, it's nothing specific to Portofino. Note, though, that in that case the context won't be reloaded when the XML changes – only the SpringConfiguration class is monitored.

Spring Boot

Traditionally, Portofino has always been distributed as a web application archive (WAR file) to be deployed on a servlet container or application server. However, since Portofino 5.3, we also have the option to build a self-contained service JAR that we can launch from the command line without any external component (apart from the JDK, of course).

TODO

Working With Archetypes

TODO war and service

Clone this wiki locally