First app
Spring Initializr is recommended to generate a Spring Boot app.
-
Go to Spring Initializr.
-
Select Gradle - Kotlin for the project.
-
Select Java for the language.
-
Set the group and artifact.
-
Add the Spring Web dependency.
-
Click the Generate button and download the zip file.
-
Unzip the zip file on your computer.
-
Open the project with your IDE.
Notice the @SpringBootApplication-annotated class in src/main/java.
Since it contains the static method main, your IDE can run the class.
1package com.example.demo;
2
3import org.springframework.boot.SpringApplication;
4import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6@SpringBootApplication
7public class DemoApplication {
8
9 public static void main(String[] args) {
10 SpringApplication.run(DemoApplication.class, args);
11 }
12
13}To get a feel for how the Spring Boot programming model works, let’s create a REST controller.
1package com.example.demo;
2
3import org.springframework.web.bind.annotation.GetMapping;
4import org.springframework.web.bind.annotation.RequestMapping;
5import org.springframework.web.bind.annotation.RestController;
6
7@RestController
8@RequestMapping("/api/hello")
9class HelloController {
10
11 @GetMapping
12 String sayHello() {
13 return "Hello, World!";
14 }
15
16}-
@RestControllertells Spring Boot this class will handle HTTP requests. -
@RequestMappingmaps the controller to a URL. Since Spring Boot apps listen to port 8080 by default, the controller is mapped to http://localhost:8080/api/hello. -
@GetMappingis a specialization of@RequestMapping. It indicates that the method following it with respond to HTTP GET.
Using cURL or your browser, check that everything is working properly.
$ curl -X GET http://localhost:8080/api/hello
Hello, World!
To match part of the URL to a function parameter, use the @PathVariable annotation.
1 @GetMapping("/{name}")
2 String sayHello(@PathVariable("name") String name) {
3 return String.format("Hello, %s!", name);
4 }$ curl -X GET http://localhost:8080/api/hello/Oscar
Hello, Oscar!
Spring Boot can serialize Java objects over the wire. Let’s create a plain old Java object to illustrate this.
1package com.example.demo;
2
3import java.util.Date;
4import java.util.UUID;
5
6public class Event {
7
8 private final UUID id;
9
10 private final Date creationDate;
11
12 public Event(UUID id, Date creationDate) {
13 this.id = id;
14 this.creationDate = creationDate;
15 }
16
17 public UUID getId() {
18 return id;
19 }
20
21 public Date getCreationDate() {
22 return creationDate;
23 }
24
25}Let’s add a new method to the controller:
1 @GetMapping("/event")
2 Event getEvent() {
3 return new Event(UUID.randomUUID(), new Date());
4 }$ curl -X GET http://localhost:8080/api/hello/event
{"id":"ef1e0ace-c476-462e-a82b-676e566997a1","creationDate":"2025-09-16T13:57:38.298+00:00"}
By default, Spring Boot converts Java objects to JSON. However, Spring Boot supports many media types, including XML.
Let’s add the jackson-dataformat-xml dependency in build.gradle.kts:
1implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml")Let’s change the annotation to produce XML instead of JSON:
1 @GetMapping(value = "/event", produces = MediaType.APPLICATION_XML_VALUE)
2 Event getEvent() {
3 return new Event(UUID.randomUUID(), new Date());
4 }$ curl -X GET http://localhost:8080/api/hello/event
<Event><id>970030e8-52eb-4dcb-b83d-342b70f8960e</id><creationDate>2025-09-16T14:00:57.496+00:00</creationDate></Event>
|
Note
|
If com.fasterxml.jackson.dataformat:jackson-dataformat-xml is present in the dependencies set in file build.gradle.kts, then by default the values sent to the client will be serialized in XML.
|
To create a resource in the system, we should POST to the collection endpoint.
If the creation was a success, the server should send the HTTP code 201 and the Location header set to the URL of the created resource.
1import org.springframework.http.HttpStatus;
2import org.springframework.http.ResponseEntity;
3import org.springframework.web.bind.annotation.GetMapping;
4import org.springframework.web.bind.annotation.PathVariable;
5import org.springframework.web.bind.annotation.PostMapping;
6import org.springframework.web.bind.annotation.RequestBody;
7import org.springframework.web.bind.annotation.RequestMapping;
8import org.springframework.web.bind.annotation.RestController;
9import org.springframework.web.server.ResponseStatusException;
10import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
11
12import java.net.URI;
13import java.util.List;
14
15@RestController
16@RequestMapping("/api/products")
17public class ProductController {
18
19 private final ProductRepository productRepository;
20
21 public ProductController(ProductRepository productRepository) {
22 this.productRepository = productRepository;
23 }
24
25 @GetMapping
26 public List<Product> getProducts() {
27 return productRepository.findAll();
28 }
29
30 @GetMapping("/{id}")
31 public Product getProduct(@PathVariable("id") Long id) {
32 return productRepository.findById(id)
33 .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
34 }
35
36 @PostMapping
37 public ResponseEntity<?> createProduct(@RequestBody Product product) {
38 Product result = productRepository.save(product);
39 URI location = ServletUriComponentsBuilder
40 .fromCurrentRequest().path("/{id}")
41 .buildAndExpand(result.getId()).toUri();
42 return ResponseEntity.created(location).build();
43 }
44
45}|
Note
|
Repositories will be seen in a later session. |