# Lab 03 : Getting started with Spring Boot applications

# Useful commands 

``` mvn spring-boot:run ```  
```bash
run --name postgresdb -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=meals_db -p 5432:5432 -d postgres:latest
```
``` nc -zv 127.0.0.1 5432 ``` 


# 1. What is Springboot

Spring Boot is a convention-over-configuration framework layer that sits on top of the Spring framework. It makes it easy to create stand-alone, production-grade Spring-based applications that run effortlessly.  
Even though it simplifies setup and speeds up development, it remains extremely realiable, being one of the most widely used frameworks for building Java enterprise applications today (software systems for banks, hospitals, governaments, etc), where many users, large amounts of data and critical business processes are handled.

Although Jakarta EE can be considered its competitor in the enterprise Java scene, Spring Boot doesn't replace it, instead, it can integrate and build upon Jakarta components, making them complementary.

Spring Boot includes several automatic configurations that boost our productivity, such as: 
- an embedded web server
- default data sources
- built-in JSON serialization/deserialization
- automatic component scanning  
  
Earlier in the course, we learned how to write unit tests with mocks, how to deal with HTTP clients and remote services, and how to apply dependencies to make code more modular and testable. Being Spring Boot the next step, it incorporates all the previous lessons, allowing us to combine them into a full enterprise-grade application with minimal setup.

<br>
<br>

# 2. Spring boot application

## 2.1 Initialize the project
Navigate to https://start.spring.io or start a new Spring Boot project in your IDE (in dependencies, include Spring Web)  

## 2.2 Create a Resource Representation Class
Think about the service interactions.   
In this example, the service will handle **GET** requests for **/greeting** (with an optional **name** parameter).  
It will return the **id of the greeting** and the **message** (long id, String content)
  
```java
public record Greeting(long id, String content) { }
```

<br>

## 2.3 Create a Resource Controller
HTTP requests are handled by a controller (using ```@RestController```).  
This way, the **GreetingController** class, handles GET requests for /greeting, by returning a **new instance of Greeting class**.  
The ```@GetMapping``` annotation ensures that HTTP GET requests to /greeting are mapped to the greeting() method.

```java
@RestController
public class GreetingController {

	private static final String template = "Hello, %s!";
	private final AtomicLong counter = new AtomicLong();

	@GetMapping("/greeting")
	public Greeting greeting(@RequestParam(defaultValue = "World") String name) {
		return new Greeting(counter.incrementAndGet(), String.format(template, name));
	}
}
```

<br>


## 2.4 Run the Service
This class is automatically created when starting the project and acts as **main()**

```java
@SpringBootApplication
public class RestServiceApplication {

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

}
```

To build the executable jar with Maven and run directly the application, use:
```
mvn spring-boot:run
```
This way, the application is running under the Tomcat server, in the port 8080.

To test, open  http://localhost:8080/greeting


<br>

## 3. Folder and Files breakdown

### 3.1. data/ - Persistence Layer

**Purpose:** Handles database interactions (CRUD operations).
Defines how bookings are **stored**, **retrieved**, and **mapped** to tables.


| **Type** | **Description** |
|-----------|-----------------|
| `@Entity` | Represents a database table, with fields like `userId`, `date`, and `state`. |
| `@Repository` | Extends `JpaRepository` or `CrudRepository`, giving access to built-in CRUD methods (`save`, `findById`, etc.). |

#### 3.1.1. Example @Entity (bookings table)
```java

@Entity
@Table(name = "bookings")
public class Bookings {
    
    public enum bState{
        ACTIVE, CANCELED, USED
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String userId;

 	@Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private bState state = bState.ACTIVE;

	public Bookings() {}

    public Bookings(String userId, LocalDate date, String shift) {
        this.userId = userId;
        this.date = date;
        this.shift = shift;
        this.state = bState.ACTIVE;
    }

	//setters and getters
}
```

<br>

### 3.2. service/ - Business Logic Layer

**Purpose:** Encapsulates the core logic of the application
Decides what should happen when the controller receives a request.


| **Type** | **Description** |
|-----------|-----------------|
| `@Service` | Implements the business rules. |

