2. Introduction to Spring
1. Spring and Spring Boot
The Spring Framework simplifies the development of Java applications, regardless of whether they are ordinary web applications or offline web applications. Its biggest advantages are a more simplified source code and less difficulty in adjustments. In order to offer the programmer these comforts, the framework is based on the following principles:
-
Dependency injection (DI): technique or design pattern used as one of the forms of inversion of control (IOC) to promote loose coupling. That is, when a class needs another class (dependency), instead of creating the object within the class itself, Spring supplies or injects it. This form of IOC follows the Hollywood principle (don't call us, we'll call you) in which the application takes control instead of the code, providing the following benefits:
- Provides modularity.
- Scalability of the application without the need to modify the classes.
- Avoid dependency between classes
-
Simple development with POJOs (Plan Old Java Objects)
- Minimize boilerplate code
- Simplifies data access thanks to ORM (Object Relational Mapping)
- Aspect Oriented Programming (AOP): Allows a much higher modularization to make a very clear separation of the different tasks that each class must perform in our application.
1.1. Main Spring Framework modules
Thanks to its modular structure for the development of the most diverse applications in Java, Spring is the perfect choice, since you can freely choose which of the components you need to use for your applications and which not. In the standard architecture, the different modules are divided into six main categories:
-
Core Container: The core container provides the basic modules:
- Core and Beans form the backbone of the framework, containing the dependency injection function and supporting POJO objects. We clarify that a Bean is a POJO, although it has some more features.
- Context inherits its features from the Beans module and can be complemented with functions for internalizing or loading resources. Additionally, it supports Java Enterprise features such as EJB and JMX (Java Management Extensions). Context-support makes it easy to integrate libraries from other vendors into Spring.
- Spring-expression contains the Spring Expression Language (SPeL), an extension of the Unified Expression Language of the JSP-2.1 (Java Server Pages) specification.
-
AOP and instrumentation: To enable aspect-oriented programming, the Spring Framework contains the spring-aop module. The spring-instrument component provides support for the implementation of object loading and handling classes for use on some servers.
- Messaging: To serve as the basis for message-based applications, the Spring Framework relies on some of the encryption functions from the Spring Integration project, such as Message, MessageChannel, or MessageHandler. This module has the name of spring-messaging.
-
Data Access/Integration: Modules in this category are designed to give Java applications the tools to interact with other applications, as well as control access to data:
- spring-jdbc provides an abstraction layer that defines the way a client accesses the database and saves the complicated coding typical of JDBC.
- spring-orm offers integration layers for accessing relational databases in popular ORM interfaces.
- spring-tx (supports programmatic transaction management for all classes and POJOs).
- spring-oxm (abstraction layer for mapping objects or XML).
- spring-jms, a module with features for message production and processing.
-
Web: in this category are the specific modules for web applications: spring-web, spring-webmvc and spring-websocket. Additionally, this Java application has added typical web-oriented integration functions such as a multipart upload function or an HTTP client. The spring-webmvc module is also known as a web servlet and is the one that contains the Spring implementations for the execution of the model-view-controller (MVC) architecture pattern and REST web services.
- Test: the spring-test module allows you to check the functionality of the components of your Java application. Thus, with the help of additional frameworks such as JUnit or TestNG, you can perform unit tests (focusing on a single component) as well as integration tests.
2. Spring vs Spring Boot
Spring Boot appeared a few years ago with the idea of complementing Spring, that is, adding to Spring, not with the idea of replacing it. As can be interpreted in the image below, Spring Boot really works with Spring below, but in an easier way.
We could define Spring Boot as an accelerator for the creation of Spring projects, which is mainly based on the concept of convention before configuration. Another way to define Spring Boot could be as a Spring project creation accelerator. Therefore, the purpose is to create Spring projects, but in a more agile way, through a series of conventions that prevail over configuration. Saving us from having to waste time making heavy configurations in files.
It should be noted that Spring Boot is not considered a Framework as such, on the other hand, Spring does have the privilege of categorizing itself as such. With Spring Boot, we can do the same as with Spring. But in a faster way than if we develop exclusively with Spring only. But with both, we could have the same development, although the difference between the two would be the time invested.
To explain the differences between the two, it is essential to introduce the concept of configuration convention, which plays such an important role in the field of software engineering.
2.1. What is the configuration convention?
This principle basically specifies/details a series of conventions (set of rules) that will be above the configuration unless otherwise specified. That is, they will be applied by default if we do not specify otherwise.
An example of a convention before configuration could be when we create an MVC application with Spring, we have to carry out many configurations, including the port. On the other hand, if we create the application using Spring Boot, thanks to the configuration convention, the default port of the application when starting it will be 8080. But if we want to change it, we only have to modify a file and add a single instruction where we will detail the port, for example, 8888. In this way, we will carry out a more agile development, since we will avoid having to make configurations, except that we want to modify the configuration of some convention.
3. Requirements and Installation
Spring works with many embedded technologies (below), so we advise having the following to make sure everything works for us. Requirements are:
- Java installed, it is advisable to have version 8, due to its stability. And that Spring doesn't support all some of the newer versions of Java.
- Apache Maven installed.
- A compatible IDE (in this case it will be Spring Tool Suite).
Spring Tool Suite 4, which is the one provided to us from the Pivotal website (official page of the creators of maintaining Spring.). It can be downloaded from https://spring.io/tools.
4. First project and execution
In order to create a Spring project, we can do it in two ways:
- Create a project from Spring Boot Initializer, the web tool provided by Pivotal here https://start.spring.io. This assistant generates a zip file with the structure of the maven project. We need to import this zip file in our IDE to start programming.
- Create the project from the IDE using the Command Line Tool (CLI), in our case the chosen IDE will be Spring Tool Suite 4. We do not need extra steps to start to program.
4.1. Initializr
We visit https://start.spring.io and fill the form:
In dependencies part, we should add the aspects of our program. Initially web app, but we could add Lombok, Thymeleaf, and other aspects
Here you will find several screenshots with the process. From STS create a new project:
And select a Spring starter project:
Select a maven project, java version installed and write information about artifact version and so:
And finally select the dependencies. In our initial project, select Spring web.
And when the process finish you will find a project structure with a pom.xml configured.
and the structure:
4.2. First run
Let's go to take a look what files have been created in our project. As you can see, only a class with a main function:
| Java | |
|---|---|
It will run a SpringApplication, in the same way as running a Thread. This class bootstrap and launch the Spring application, with arguments, if exists.
Tip
Spring as a web app, does not interact with user, and it will wait and serve to many clients. For this reason it is not a good idea to do interactive programs with users
To run our Spring app:
And it will appear in console a log similar to:
The first important thing you need to see is the port that tomcat server is listening to. By default is port 8080:
| Bash | |
|---|---|
And when we stop our program:
Tip
Remember that is very useful to read all these messages, specially when something does not work as it is expected
To show that our program is working properly, we need to test the specific port, and then, going to our browser and writing http://localhost:8080.
The error message that we get Whitelabel Error Page, it is not an error at all, due to we have not program any controller, i. e. the server is working, but it is not serving anything.
4.3. application.properties file
This file contains lot of useful configurations we will set along our development cycle. We will study as they will appear, but all configurations we set in hibernate.cfg.xml file in unit 3 will be set in this file.
This file, as all properties file, has an attribute-value pair structure. First important value is to change the port that our server listen. This file is under src/main/resources folder. We must add, for instance:
If we re-run our app, we must change port in browser to access our server.
Tip
You can view (almost) all properties visiting this webpage
We could add any value that we want use, like constants to use in our programs. Then we can load it in our programs. For instance:
| Bash | |
|---|---|
to load in our programs, we need to use @Value annotation:
| Java | |
|---|---|
4.4. @SpringBootApplication annotation
In Spring Boot, it is very common to apply multiple annotations on the main class. But commonly, most developers mainly apply 3 annotations.
@Configuration: Available from version 3 of Spring, it offers us the possibility of making a notation that will be in charge of defining the class that owns it as a configuration class. This configuration for the Spring framework will be based on annotations. And not like in its origins, which was based on XML, which made it more complex. Another purpose of this annotation will be to allow dependency injection.@EnableAutoConfiguration: Spring Boot Auto Configuration attempts to automatically configure your Spring application based on any jar dependencies you've added. If, for example, if you put an HSQLDB (system database management) is in your classpath, and you haven't manually configured any database connection beans, Spring Boot automatically configures an in-memory database.@ComponentScan: It is used together with@Configurationto tell Spring where to look for the components, and it will be within the package that we have annotated. By only having to write it down once, being able to make all the packages be children of the package of the parent class (the one that contains the main). Basically this tells Spring where everyone should look for components.
In order to use this three-pack annotations, Spring Boot offer us @SpringBootApplication as the join of three annotations explained before.
5. MVC with Spring
5.1. Controllers
A controller, is responsible for responding to events. Normally, these events are actions (more technically known as requests) that are usually performed by the user, although they can also be more automated requests such as APIS, Ajax front pages, etc.
In a real life context, a controller is like a waiter; He or She is waiting behind the bar until a client arrive. The client apply for a coke, and the waiter, if have will serve. Then arrives another client, and applies for a coffee, and then the waiter serves. Another client arrive, and applies for a green tea, and the waiter say that he could not serve, because he has no tea. Again and again... The waiter will serve all that the client wants, if he could.
Returning to spring, we must add in our program a module that works as a controller, listening all client requests, and answering (if could) with the data that the client request.
Remember the error in first Spring execution: Spring App works fine, but we have not a controller yet. Let's go.
5.2. Package controllers
We are going to create a controller, but first, we have to create a package, which contains said controller. Earlier we were talking about the @SpringBootApplication annotation that we talked about being equivalent to having 3 annotations. One of them was @ComponentScan. If we don't want to have to tell it to scan several packages (which is usually the best idea), we usually put the entire package structure inside the parent package, which will be the package where we have the main.
To do this, right-click on the package that contains main. In this way, when we go to put the name directly we will get the com.example and we will only have to add a . and the name of the child package. If not, we would have to write the full name of the package. As you can see, the white package tell us that is an empty package instead of brown package
Let's go to create a simple class that control index of our application. For this reason we must call our class like indexController.java. Remember that index refers to our server/app main domain.
Tip
It is a good practice to set class names following simple rules to understand the class behavior. Thus, a class called clientController is the controller that maps information about Client, and filmController.java is about Films.
Once our class has been created, inside package controller, we must set up. Let's go seeing an example of indexController.java:
| Java | |
|---|---|
Take a look of our anotations:
@Controller→ tell Spring that this class is a controller. Is a specialization of@Component, and as Spring explores all classpath, is automatically detected.@GetMapping("/")→ is the controller. We define a path ("/") in our server, and we listenGETmethod. We will speak more next.@ResponseBody→ tells the controller to serialize the return value (an String in our sample) to JSON and send it throwhttp_responseto the client that calls the controller.
Now if we try to reload the page in navigator, instead of an error message you will get the returned value by the controller:


