Spring Boot helps us build stand-alone, production Spring Applications easily, less configuration then rapidly start new projects.
Features:
- Stand-alone Spring applications
- Embedded Serverlet Container: Tomcat, Jetty or Undertow.
- Support ‘Starter’ POMs to make your Maven configuration easily ways.
- Automatically configure Spring.
- Provide production-ready features such as metrics, health checks and externalized configuration
- No code generation, No requirement for XML configuration
SQL Databases
1. Configure DataSource
Spring Boot supports auto-configured DataSource if you use spring-boot-starter-jdbc
or spring-boot-starter-data-jpa
‘starters’. Details configuration at application.properties file:
spring.datasource.url=jdbc:postgresql://ozenero.com/test spring.datasource.username=user spring.datasource.password=pass
But How to configure 2 or Multi-Datasource?
Steps to do:
– Open application.properties, configure datasource’s info:
#db1 datasource db1.datasource.url=jdbc:postgresql://url1 db1.datasource.username=user1 db1.datasource.password=password1 #db2 datasource db2.datasource.url=jdbc:postgresql://url2 db2.datasource.username=user2 db2.datasource.password=password2
– Mark one of the DataSource with @Primary
:
@Configuration public class DataSourceBeans { @Primary @Bean(name="db1.datasource") @ConfigurationProperties(prefix="db1.datasource") public DataSource db1DataSource(){ return DataSourceBuilder.create().build(); } @Bean(name="db2.datasource") @ConfigurationProperties(prefix="db2.datasource") public DataSource db2DataSource(){ return DataSourceBuilder.create().build(); } }
– Now they are ready to be injected:
... // datasource 1 @Autowired @Qualifier("db1.datasource") DataSource dataSource1; // datasource 2 @Autowired @Qualifier("db2.datasource") DataSource dataSource2;
>>> More details at: How to configure multi Postgres DataSources with Springboot
2. Using JdbcTemplate
Spring’s Jdbc Template is used to access and manipulate databases. Spring Boot provides auto-configuration JdbcTemplate bean. So we can easily inject it via @Autowire
. Or using supported function: getJdbcTemplate()
of Spring’s JdbcDaoSupport class:
... @Repository public class CustomerDaoImpl extends JdbcDaoSupport implements CustomerDao{ @Autowired DataSource dataSource; @PostConstruct private void initialize(){ setDataSource(dataSource); } ... @Override public void insert(Customer cus) { String sql = "INSERT INTO customer " + "(CUST_ID, NAME, AGE) VALUES (?, ?, ?)" getJdbcTemplate().update(sql, new Object[]{ cus.getCustId(), cus.getName(), cus.getAge() }); } ... }
>>> More details at: How to use Spring JDBC Template with Spring Boot for Postgres DataBase
3. Spring JPA and Spring Data
For persistence, SpringBoot provides @Entity
anonation for scanning entities.
... import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="company") public class Company { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; ... }
>>> Example to practice:
– Spring JPA – One to Many Relationship
– Spring JPA – Many to Many relationship
With RestAPIs ->
– SpringBoot + Hibernate Spring JPA One-to-One Association + PostgreSQL | CRUD RestAPIs Post/Get/Put/Delete
– Spring JPA/Hibernate One-to-Many Association + PostgreSQL | SpringBoot CRUD RestAPIs Post/Get/Put/Delete example
4. H2 Database
H2 database has small footprint (smaller than 1.5 MB) with low memory requirements. It supports for multiple schemas and standard SQL, JDBC API. We can use H2 with disk based or in-memory databases.
H2 can be built by following mode:
– Embedded mode (local connections)
– Server mode (remote connections)
– Mixed mode (local and remote connections)
With Embedded Mode, an application uses JDBC to create a H2 database within the same JVM so it’s very fast to exchange data.
How to configure it with SpringBoot?
-> Spring Boot has a built in H2 database, so We just add below dependency:
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency>
>>> More details at: Integrate H2 database with SpringBoot & Spring JPA in Embedded mode
If your project uses H2 database to develop and also enable Spring Security, then when accessing to H2 console path: /h2_console
, an error Access Denied Page will be thrown.
Why?
-> By default, Spring Security will block /h2_console
path of H2 database.
How to resolve it?
-> Solution is a simple configuration with Spring Security as below segment code:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() ... http.csrf().disable(); http.headers().frameOptions().disable(); }
http.csrf().disable()
: disable CRSF.
http.headers().frameOptions().disable()
: H2 database console runs inside a frame, So we need to disable X-Frame-Options in Spring Security.
>>> More details at: How to configure Spring Security to access H2 database console in Spring Boot project
NoSQL Technologies
1. MongoDB
MongoDB is an open-source NoSQL document database, written using C++. Spring Boot provides an spring-boot-starter-data-mongodb to work with MongoDB.
To define MongoDb configured beans, use:
– MongoDbFactory: an interface for factories to create DB instances.
– MongoOperations: an interface that specifies a basic set of MongoDB operations.
@Configuration public class AppConfig { @Bean public MongoDbFactory mongoDbFactory() throws UnknownHostException{ return new SimpleMongoDbFactory(new MongoClient("localhost", 27017), "test"); } @Bean public MongoOperations mongoOperations() throws UnknownHostException{ return new MongoTemplate(mongoDbFactory()); } }
To define Document model, use @Document
>>> Example for details at: Spring MongoOperations to access MongoDB
2. Neo4j
Neo4j is a highly scalable, native graph database. Spring Boot supports Spring Neo4J configuration with module: spring-boot-starter-data-neo4j
.
– Configuration for connecting to Neo4J:
spring.data.neo4j.uri=http://my-server:7474 spring.data.neo4j.username=neo4j spring.data.neo4j.password=admin
– Create a Neo4J repository by extends GraphRepository
, sample:
... import org.springframework.data.neo4j.repository.GraphRepository; public interface StudentRepository extends GraphRepository{ ... }
– Some annotations for Neo4j database:
@NodeEntity: Identifies a domain entity as being backed by a node in the graph.
@GraphId: Identifies the field in the domain entity which is to be mapped to the id property of its backing node in the graph.
@Relationship: purpose for creating relationship of entities in Neo4j.
>>> Example for more details at: Spring Neo4J
3. Gemfire
Spring Data REST provides a mechanics for creating and retrieving an Object from Gemfire storage.
Configuration steps:
– Use needed dependencies: spring-boot-starter-data-rest
, spring-boot-starter-data-gemfire
:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-gemfire</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency>
– Use annotation @Region
for mapping data:
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.gemfire.mapping.Region; @Region("customer") public class Customer { private static AtomicLong COUNTER = new AtomicLong(0L); @Id private Long id; private String firstname; private String lastname; private int age; @PersistenceConstructor public Customer() { this.id = COUNTER.incrementAndGet(); } ... }
– Config CacheFactoryBean
and LocalRegionFactoryBean
:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.data.gemfire.LocalRegionFactoryBean; import com.gemstone.gemfire.cache.GemFireCache; import com.javasampleapproach.gemfirerestapi.model.Customer; @Configuration public class GemfireConfig { @Bean Properties gemfireProperties() { Properties gemfireProperties = new Properties(); gemfireProperties.setProperty("name", "EmbeddedGemfireApplication"); gemfireProperties.setProperty("mcast-port", "0"); return gemfireProperties; } @Bean CacheFactoryBean gemfireCache() { CacheFactoryBean gemfireCache = new CacheFactoryBean(); gemfireCache.setProperties(gemfireProperties()); return gemfireCache; } @Bean LocalRegionFactoryBeancustomerRegion(final GemFireCache cache) { LocalRegionFactoryBean customerRegion = new LocalRegionFactoryBean<>(); customerRegion.setCache(cache); customerRegion.setName("customer"); customerRegion.setPersistent(false); return customerRegion; } }
– Create a Gemfire repository by extends CrudRepository
interface:
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(collectionResourceRel = "customer", path = "customer") public interface CustomerRepository extends CrudRepository{ Customer findByFirstname(@Param("firstname") String firstname); Customer findByLastname(@Param("lastname") String lastname); Iterable findByAgeGreaterThan(@Param("age") int age); Iterable findByAgeLessThan(@Param("age") int age); }
>>> Example for more details at: How to create a SpringBoot Gemfire RestfulApi
4. Elasticsearch
Elasticsearch is a distributed, full-text search engine based on Lucene with JSON schema. SpringBoot provides a convenient way by supported dependency: spring-boot-starter-data-elasticsearch
‘Starter’.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
– Using annotation: @Document(indexName = "javasampleapproach", type = "customer")
to create a mapping model.
... import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; @Document(indexName = "javasampleapproach", type = "customer") public class Customer { @Id private String id; ... }
– The main part is how to connect with Elasticsearch server, We use interface ElasticsearchRepository that is supported by Spring Data:
import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import com.javasampleapproach.elasticsearch.model.Customer; public interface CustomerRepository extends ElasticsearchRepository{ List findByFirstname(String firstname); Page findByFirstname(String firstname, Pageable pageable); List findByAge(int age); }
– Use spring.data.elasticsearch.cluster-nodes
to define elasticsearch’s cluster.
>>> More details at: How to start SpringBoot ElasticSearch using Spring Data
5. Apache Cassandra
Apache Cassandra database is a NoSql solution for scalability & high availability. SpringBoot provides a convenient way by supported dependency: spring-boot-starter-data-cassandra
‘Starter’.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-cassandra</artifactId> </dependency>
Use @Table
& @PrimaryKey
to create mapping model:
– @Table: identifies a domain object to be persisted to Cassandra as a table.
– @PrimaryKey: identifies the primary key field of the entity.
import org.springframework.data.cassandra.mapping.PrimaryKey; import org.springframework.data.cassandra.mapping.Table; @Table public class Customer { @PrimaryKey private int id; private String firstname; ...
Create a Cassandra repository:
– Need provide port, keyspace-name and contact-points properties for connection’s info, via spring.data.cassandra:
spring.data.cassandra.keyspace-name=javasampleapproach spring.data.cassandra.contact-points=ozenero.com spring.data.cassandra.port=9042
– Spring Data supports basic operations for Cassandra. But more limited than JPA repositories, so we need use @Query
.
... public interface CustomerRepository extends CrudRepository{ @Query(value="SELECT * FROM customer WHERE firstname=?0") public List findByFirstname(String firstname); @Query("SELECT * FROM customer WHERE age > ?0") public List findCustomerHasAgeGreaterThan(int age); }
>>> More details at: How to start Spring Data Cassandra with SpringBoot
6. Couchbase
Spring Boot provides auto-configuration for Couchbase and abstractions on top of it by Spring Data Couchbase. We can use it easily via spring-boot-starter-data-couchbase
‘Starter’ which had collected the needed dependencies.
For connecting with Couchbase Bucket and Cluster, we can use spring.couchbase.*
properties in application.properties file:
spring.couchbase.bootstrap-hosts=127.0.0.1 spring.couchbase.bucket.name=jsabucket spring.couchbase.bucket.password=123456 spring.data.couchbase.auto-index=true
For working with Couchbase repository, we use CouchbaseRepository interface
:
public interface CouchbaseRepositoryextends CrudRepository { /** * @return a reference to the underlying {@link CouchbaseOperations operation template}. */ CouchbaseOperations getCouchbaseOperations(); }
>>> More details at: Couchbase – How to create Spring JPA Couchbase application with SpringBoot
7. Solr
SpringBoot provides spring-boot-starter-data-solr
Starter to support connecting and abstractions on top of Spring Data Solr.
7.1 Solr connection
In application.properties file, We use spring.data.solr.*
to configure Solr connection.
Here is the details of sourcecode – SolrProperties:
@ConfigurationProperties(prefix = "spring.data.solr") public class SolrProperties { /** * Solr host. Ignored if "zk-host" is set. */ private String host = "http://127.0.0.1:8983/solr"; /** * ZooKeeper host address in the form HOST:PORT. */ private String zkHost; ... }
By default the instance will attempt to connect to a server using http://localhost:8983/solr
. And we can add @Bean
with SolrClient type to override it.
7.2 Spring Data Solr repositories
We use @SolrDocument
to create Solr document:
@SolrDocument(solrCoreName = "customer") public class Customer { @Id @Field private String id; @Field private String name; @Field private Integer age; public Customer() { } ...
Using SolrCrudRepository
to create Solr repositories:
... import org.springframework.data.solr.repository.SolrCrudRepository; import com.javasampleapproach.solr.model.Customer; public interface CustomerRepository extends SolrCrudRepository{ List findByNameEndsWith(String name); }
Details about interface SolrCrudRepository
:
public interface SolrCrudRepositoryextends SolrRepository , PagingAndSortingRepository { }
>>> More details at: Apache Solr – How to start Spring Data Solr with SpringBoot
Spring MVC
1. XML REST service
– If on the classpath has Jackson XML extension (jackson-dataformat-xml), SpringBoot will be used to render XML responses.
– If jackson-dataformat-xml is not available, JAXB in JDK will be used with a required annotation @XmlRootElement in model
import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Customer { private String firstname; ... }
– GET requests must have Accept: text/xml header.
– POST requests must have Content-Type: text/xml header.
>>> More details at: How to create a SpringBoot XML REST Service
2. Multipart File Uploads
Upload files to Servlet containers, application need register a MultipartConfigElement class. But Spring Boot makes it more easy by automatically configure it.
– From upload form, we specify enctype="multipart/form-data"
:
... <form method="POST" enctype="multipart/form-data" action="/"> <table> <tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr> <tr><td></td><td><input type="submit" value="Upload" /></td></tr> </table> </form> ...
– In Post Mapping method, we specify MultipartFile file
request’s parameter:
... @PostMapping("/") public String handleFileUpload(@RequestParam("file") MultipartFile file, Model model) { ...
We can handle limit of file’s size by spring.http.multipart
config:
– spring.http.multipart.max-file-size: limit total file size for each request.
– spring.http.multipart.max-request-size: limit total request size for a multipart/form-data.
>>> More details at: How to upload MultipartFile with Spring Boot
HATEOAS
Spring HATEOAS project helps to create REST representations that follow HATEOAS (Hypertext as the Engine of Application State) principle.
1. HATEOAS
In general, HATEOAS principle implies that with each response, API should shows Clients appropriate information about the next potential steps or guide to deeper understanding itself.
For example, if client requests for specific Customer information:
http://localhost:8080/customers/68
The Service should provide link to get all Orders of that Customer in the response:
{ ... "customerId": 68, "_links": { "self": { "href": "http://localhost:8080/customers/68" }, "allOrders": { "href": "http://localhost:8080/customers/68/orders" } } }
2. Spring HATEOAS
Spring HATEOAS provides a set of useful types to ease working with those.
Firstly, we need create a Link
object:
– Way 1: using Spring HATEOAS ControllerLinkBuilder
– Way 2: using Spring HATEOAS EntityLinks
Then, add Link
object to ResourceSupport
object:
– Way 1: extending ResourceSupport
class
– Way 2: using ResourcesResourceSupport
class)
Finally, just return YourClass
object or Resource
object to Client.
>>> More details at: How to start Spring HATEOAS RestAPI with Spring Boot
3. Spring HATEOAS Rest API with JQuery Ajax POST/GET
We’ll build a Spring Boot Application in that:
– HATEOAS REST Service provides interface for interacting with Database.
– Client calls API by using JQuery Ajax POST/GET.
>>> More details at: Spring HATEOAS Rest API + JQuery Ajax POST/GET example | Spring Boot
4. Consume Spring HATEOAS Rest API using JQuery Ajax
We’ll build a Spring Boot Application in that:
– HATEOAS REST Service provides interface for interacting with Database.
– Client calls API by using JQuery Ajax GET, consume HATEOAS REST Service above and displays Data.
>>> More details at: Consume Spring HATEOAS Rest API using JQuery Ajax example | Spring Boot
5. Consume Spring HATEOAS Rest API using AngularJS
– HATEOAS REST Service provides interface for interacting with Database.
– Client calls API by using AngularJS, consume HATEOAS REST Service above and displays Data.
>>> More details at: Consume Spring HATEOAS Rest API using AngularJS example | Spring Boot
CORS
Cross-Origin-Resource-Sharing (CORS) is a W3C specification which defines how a browser should be allowed using script to access different origin than the origin it has been served. With CORS, we can specify what kind of cross domain requests are authorized in a flexible way, instead of using some less secured and less powerful hacks like IFRAME or JSONP.
1. Configure CORS using @CrossOrigin
@CrossOrigin(origins = { "http://localhost:9000" }, maxAge = 3000) @RestController public class WebController { @CrossOrigin(origins = { "http://localhost:8484" }, maxAge = 6000) @RequestMapping("customers") public ListgetCustomers() { // ... } @RequestMapping("data") public List getData() { // ... } }
>>> More details at: Spring CORS example using @CrossOrigin – Spring Boot
2. Global CORS Configuration using Java Config
Spring provides a way that uses Java Config applying for all REST Service Controllers in our project.
WebMvcConfigurerAdapter
has addCorsMappings()
method that we need to override to configure CORS:
@Configuration public class AppConfig extends WebMvcConfigurerAdapter { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/customers") .allowedOrigins("http://localhost:8484", "http://localhost:9000") .allowedMethods("POST", "GET", "PUT", "DELETE") .allowedHeaders("Content-Type") .exposedHeaders("header-1", "header-2") .allowCredentials(false) .maxAge(6000); } }
>>> More details at: Spring Boot – CORS Support using Java Config
3. Global CORS Configuration using XML Config
Spring also provides a way that uses XML Config applying for all REST Service Controllers in our project:
<mvc:cors> <mvc:mapping path="/customers" allowed-origins="http://localhost:8484, http://localhost:9000" allowed-methods="POST, GET, PUT, DELETE" allowed-headers="Content-Type" exposed-headers="header-1, header-2" allow-credentials="false" max-age="6000" /> </mvc:cors>
>>> More details at: Spring Boot – CORS Support using XML Config
Logging
1. Log4j2
Apache Log4j2 is an upgrade to Log4j that provides significant improvements over its predecessor, Log4j 1.x, and provides many of the improvements available in Logback while fixing some inherent problems in Logback’s architecture.
To configure Log4j2 dependency with Spring Boot, we do 3 steps:
– Exclude logback from default log dependency of Spring Boot:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
– Add Spring Web MVC dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
– Add Log4j2 dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
And create a file with special name: log4j2.xml under /src/main/resources folder:
... <Loggers> <Logger name="org.springframework.web" level="info" additivity="false"> <AppenderRef ref="SpringBoot-Appender"/> <AppenderRef ref="Console-Appender"/> </Logger> <Logger name="com.javasampleapproach.log4j2.controller" level="info" additivity="false"> <AppenderRef ref="App-Appender"/> <AppenderRef ref="Console-Appender"/> </Logger> <Root> <AppenderRef ref="Console-Appender"/> </Root> </Loggers> ...
>>> More details at: How to configure Apache Log4j2 with Spring Boot
2. Actuator Loggers Endpoint
Spring Boot 1.5.1 provides some new features. Among them, we have a new actuator loggers endpoint, which helps us to view and change logging level of application with the MVC endpoint.
– Start with spring-boot-starter-actuator
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
– Actuator endpoints help us to monitor and interact with our application. Spring Boot includes a number of built-in endpoints including Loggers Endpoint:
{ "configuredLevel":"...", "effectiveLevel":"..." }
‘…‘ could be: TRACE, DEBUG, INFO, WARN, ERROR…
– We can change how this endpoint exposes by add some code to application.properties, in this example:
management.port=8081 management.security.enabled=false management.address=127.0.0.1 management.context-path=/actuator endpoints.loggers.enabled=true
– View Logging Level:
Just make a HTTP GET request to /loggers/[our qualified name of package]. The JSON String result will be:
{ "configuredLevel":"[Logging Level to be set]", "effectiveLevel":"[current active Logging Level]" }
– Change Logging Level: We can issue a HTTP POST request to /loggers/[our qualified name of package] with the following JSON
{ "configuredLevel": "[Logging Level]" }
>>> More details at: How to change logging level with the MVC endpoint – new Actuator Loggers Endpoint | Spring Boot
MicroService
1. Routing and Filtering
Netflix Zuul is a proxy solution to forward requests to microservices, Spring Cloud Netflix contains an embedded Zuul.
Step to start building a Zuul gateway:
– Add required dependencies:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> <version>1.3.0.RELEASE</version> </dependency>
– Configure MicroServices for routing:
zuul.routes.students.url=http://localhost:8081 zuul.routes.lecturers.url=http://localhost:8082 ribbon.eureka.enabled=false server.port=8080
– Enable Zuul Gateway by annotation @EnableZuulProxy
:
... import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableZuulProxy @SpringBootApplication public class SpringBootZuulGateWayApplication { public static void main(String[] args) { SpringApplication.run(SpringBootZuulGateWayApplication.class, args); } }
Zuul has 4 filter types:
– pre filters are executed before the request is routed.
– route filters uses to route the request.
– post filters are executed after the request has been routed.
– error filters execute if an error occurs while handling the request.
For creating a filter, just extends ZuulFilter. Then need overview 4 functions:
– public String filterType()
: specify the type of a filter: (pre, route, post, error) by a String
– public int filterOrder()
: indicates the order to process this filter.
– public boolean shouldFilter()
: gives a condition to consider to execute the filter.
– public Object run()
: functionality of the filter.
>>> More details at: How to configure SpringBoot Zuul – Routing and Filtering
2. Spring Cloud Ribbon – Client Load Balancing
Spring Cloud Ribbon is a solution for Client Load Balancing.
Advantage & Disadvantage:
– Decentralized Load Balancing
– No bottle neck
– Resilent
– Data can be inconsistent
SpringBoot provides a convenient way by supported dependency: spring-cloud-starter-ribbon
‘Starter’.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
Config Ribbon Client:
spring: application: name: Ribbon-Client helloworld: ribbon: eureka: enabled: false listOfServers: localhost:8090,localhost:8091,localhost:8092 ServerListRefreshInterval: 1000 server: port: 8080
– @RibbonClient
is used to configure a Ribbon Client.
... @SpringBootApplication @RibbonClient(name = "helloworld", configuration = Configuration.class) public class SpringClientSideRibbonApplication { ...
– @LoadBalanced
annotation is used to configure RestTemplate bean as a LoadBalancerClient.
@RestController public class WebController { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } ...
>>> More details at: Client Load Balancing – Spring Cloud Ribbon + Spring Boot
Messaging
I. ActiveMQ
1. JMS Producer/Consumer
Spring JMS (Java Message Service) is a powerful mechanism to integrate in distributed system.
ActiveMQ is a Java Open Source, it is simple JMS solution for concurrent, consumers and producers architecture in integrated development.
Spring Boot will create a Connection Factory basing on those information automatically:
spring.activemq.broker-url=failover://tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin
Use JmsTemplate for sending & receiving messages:
– JmsConsumer
@Component public class JmsConsumer { @Autowired JmsTemplate jmsTemplate; @Value("${jms.queue.destination}") String destinationQueue; public String receive(){ return (String)jmsTemplate.receiveAndConvert(destinationQueue); } }
– JmsProducer
@Component public class JmsProducer { @Autowired JmsTemplate jmsTemplate; @Value("${jms.queue.destination}") String destinationQueue; public void send(String msg){ jmsTemplate.convertAndSend(destinationQueue, msg); } }
>>> Example for details at: How to use Spring JMS with ActiveMQ – JMS Consumer and JMS Producer
2. Explicitly configure Spring ActiveMq ConnectionFactory
For configuring ActiveMQ ContainerFactory, we need to setup a new bean ConnectionFactory to override the auto-configured connection-factory bean of SpringBoot.
... @Bean public ConnectionFactory connectionFactory(){ ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); ... return connectionFactory; }
Then use the ConnectionFactory
bean to configure 2 beans {JmsListenerContainerFactory
, JmsTemplate
}:
/* * Used for Receiving Message */ @Bean public JmsListenerContainerFactory> jsaFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); ... return factory; } /* * Used for Sending Messages. */ @Bean public JmsTemplate jmsTemplate(){ ... return template; } ...
– JmsTemplate
bean is used to send Jms messages.
– JmsListenerContainerFactory
is used to listen Jms messages.
>>> More details at: ActiveMq – Explicitly configure Spring ActiveMq ConnectionFactory with SpringBoot
3. JMS ActiveMQ – Send Java object messages(specially with Bi-Directional relationship Java objects)
Use Jms MessageConverter bean as below:
@Bean // Serialize message content to json using TextMessage public MessageConverter jacksonJmsMessageConverter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); converter.setTargetType(MessageType.TEXT); converter.setTypeIdPropertyName("_type"); return converter; }
With Bi-Directional Java object messages -> We got an Infinite recursion (StackOverflowError) exception:
... Caused by: org.springframework.jms.support.converter.MessageConversionException: Could not map JSON object ...
-> We can use @JsonIdentityInfo
to resolve it.
>>> More details at: Spring Jms ActiveMq – How to send Java object messages to ActiveMQ server (specially with Bi-Directional relationship Java objects)
4. JMS ActiveMq Topic (Publisher-Subcribers pattern)
ActiveMq provides the Publish-Subscribe pattern (pub-sub) for building Jms message distributed systems.
How it work? -> When you publish a messages, all active subscribers will receive a copy of the message:
With SpringBoot application, we need to enable pubSubDomain (.setPubSubDomain(true))
for 2 beans {JmsTemplate
, JmsListenerContainerFactory
}:
@Bean public JmsListenerContainerFactory> jsaFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) { ... factory.setPubSubDomain(true); ... return factory; } @Bean public JmsTemplate jmsTemplate(){ JmsTemplate template = new JmsTemplate(); ... template.setPubSubDomain(true); return template; }
And set spring.jms.pub-sub-domain=true
in application.properties file.
>>> More details at: ActiveMq – How to work with Spring JMS ActiveMq Topic (Publisher-Subcribers pattern) using SpringBoot
5. Response Management
5.1 @SendTo
With the Spring JMS improvements (from 4.1), we can used @SendTo
annotation to define the default next destination with @JmsListener
:
@JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory") @SendTo("${jsa.activemq.queue.sendto}") public Product processOrder(Product product) { // process a newProduct return newProduct; }
For additional headers, you could return a Message object instead:
@JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory") @SendTo("${jsa.activemq.queue.sendto}") public Messagereceive(Product product, @Header("company") String companyName){ ... Message mesage = MessageBuilder .withPayload(product) .setHeader("type", product.getType()) .build(); return mesage; }
>>> More details at: Spring Jms ActiveMQ – How to create a SpringBoot ActiveMQ Response Management application by @SendTo annotation
5.2 JmsResponse
With the support of JmsResponse
, we can configure the response destination at runtime:
... @JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory="jsaFactory") public JmsResponse> receive(Product product, @Header("company") String companyName){ ... Message response = MessageBuilder .withPayload(product) .setHeader("type", product.getType()) .build(); return JmsResponse.forQueue(response, sendToQueue); } ...
>>> More details at: Spring JMS ActiveMq – How to implement a runtime SpringBoot ActiveMQ JmsResponse application
Other Examples
– ActiveMQ Producer/Consumer + SpringBoot RestAPIs example
– Ajax JQuery + SpringBoot RestAPI + ActiveMQ Producer/Consumer example
II. Apache Artemis
SpringBoot Auto-configure
When having artemis-jms-client
Artemis on the classpath, Spring Boot can auto-configure a ConnectionFactory.
We use spring.artemis.*
to control Artemis configuration:
spring.artemis.mode=native spring.artemis.host=localhost spring.artemis.port=61616 spring.artemis.user=jsa spring.artemis.password=12345
spring.artemis.mode
has 2 mode: {NATIVE, EMBEDDED}:
– NATIVE: Connect to a broker using the native Artemis protocol.
– EMBEDDED: Embed the broker in the application.
For sending message, we use: JmsTemplate
:
@Component public class ArtemisProducer { @Autowired JmsTemplate jmsTemplate; @Value("${jms.queue.destination}") String destinationQueue; public void send(String msg){ jmsTemplate.convertAndSend(destinationQueue, msg); } }
For recieved messages, we use: @JmsListener
:
@Component public class ArtemisConsumer { @JmsListener(destination = "${jms.queue.destination}") public void receive(String msg){ System.out.println("Recieved Message: " + msg); } }
>>> More details at: Apache Artemis – How to produce/consume JMS messages with SpringBoot Artemis applications.
III. AMQP
1. RabbitMQ Producer/Consumer
Creating 2 SpringBoot applications {Producer, Consumer} for working with RabbitMQ:
– Producer will send messages to RabbitMQ Exchanges with a routingKey
. RabbitMQ uses routingKey to determine which queues for routing messages.
– Consumer listens on a RabbitMQ Queue to receive messages.
With SpringBoot, we use spring.rabbitmq.*
for controlling RabbitMQ configuration:
spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest
Producer uses AmqpTemplate
to send messages:
@Component public class Producer { @Autowired private AmqpTemplate amqpTemplate; public void produceMsg(String msg){ amqpTemplate.convertAndSend(exchange, routingKey, msg); } }
Consumer uses @RabbitListener
to recieve messages:
@Component public class Consumer { @RabbitListener(queues="${jsa.rabbitmq.queue}") public void recievedMessage(String msg) { // to do } }
>>> More details at: RabbitMQ – How to create Spring RabbitMQ Producer/Consumer applications with SpringBoot
2. RabbitMq Publish/Subcribe pattern
Flow messages:
– Publisher will send messages to the fanout exchange.
– The fanout exchange routes messages to all of the queues that are bound to it and the routing key is ignored.
– Subcribers instances recieves messages from the queues.
>>> More details at: RabbitMq – How to create Spring RabbitMq Publish/Subcribe pattern with SpringBoot
3. RabbitMQ – send/receive Java object messages
Using Message Converter:
@Bean public MessageConverter jsonMessageConverter(){ return new Jackson2JsonMessageConverter(); }
With Bi-Directional Java object messages -> We may get an Infinite recursion (StackOverflowError)
exception.
-> Solution: we can use @JsonIdentityInfo
to handle the exception.
>>> More details at: RabbitMQ – How to send/receive Java object messages with Spring RabbitMq | SpringBoot
IV. Apache Kafka
1. SpringBoot supports auto-configuration
SpringBoot supports auto-configuration for Apache Kafka development:
– Use spring.kafka.*
in application.properties file to modify external configuration.
– Use Spring auto-configured KafkaTemplate to send Kafka-based messages:
@Autowired private KafkaTemplatekafkaTemplate; public void send(String data) { ... kafkaTemplate.send(kafkaTopic, data); }
– Use @KafkaListener
to setup a Kafka listener:
@Component public class KafkaConsumer { ... @KafkaListener(topics="${jsa.kafka.topic}") public void processMessage(String content) { ... } }
>>> More details at: How to start Spring Apache Kafka Application with SpringBoot Auto-Configuration
2. Spring Kafka JsonSerializer (JsonDeserializer) to produce/consume Java Object messages
We send and receive Java object messages to/from Apache Kafka, so ProducerFactory uses JsonSerializer.class
and ConsumerFactory uses JsonDeserializer.class
to serialize/deserialize Java objects to Json bytes.
– KafkaProducerConfig:
@Bean public ProducerFactoryproducerFactory() { ... configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } @Bean public KafkaTemplate kafkaTemplate() { return new KafkaTemplate<>(producerFactory()); }
– KafkaConsumerConfig:
@Bean public ConsumerFactoryconsumerFactory() { ... props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class); return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(), new JsonDeserializer<>(Customer.class)); } @Bean public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); ... return factory; }
– Note: SpringKafka uses Jackson library to serialize/de-serialize Java objects to/from Json bytes so we need jackson-databind
dependency.
>>> More details at: How to use Spring Kafka JsonSerializer (JsonDeserializer) to produce/consume Java Object messages
Caching
1. Infinispan
Infinispan cache is a distributed in-memory key/value data store, it is a excellent cache for software system. For starting with SpringBoot, we need dependencies:
...org.springframework.boot spring-boot-starter-cache ... org.infinispan infinispan-jcache
– In application.properties file, use spring.cache
to define configuration of Infinispan:
spring.cache.infinispan.config=infinispan.xml spring.cache.type=infinispan
– The infinispan.xml file is created under folder: /src/main/resources:
– Enable caching by annotation: @EnableCaching
:
import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class SpringCachingInfinispanApplication { public static void main(String[] args) { SpringApplication.run(SpringCachingInfinispanApplication.class, args); } }
>>> More details at: Infinispan Cache Solution | Spring Boot
2. Couchbase
We can use Couchbase as backing cache:
How to configure Couchbase server as Cache?
-> We need to build a CacheManager
with Couchbase cluster:
@EnableCaching @Configuration public class CacheConfig { ... @Bean(destroyMethod = "disconnect") public Cluster cluster() { return CouchbaseCluster.create(couchbaseServer); } @Bean(destroyMethod = "close") public Bucket bucket() { return cluster().openBucket(couchbaseBucket, couchbasePassword); } @Bean public CacheManager cacheManager() { CacheBuilder cacheBuilder = CacheBuilder.newInstance(bucket()).withExpiration(0); return new CouchbaseCacheManager(cacheBuilder, CACHE_NAME); } }
@EnableCaching
is used to enable the caching.
Document for Couchbase cache is built with Serializable
:
public class Customer implements Serializable { ... }
>>> More details at: Couchbase – How to create Spring Cache Couchbase application with SpringBoot
Deployment
Traditional Deployment
Create a deployable war file
Step to do:
– Extends SpringBootServletInitializer
– Update build configuration
1. Extends SpringBootServletInitializer
package com.javasampleapproach.wardeployment; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class SpringBootWarDeploymentApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootWarDeploymentApplication.class); } public static void main(String[] args) { SpringApplication.run(SpringBootWarDeploymentApplication.class, args); } }
2. Update build configuration=
– Update your build configuration: war
– Configure embedded servlet container dependency as provided
...war ...org.springframework.boot spring-boot-starter-tomcat provided
>>> More details at: How to deploy Spring Boot Web App War file to Tomcat Server with Maven build
Deployment on Heroku Clouud
Batch Application
Many business operations need to process with batch job for critical environment. Spring Batch is a lightweight framework to boot the batch application. To start SpringBatch by SpringBoot, using dependency:
org.springframework.boot spring-boot-starter-batch
Configure datasource for repository of SpringBatch Application by easy way:
spring.datasource.url=jdbc:postgresql://url spring.datasource.username=db spring.datasource.password=password
Spring Boot provides @EnableBatchProcessing
annotation for automatically enable Spring Batch:
@SpringBootApplication @EnableBatchProcessing public class SprinpBatchApplication { public static void main(String[] args) { SpringApplication.run(SprinpBatchApplication.class, args); } }
To configure details of a Batch Job, we can use Java Config or XML config:
– Java config
... @Configuration public class BatchConfig { @Autowired public JobBuilderFactory jobBuilderFactory; @Autowired public StepBuilderFactory stepBuilderFactory; @Bean public Job job() { return jobBuilderFactory.get("job") .incrementer(new RunIdIncrementer()) .flow(step1()) .end() .build(); } @Bean public Step step1() { return stepBuilderFactory.get("step1") .chunk(1) .reader(new Reader()) .processor(new Processor()) .writer(new Writer()) .build(); } }
– XML config
......
>>> More details at:
– How to start with Spring Batch using Spring Boot – Java Config
– Spring Batch XML Config with Spring Boot
Sending Email
Spring Framework provides JavaMailSender interface & Spring Boot provides auto-configuration for sending mail.
– Using spring-boot-starter-mail dependency.
– Configure spring.mail for JavaMailSender:
spring.mail.host=smtp.gmail.com spring.mail.port=587 spring.mail.username=javasampleapproach spring.mail.password=*** #mail properties spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true
– Create a MailSender class:
... import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; @Component("javasampleapproachMailSender") public class MailSender { @Autowired JavaMailSender javaMailSender; public void sendMail(String from, String to, String subject, String body) { SimpleMailMessage mail = new SimpleMailMessage(); mail.setFrom(from); mail.setTo(to); mail.setSubject(subject); mail.setText(body); javaMailSender.send(mail); ... } }
>>> More Details at: How to configure JavaMailSender with SpringBoot
WebSocket
1. Flow of messages
We create a Spring WebSocket Application with the below flow of messages:
Detail explanations:
– WebSocket clients connect to the WebSocket endpoint at ‘/jsa-stomp-endpoint’
– Subscriptions to ‘/topic/hi’ pass through the response channel, then are forwarded to the In-memory broker (Simple Broker).
– User objects sent to ‘/jsa/hello’ pass through the request channel then are forwarded to the spring WebController. WebController will handle User
objects by @MessageMapping
and transform to Hello
messages then use @SendTo
returns the messages to ‘/topic/hi’ through the brokerChannel.
... @MessageMapping("/hello") @SendTo("/topic/hi") public Hello greeting(User user) throws Exception { return new Hello(...); } ...
– The Simple Broker broadcasts messages to subscribers through the response channel.
2. Server side
In server side, we use SockJS and STOMP for our application.
What is SockJS?
-> SockJS lets applications use a WebSocket API but falls back to non-WebSocket alternatives when necessary at runtime, without the need to change application code.
Simple Java configuration to enable SockJS and Stomp in Spring application:
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/jsa"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/jsa-stomp-endpoint").withSockJS(); } }
3. Client side
About client side, we uses {sockjs-client, stomp-websocket} libs for development:
– Make a connection:
function connect() { var socket = new SockJS('/jsa-stomp-endpoint'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); stompClient.subscribe('/topic/hi', function (hello) { ... }); }); }
The connect()
function uses SockJS
and stomp.js
to open a connection to /jsa-stomp-endpoint
, which is where our SockJS
server is waiting for connections.
– Dis-Connection:
function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); }
– Send messages:
function sendName() { stompClient.send("/jsa/hello", {}, JSON.stringify({'name': $("#name").val()})); }
>>> More details at: WebSocket – Create Spring WebSocket Application with SpringBoot + SockJS + STOMP
JWT Authentication
With MySQL database ->
– Spring Security JWT Authentication example – RestAPIs SpringBoot + Spring MVC + Spring JPA + MySQL
With PostgreSQL database ->
– Spring Security JWT Authentication + PostgreSQL – RestAPIs SpringBoot + Spring MVC + Spring JPA
Other Examples
Spring Social with SpringBoot
– SpringBoot Social Facebook – Authentication & Access Facebook Feeds Example
CSV, PDF, Excel Files with SpringBoot
– iText PDF + SpringBoot RestAPI – Extract MySQL Data to PDF File
– Excel File – Download from SpringBoot RestAPI + Apache POI + MySQL
– CSV File – Download from SpringBoot RestAPI + OpenCSV + MySQL
– Download CSV File from SpringBoot RestAPI + MySQL – using Apache Commons CSV + Spring JPA
All Articles
>>> SPRING BOOT