You are on page 1of 20

Chapter 1.

Spring

I. Introduction
Spring is a Java framework for building web applications.

Spring has several libraries (or projects), such as:

- Spring Boot: Takes an opinionated view of building Spring applications and gets you up and
running as quickly as possible.
- Spring Framework: Provides core support for dependency injection, transaction management,
web apps, data access, messaging, and more.
- Spring Data: Provides a consistent approach to data access – relational, non-relational, map-
reduce, and beyond.
- Spring Cloud: Provides a set of tools for common patterns in distributed systems. Useful for
building and deploying microservices.
- Spring Cloud Data Flow: Provides an orchestration service for composable data microservice
applications on modern runtimes.
- Spring Security: Protects your application with comprehensive and extensible authentication
and authorization support.
- Spring Authorization Server: Provides a secure, light-weight, and customizable foundation for
building OpenID Connect 1.0 Identity Providers and OAuth2 Authorization Server products.
- Spring for GraphQL: Spring for GraphQL provides support for Spring applications built on
GraphQL Java.
- Spring Session: Provides an API and implementations for managing a user’s session information.
- Spring Integration: Supports the well-known Enterprise Integration Patterns through lightweight
messaging and declarative adapters.
- Spring Web Services: Facilitates the development of contract-first SOAP web services.

See: https://spring.io/projects

 The term "Spring" means different things in different contexts. It can be used to refer to the