#### 3.2.1. Example @Service (User service)
```java
@Service
public class UserServiceImpl UserServiceImpl implements UserService{

    @Autowired
    private UserRepository userRepository;

    public Optional<User> getUserDetails(Long id) {
        return userRepository.findById(id);
    }

    @Override
    public Optional<User> getUserByUsername(String username) {
        return Optional.ofNullable(userRepository.findByUsername(username));
    }

    @Override
    public boolean exists(String username) {
        return userRepository.findByUsername(username) != null;
    }

    @Override
    public User save(User user) {
        return userRepository.save(user);
    }

    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public void deleteUser(User user) {
        userRepository.delete(user);
    }
}
```

<br>


### 3.3. boundary/ - Web/API Layer

**Purpose:** Defines the REST API endpoints.  
The controller receives HTTP requests, validates input, and calls the service layer.


| **Type** | **Description** |
|-----------|-----------------|
| `@RestController` | Exposes API endpoints for creating bookings (`POST /bookings`), retrieving them (`GET /bookings`), and updating their state (`PUT /bookings/{id}/cancel`). |

#### 3.3.1. Example @RestController (/bookings)

```java
@RestController
@RequestMapping("/bookings")
public class MealsbookingController {

    private final MealsbookingService service;

    public MealsbookingController(MealsbookingService service) {
        this.service = service;
    }


    // POST — create a new booking
    @PostMapping
    public ResponseEntity<Bookings> createBooking(@RequestBody Bookings request) {
        Bookings created = service.bookMeal(request);
        return ResponseEntity.ok(created);
    }

    //GET — retrieve booking by ID
    @GetMapping("/{id}")
    public ResponseEntity<Bookings> getBookingById(@PathVariable(value = "id") Long id) {
        return service.findBooking(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}
```

<br>

### 3.4. ./ - Application Entry Point

**Purpose:** Starts and configures the Spring Boot application.  
This class contains the `main()` method and triggers **component scanning**, allowing Spring to discover your controllers, services, and repositories automatically.

| **Type** | **Description** |
|-----------|-----------------|
| `@SpringBootApplication` | Main entry point for the Spring Boot app. It runs the embedded server (Tomcat by default) and initializes all components. |

<br>


## 4. Useful REST API Annotations

| **Annotation** | **Used On** | **Purpose** |
|----------------|-------------|--------------|
| `@RestController` | Class | Defines a REST controller — handles HTTP requests and returns JSON responses. |
| `@RequestMapping("/path")` | Class / Method | Defines a base URL for endpoints. |
| `@GetMapping("/path")` | Method | Handles **GET** requests. |
| `@PostMapping("/path")` | Method | Handles **POST** requests. |
| `@PutMapping("/path")` | Method | Handles **PUT** requests. |
| `@DeleteMapping("/path")` | Method | Handles **DELETE** requests. |
| `@PathVariable` | Method parameter | Extracts a **path value** from the URL (e.g., `/users/{id}`). |
| `@RequestParam` | Method parameter | Gets **query parameters** from the URL (e.g., `?name=Ana`). |
| `@RequestBody` | Method parameter | Maps the **HTTP request body** (usually JSON) to a Java object. |
| `@ResponseStatus(HttpStatus.OK)` | Method / Class | Sets a **custom HTTP status code** for the response. |
|
 
<br>

## 5. Some important dependencies 

| **Component** | **Library / Dependency** | **Purpose / Description** |
|----------------|--------------------------|----------------------------|
| **Spring Data JPA** | `spring-boot-starter-data-jpa` | Lets the **Spring framework API**  interact with relational databases. |
| **Jakarta Persistence (JPA)** | `spring-boot-starter-data-jpa` | The **Java Persistence API**, a standard specification for managing relational data in Java applications. |
| **Database drivers** | `com.h2database:h2` and `org.postgresql:postgresql` | Provide the actual **connection drivers** for the databases used. **H2 is an in-memory test database**; **PostgreSQL is a full production relational database**. |

<br>
<br>


# 6. Application Properties for PostgreSQL and Hibernate

```
# PostgreSQL database configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/meals_db
spring.datasource.username=admin
spring.datasource.password=secret
platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true

# Hibernate (JPA) configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
``` 
