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.
@SpringBootApplicationis equivalent to@Configuration,@EnableAutoConfigurationand@ComponentScantogether.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
Environmentabstraction @ConfigurationPropertieswith 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
@Componentand@Configurationwhen 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
piDecimalscache that matches theiargument - if an entry is found,
- content retrieved from the cache is returned to the caller and
computePiDecimalis not invoked
- content retrieved from the cache is returned to the caller and
- else
- Method is invoked and
piDecimalscache 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.