Spring Framework project itself. Most often, when people say "Spring", they mean the entire
family of projects. (link: https://docs.spring.io/spring-framework/reference/overview.html)

1
II. Spring Framework
The current version of Spring Framework is 6.1.3. As of Spring Framework 6.0, Spring requires Java 17+.

Spring supports different programming languages: Java, Kotlin and Groovy.

The Spring Framework uses Beans. It supports the Dependency Injection and Common Annotations.

Features:

 Core technologies: dependency injection, events, resources, i18n, validation, data binding, type
conversion, SpEL, AOP.

 Testing: mock objects, TestContext framework, Spring MVC Test, WebTestClient.

 Data Access: transactions, DAO support, JDBC, ORM, Marshalling XML.

 Spring MVC and Spring WebFlux web frameworks.

 Integration: remoting, JMS, JCA, JMX, email, tasks, scheduling, cache and observability.

 Languages: Kotlin, Groovy, dynamic languages.

1. Annotations

An annotation looks like the following:

@Entity

The at sign character (@) indicates to the compiler that what follows is an annotation. In the following
example, the annotation's name is Override:

@Override
void mySuperMethod() {
}

2
The annotation can include elements, which can be named or unnamed, and there are values for those
elements:

@Author(name = "Ali Dridi", date = "3/27/2003")


class MyClass {
}

or

@SuppressWarnings(value = "unchecked")
void myMethod() {
}

If there is just one element named value, then the name can be omitted, as in:

@SuppressWarnings("unchecked")
void myMethod() {
}

If the annotation has no elements, then the parentheses can be omitted, as shown in the previous
@Override example.

It is also possible to use multiple annotations on the same declaration:

@Author(name = "Jane Doe")


@EBook
class MyClass {
}

The annotation type can be one of the types that are already defined. In the previous examples,
Override and SuppressWarnings are predefined Java annotations. It is also possible to define your own
annotation type. The Author and Ebook annotations in the previous example are custom annotations.

Where Annotations Can Be Used

Annotations can be applied to declarations: declarations of classes, fields, methods, and other program
elements.

3
2. Beans

A Spring Application is composed of components. These components are called “beans”.

There are several types of beans: @Component, @Service, @Repository, @Controller,


@RestController and others.

The following example shows a @RestController Bean:

@RestController
public class HomeController {
@GetMapping
public String index() {
return "hello world";
}
}

 To scan and register the application beans, it is necessary to add @ComponentScan or


@SpringBootApplication annotation (which implicitly includes @ComponentScan) to the main
class (the application class)
 The main class should be located in a top package

Example:

@SpringBootApplication
public class WebapiApplication {
public static void main(String[] args) {
SpringApplication.run(WebapiApplication.class, args);
}
}

3. Dependency injection

Dependency injection (DI) is a process where objects define their dependencies (that is, the other
objects they need). The container then injects those dependencies when it creates the bean.

4
A class can define its dependencies in different ways:

- constructor arguments
- arguments to a method, or
- fields annotated with @Autowired

Constructor-based Dependency Injection

Constructor-based DI is accomplished by the container invoking a constructor with a number of


arguments, each representing a dependency. The following example shows a class that can be
dependency-injected with constructor injection:

public class SimpleMovieLister {


// the SimpleMovieLister has a dependency on a MovieFinder
private final MovieFinder movieFinder;

// a constructor so that the Spring container can inject a MovieFinder


public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}

Annotation-based Dependency Injection

The following example shows a class that can be dependency-injected with @Autowired annotation:

public class SimpleMovieLister {


@Autowired
private final MovieFinder movieFinder;
}

4. RESTful web API

Spring is mainly used to create REST Web Services (RESTful Web API). It lets you create special
@RestController beans to handle incoming HTTP requests. Methods in your controller are mapped to
HTTP by using @RequestMapping annotations.

The following code shows a typical @RestController that serves JSON data:

5
@RestController
@RequestMapping("/users")
public class MyRestController {
private final UserRepository userRepository;

public MyRestController(UserRepository userRepository) {


this.userRepository = userRepository;
}

@GetMapping
public List<User> getUsers() {
return this.userRepository.findAll();
}

@GetMapping("/{userId}")
public User getUser(@PathVariable Long userId) {
return this.userRepository.findById(userId).get();
}

@PostMapping
public void createUser(@RequestBody User user) {
// create user
}

@PutMapping("/{userId}")
public User updateUser(@PathVariable Long userId, @RequestBody User user)
{
// update user
}

@DeleteMapping("/{userId}")
public void deleteUser(@PathVariable Long userId) {
this.userRepository.deleteById(userId);
}
}

5. Spring MVC

The Spring Web MVC framework (often referred to as “Spring MVC”) is a rich “model view controller”
web framework.

Spring MVC lets you create special @Controller or @RestController beans to handle incoming HTTP
requests.

6
Spring MVC allows us to serve dynamic HTML content. It supports a variety of templating technologies,
including:

- Thymeleaf
- JSP
- FreeMarker
- Groovy
- Mustache

 If possible, JSPs should be avoided. There are several known limitations when using them with
embedded servlet containers.

When you use one of these templating engines with the default configuration, your templates are
picked up automatically from src/main/resources/templates.

III. Spring Boot


Link: https://spring.io/projects/spring-boot

Spring Boot makes it easy to create Spring based Applications that you can "just run".

Most Spring Boot applications need minimal Spring configuration.

Features

- Create stand-alone Spring applications


- Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
- Provide opinionated 'starter' dependencies to simplify your build configuration
- Automatically configure Spring and 3rd party libraries whenever possible
- Provide production-ready features such as metrics, health checks, and externalized
configuration
- Absolutely no code generation and no requirement for XML configuration

Getting Started

- Super quick — try the Quickstart Guide.


- More general — try Building an Application with Spring Boot
- More specific — try Building a RESTful Web Service.
- Or search through all our guides on the Guides homepage.

7
1. Create new project

The easiest way to create a new project is using Spring initializr: https://start.spring.io/

We choose Maven as the project building tool, and Java as the programming language

Select the Spring boot version

Fill the project metadata:

- Group : name of the application owner (or his reversed domain name)
- Artifact: the application name (Artifact = Name)

The selected Java version should be installed on your computer

Add the project dependencies based on your needs

Generate the Zip file, extract it and open it using your IDE

8
2. Project Structure

Required tools:

- IDE
o
IntelliJ IDE
o
Eclipse IDE for Enterprise Java and Web Developers:
https://www.eclipse.org/downloads/packages/
o VS Code + Java Extension Pack + Spring Boot Extension Pack
- Postman

9
TP 1

1) Installer les outils suivants :


