Part 1: Basic set up
Steps inspired by spring boot getting started guide.
Add some basic dependencies and Java file to return Hello world!
Part 2: Using spring boot
Typical project layout
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
Where Application.java
declares the main
method, being the app’s entry point, like so:
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Reference: Locating the Main Application Class.
Configuration
Favour Java-based configuration classes over XML.
Note that you can mix and match XML and Classes. Loading XML-based config via
@ImportResource
.Reference: Configuration Classes.
Gradually replace the auto-configuration with yours
It could be handy to start with auto-configuration, while seeing which config is applied using --debug
when starting the app like so:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
You would need to use the @EnableAutoConfiguration
or @SpringBootApplication
on your @Configuration
class.
@SpringBootApplication
is equivalent to@Configuration
,@EnableAutoConfiguration
and@ComponentScan
together.Reference: Auto-configuration.
Developer tools
Check the spring-boot-devtools
module!
It provides useful things like automatic restart,
LiveReload,
and Remote tools.
Reference: Developer Tools.
Part 3: Spring boot features
Application Events and Listeners
Events are sent in the following order as the application runs:
Event | When |
---|---|
ApplicationStartingEvent |
Start of a run, before any processing except registration of listeners and initialisers |
ApplicationEnvironmentPreparedEvent |
When Environment to use is known but before the context is created |
ApplicationPreparedEvent |
After bean definitions are loaded but before refresh is started |
ApplicationReadyEvent |
After refresh + related callbacks have been processed = App ready for service requests |
ApplicationFailedEvent |
Startup exception has been raised |
Be careful when using a hierarchy of SpringApplication
instances, as a listener may receive multiple instances of the same type of application event.
Implement ApplicationContextAware
to inject context and compare it with the event’s context.
If the listener is a @Bean
, use @Autowired
.
Reference: Application Events and Listeners.
Web environment
Call setWebEnvironment(false)
when using SpringApplication
within a JUnit test.
Reference: Web Environment.
Externalised configuration
Run the same application code no matter what the environment!
Pass your configuration with:
- Properties files
- YAML files
- Environment variables
- Command-line arguments
Property values can then be injected into beans using @Value
accessed via:
- Spring’s
Environment
abstraction @ConfigurationProperties
with structured objects bindings
Properties are considered in a specific order, go have a look at it.
Reference: Externalized configuration.
Relaxed binding
Interestingly, there is no need for an exact match between Environment
and @ConfigurationProperties
beans property names.
Example:
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
To pass the firstName
property you can use:
Property | Format | Usage |
---|---|---|
person.firstName |
Camel case | Standard |
person.first-name |
Kebab case | Recommended in .properties and .yml files |
person.first_name |
Underscore notation | Alternative format in .properties and .yml files |
PERSON_FIRSTNAME |
Upper case | Environment variables |
Reference: Relaxed binding.
Profiles
Segregate parts of your application to make them available only in certain environments.
Applies to
@Component
and@Configuration
when marked with@Profile
.
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
Then, specify which profiles are active using spring.profiles.active=dev,hsqldb
or on the command line with --spring.profiles.active=dev,hsqldb
.
Profiles also allow per-profile configuration files.
Reference: Profiles.
Developing web applications
- Spring MVC which covers:
- Spring WebFlux for async which covers:
- Auto-config
- HTTP Codecs with HttpMessageReaders and HttpMessageWriters
- Static content
- Template engines
- Error Handling, including custom error pages
- JAX-RS and Jersey
- Embedded Servlet Container Support
Reference: Developing web applications.
More on Spring webflux
Security
Defaults to basic auth when enabled. OAuth2 also supported OOTB.
Refer to the Spring Security Reference.
Reference: Security
Data stores
Depending on your needs, refer to SQL databases and NoSQL databases (which includes SolR and ElasticSearch) documentations where you will find details about common data stores.
Caching
Refer to Spring documentation for details.
Example:
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component;
@Component
public class MathService {
@Cacheable("piDecimals")
public int computePiDecimal(int i) {
// ...
}
}
Here, before invoking computePiDecimal
,
- abstraction looks for an entry in
piDecimals
cache that matches thei
argument - if an entry is found,
- content retrieved from the cache is returned to the caller and
computePiDecimal
is not invoked
- content retrieved from the cache is returned to the caller and
- else
- Method is invoked and
piDecimals
cache is updated before returning the value to the caller.
- Method is invoked and
Reference: Caching.
Cache providers
Many cache providers are supported, including Couchbase and Redis. See the list of supported cache providers.
Disabling caching
You may want to disable caching altogether in certain environments even if @EnableCaching
is present in configuration.
A handy way of doing it would be to force the none
cache type:
spring.cache.type=none
Messaging
Support for both JMS and AMPQ.
- JMS (Java Message Service)
- ActiveMQ
- Artemis
- AMQP (Advanced Message Queueing Protocol)
- RabbitMQ
- Apache Kafka
Reference: Messaging.
REST clients
RestTemplate
RestTemplate
is a convenient way of handling your calls to other REST services.
Example:
@Service
public class MyService {
private final RestTemplate restTemplate;
public MyBean(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder.build();
}
public Details someRestCall(String name) {
return this.restTemplate.getForObject("/{name}/details", Details.class, name);
}
}
Reference: Calling REST Services with RestTemplate
WebClient
When in use with WebFlux. WebClient
is fully reactive.
Example:
@Service
public class MyService {
private final WebClient webClient;
public MyBean(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("http://example.org").build();
}
public Mono<Details> someRestCall(String name) {
return this.webClient.get().url("/{name}/details", name)
.retrieve().bodyToMono(Details.class);
}
}
Reference: Calling REST Services with WebClient.
Testing
Reference: Testing
WebSockets
Accessible through the spring-boot-starter-websocket
module.
Documentation on spring framework websockets
MQTT is available through sprint integration
Reference: Websockets.