Another way to get same result will be:
| Java | |
|---|---|
where:
@RestController→ tells that in this class all methods includes@ResponseBodyannotation. Be careful, due to all methods will return a JSON object, and exists some cases (when we will send data to views in other format), it is a bad idea.
5.3. Requests and Parameters
Attention
To test our request, from now let's go to use POSTMAN https://www.postman.com/downloads/. There is an appendix about using postman.
Let's add some intelligence to a controller route, giving it some dynamism through parameter passing. These parameters will be accepted thanks to the @RequestParam annotation.
The number of parameters that we will receive will be equal to the number of parameters that we have defined within the @RequestParam annotation of the controller route method, as follows
| Java | |
|---|---|
It means that a request of GET /hola will need a parameter (name) with its value. For instance http://localhost:9090/hola?name=Joange.
Notice that if we do not add the parameter, the request will be wrong. We could solve it, setting this parameter as no required and a default value, as follows:
| Java | |
|---|---|
5.4. Logger
A good idea too, is to use Logger to show what is happen in our server. We can use like we suggest:
| Java | |
|---|---|
Logger offer us to show each kind of message type:
void error(String msg)void warn(String msg)void info(String msg)
5.5. Multiple parameters
Let's go to study how to get several parameters, even though is not recommended more than three or four, because the paths increases a lot, and there better methods to pass data to the server, as objects in the BODY request from forms or data inside paths. A classical sample is like follows:
notice that:
- Although default values could be integers or numbers, we must set as strings.
- The
HttpServletRequestvariable defined is used to get extra information about the http request received.
Important
Spring @Autowired is one of the most used annotations. This annotation allows doing dependency injection. This mean that Spring will look for class inside the application context that match with desired bean, create a new instance and inject inside the bean who posses the injection.
5.6. Post request
Apart from GET, we can do POST, PUT, DELETE and more request to our server. We simply have to replace @GetMapping with @PostMapping, with corresponding import. In fact, since they are different routes, even if they are called the same, they could be in the same file without any problem.
| Java | |
|---|---|
As POST are usually called inside a form, it is a good idea to set the parameter in the body section of request. To do this, we must set the BODY section of POSTMAN, select www-form-urlencoded and set the parameters.
If we want an unlimited number of parameters, you can create an array, an create multiple parameters in POSTMAN with same name:
5.7. Variables in the path
If we want to get for a specific value, in the form of a vaule in the path, for instance GET films/1 instead of GET films?idFilm=1, the way is as follows:
| Java | |
|---|---|
The request will be as follows:
As we can see:
- In the java program we set in the path a
idWhoparameter. - In the java controller method we define that parameter as String to access it inside our method
- When we do the request, the value in the request will be transferred to the parameter.