a. Installer l’IDE de votre choix parmi les options suivantes : Eclipse Enterprise, IntelliJ
IDEA ou VS Code. Dans le cas de VS Code, il faut installer l’extension « Extension Pack
for Java » et s’assurer que la JDK Java est installée (version minimale 17)
b. Postman

2) Créer un nouveau projet Spring Boot avec Spring initializr :


a. Group : com.fsm
b. Artifact : webapi
c. Dépendances : Spring Web + Spring Boot DevTools

3) Ouvrir le projet avec un IDE et créer les packages « controllers » (com.fsm.webapi.controllers)


et « services » (com.fsm.webapi.services)

4) Créer un RestController dans le package « controllers » et nommer le « HomeController ». Il


doit être accessible à l’url « /home ». Remarque : un RestController est une classe Java annotée
par @RestController.

5) Créer 4 méthodes publiques dans « HomeController » :


a. Ces méthodes doivent être accessibles à l’url « /home » en utilisant les 4 méthodes
http : Get, Post, Put et Delete.
b. Chaque méthode retourne une chaine de caractères avec le nom de la méthodes http
utilisée (Get, Post, Put ou Delete)

6) Créer la classe « LogHelper » dans le package « services » :


a. Enregistrer cette classe en tant que bean de type service (la classe doit être annotée par
@Service)
b. Créer la méthode publique log() qui permet d’afficher la date sur la console

7) Injecter l’objet « LogHelper » dans le contrôleur « HomeController » en utilisant l’annotation


@Autowired. Utiliser cet objet dans les différentes méthodes du contrôleur.

10
Chapter 2. Spring Web

I. Controllers
Link : https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller.html

1. Declaration

Spring Web provides an annotation-based programming model where @Controller and


@RestController components use annotations to express request mappings, request input, exception
handling, and more.

You can define controller beans by using the @Controller annotation.

@RestController is a composed annotation that is itself annotated with @Controller and


@ResponseBody to indicate a controller whose every method inherits the @ResponseBody annotation
and, therefore, writes directly to the response body and does not render an HTML view.

The following example shows a REST controller defined by annotations:

@RestController
public class HelloController {

@GetMapping("/hello")
public String handle() {
return "Hello World!";
}
}

In the preceding example, the method is accessible using the HTTP GET method at the URL “/hello” and
returns a String.

2. API Endpoint

An API endpoint is a URL that acts as the point of contact between a client and a server:

- Clients send requests to API endpoints in order to access the API’s functionality and data.
- A typical REST API has many endpoints that correspond to its available resources.

11
For example, a REST API for blogging application might have the following URLs endpoints:

- “/authors” : This URL has 2 endpoints:


o GET: to retrieve a list of authors
o POST: to create a new authors
- “/authors/:id” : This URL has 3 endpoints:
o GET: to retrieve a specific author
o PUT: to update an existing author
o DELETE: to delete a specific author
- “/articles” : This URL has 2 endpoints:
o GET: to retrieve a list of articles
o POST: to create a new article
- “/articles/:id” : This URL has 3 endpoints:
o GET: to retrieve a specific article
o PUT: to update an existing article
o DELETE: to delete a specific article

 An endpoint is also called a “route”

3. Mapping Requests

You can use the @RequestMapping annotation to map requests to controller methods. You can use it at
the class level to express shared mappings or at the method level to express a specific endpoint
mapping.

The following example creates an endpoint accessible using the HTTP GET method at the URL “/

There are also HTTP method specific shortcut variants of @RequestMapping:

 @GetMapping
 @PostMapping
 @PutMapping
 @DeleteMapping
 @PatchMapping

The shortcuts are mainly used with controller methods while @RequestMapping is usually needed at
the class level to express shared mappings.

12
The following example has class and method level mappings:

@RestController
@RequestMapping("/books")
public class BooksController {

@GetMapping
public String getBooks() {
return "getBooks";
}

@GetMapping("list")
public String getBooks2() {
return "getBooks2";
}

@GetMapping({"/get", "getAll", "getAll/"})


public String getBooks3() {
return "getBooks3";
}
}

The method “getBooks” is accessible at the URL “/books”

The method “getBooks2” is accessible at the URL “/books/list” (URL “/books/list/” is not defined)

The method “getBooks3” is accessible at the URL “/books/get”, “/books/getAll” and “/books/getAll/”

Methods annotated with @RequestMapping (and its shortcuts) can be mapped using URL patterns.
Example: "/projects/{project}/versions" - match a URL segment (project) and capture it as a variable.

Captured URL variables can be accessed with @PathVariable. For example:

@GetMapping("/owners/{ownerId}/pets/{petId}")
public String findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}

4. Handler Methods

Controller methods annotated with @RequestMapping (or its shortcuts) are called handler methods.

13
The method arguments are called the method signature.

Handler methods have a flexible signature and can choose from a range of supported arguments and
return values.

a. Method Arguments

The next table describes several supported controller method arguments:


signatures
Controller method argument Description
HttpMethod The HTTP method of the request.
@PathVariable For access to URI template variables
@MatrixVariable For access to name-value pairs in URI path segments. See Matrix
Variables.
@RequestParam For access to the request parameters, including multipart files.
Parameter values are converted to the declared method argument
type. Note that use of @RequestParam is optional for simple
parameter values.
@RequestBody For access to the HTTP request body. Body content is converted to
the declared method argument type.
Errors, BindingResult For access to errors from the validation of a @RequestBody or
@RequestPart arguments. You must declare an Errors, or
BindingResult argument immediately after the validated method
argument.

The complete list of supported controller method arguments is available at this link.
/data/list?abc=15&test=bonjour&xyz=2024

Example 1:

@RestController
@RequestMapping("/books")
public class BooksController {

@GetMapping
public String getBooks(
@RequestParam String author,
@RequestParam(defaultValue = "all") String category) {
return "Get Books of " + author + " - category : " + category;
}
}

14
The response of a GET request to http://localhost/books?author=Ali&category=Science is: Get Books
of Ali - category : Science

The response of a GET request to http://localhost/books?author=Ali is: Get Books of Ali - category : all

Example 2:

@RestController
@RequestMapping("/books")
public class BooksController {

@PutMapping("{id}")
public String updateBook(
@PathVariable int id,
@RequestBody Book book) {
return "id=" + id + " - title: " + book.getTitle();
}
}

Request and Response using Postman:

15
b. Return Values

The complete list of supported controller method return values is available at this link. The next table
describes some of them:

Return value Description


@ResponseBody The return value is transmitted in the response body. This type is
already used by @RestController, which is an annotation marked
with @Controller and @ResponseBody.
HttpEntity<B>, ResponseEntity<B> The return value that specifies the full response (including HTTP
headers and body) is to be written to the response.
HttpHeaders For returning a response with headers and no body.
void indicates “no response body”
String Returns a string
Model objects A Java object that can be converted into a JSON object
List A list of values that can be converted into a JSON array
Map A list of pairs <key, value> that can be converted into a JSON
object

Example 1:

@GetMapping("/titles")
public List<String> getTitles() {
List<String> titles = new ArrayList<String>();
titles.add("title1");
titles.add("title2");
titles.add("title3");

return titles;
}

Response:

[
"title1",
"title2",
"title3"
]

model un class pour stocker les donné

16
Example 2:

@GetMapping("/books/best")
public Book getBestBook() {
Book book = new Book();
book.setTitle("Spring Boot Guide");
book.setAuthor("Ali Dridi");
book.setIsbn("45874584211");
book.setPrice(78.9);

return book;
}

Response:

{
"title": "Spring Boot Guide",
"author": "Ali Dridi",
"isbn": "45874584211",
"price": 78.9
}

Example 3:

@GetMapping("{id}")
public ResponseEntity<Object> getBook(@PathVariable int id) {
Book book = new Book();
book.setTitle("Spring Boot Guide");
book.setAuthor("Ali Dridi");
book.setIsbn("45874584211");
book.setPrice(78.9);

if (id < 1) return ResponseEntity.badRequest().body("Bad id");


if (id == 1) return ResponseEntity.ok(book);
return ResponseEntity.notFound().build();
}

Response to http://localhost:8080/books/0 :

17
c. Validation

Link: https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-
validation.html

Method parameters such as @RequestBody and @RequestPart do perform validation if annotated with
Jakarta’s @Valid or Spring’s @Validated annotation, and raise MethodArgumentNotValidException in
case of validation errors. If you want to handle the errors in the controller method instead, you can
declare an Errors or BindingResult method parameter immediately after the validated parameter.

To use data validation, we need to :

- Add the “Validation” dependency to the project. It can be added while creating a new
project using Spring initializr, or you can add the following tag to “pom.xml”:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

- Create a new Model and annotate its fields using the appropriate annotations, example:

public class Book {


@NotEmpty(message = "The title is required")
@Size(min = 2, max = 100)
private String title;

@NotEmpty @Size(min = 2, max = 100)


private String author;

@NotEmpty @Size(min = 8, max = 15)


private String isbn;

@Min(0)
private double price;

// create getters and setters


}

- Add the @Valid annotation to method parameters such as @RequestBody. This will raise
MethodArgumentNotValidException in case of validation errors.

18
- To handle the errors in the controller method instead, you can declare a BindingResult
method parameter immediately after the validated parameter, example:

@PostMapping
public ResponseEntity<Object> createBook(
@Valid @RequestBody Book book,
BindingResult result
) {

if (result.hasErrors()) {
var errorsList = result.getAllErrors();
var errorsMap = new HashMap<String, String>();

for(int i = 0; i < errorsList.size(); i++) {


var error = (FieldError) errorsList.get(i);
errorsMap.put(error.getField(), error.getDefaultMessage());
}

return ResponseEntity.badRequest().body(errorsMap);
}

return ResponseEntity.ok(book);
}

19
TP 2

1) Add the “Validation” dependency to the “webapi” project by adding the following xml tag to
“pom.xml”:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2) Create the “models” package and add 2 models in this package: Product and ProductDto.
ProductDto has the following fields: String name, String brand, String category, double price,
String description
All these fields are private and required. Generate the getters and setters using the IDE. The
Product model has the same fields in addition to the “int id” and “Date createdAt”.

3) Create a @RestController called “ProductsController” in the “controllers” package


- This controller should be accessible at the url “/products”
- Create a private field to store the products:
List<Product> products = new ArrayList<Product>();
- Create the handler method “getProducts” (route “/products + GET”) that returns the list
of products
- Create the handler method “getProduct” (route “/products/{id} + GET”) that returns the
product by id. If the product is not found, the method returns the http response “not
found”.
- Create the handler method “createProduct” (route “/products + POST”). It requires a
valid ProductDto object. If the object is not valid, it returns “bad request” with the
validation errors. Otherwise, it creates a Product object using the ProductDto object and
add it to the products list. Then, it returns the created product.
- Create the handler method “updateProduct” (route “/products/{id} + PUT”). It requires
a valid ProductDto object. If the object is not valid, it returns “bad request” with the
validation errors. If the product id is not found in the products list, it returns “not
found”. Otherwise, it updates the product in the products list and returns the updated
product.
- Create the handler method “deleteProduct” (route “/products/{id} + DELETE”). If the
product id is not found in the products list, it returns “not found”. Otherwise, it deletes
the product and returns an empty success response by calling the statement:
return ResponseEntity.ok().build();

dto=data transfert object 20

You might also like