# Spring Boot - Create a Simple Rest API

Get familiar with the Spring Initializr interface by creating a simple Spring Boot Web application.

Time: 25 minutes.

## Directory Web App

1. Open a browser and hit the url: http://start.spring.io

2. Click the Switch to the full version link.

3. Fill out the Directory Web App Project metadata with (See Figure 1.0):

   Table 1. Directory Web App - metadata
   Property | Value
   --- | ---
   Group: | io.pivotal.workshop
   Artifact: | directory-web
   Name: | directory-web
   Package Name: | io.pivotal.workshop.directory
   Dependencies: | Web
   Spring Boot: | 2.0.0.M7

   Figure 1.0: Spring Initializr - http://start.spring.io

   Tip | You can choose either Maven or Gradle project types.

4. Type Web in the Dependencies field and press Enter.

5. Click the Generate Project button.

6. Unzip the file in any directory you want.

7. Import your project in any IDE you want.

8. Once imported, review the pom.xml file (or build.gradle).

   maven - pom.xml

       <?xml version="1.0" encoding="UTF-8"?>
       <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="
           http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
               <modelVersion>4.0.0</modelVersion>

               <groupId>io.pivotal.workshop</groupId>
               <artifactId>directory-web-app</artifactId>
               <version>0.0.1-SNAPSHOT</version>
               <packaging>jar</packaging>

               <name>directory-web-app</name>
               <description>Demo project for Spring Boot</description>

               <parent>
                       <groupId>org.springframework.boot</groupId>
                       <artifactId>spring-boot-starter-parent</artifactId>
                       <version>2.0.0.RC1</version>
                       <relativePath/> <!-- lookup parent from repository -->
               </parent>

               <properties>
                       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
                       <java.version>1.8</java.version>
               </properties>

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

                       <dependency>
                               <groupId>org.springframework.boot</groupId>
                               <artifactId>spring-boot-starter-test</artifactId>
                               <scope>test</scope>
                       </dependency>
               </dependencies>

               <build>
                       <plugins>
                               <plugin>
                                       <groupId>org.springframework.boot</groupId>
                                       <artifactId>spring-boot-maven-plugin</artifactId>
                               </plugin>
                       </plugins>
               </build>

           <repositories>
                       <repository>
                               <id>spring-milestones</id>
                               <name>Spring Milestones</name>
                               <url>https://repo.spring.io/libs-milestone</url>
                               <snapshots>
                                       <enabled>false</enabled>
                               </snapshots>
                       </repository>
               </repositories>

       </project>

   Remember the Spring Boot components:

   - spring-boot-starter-parent

   - dependencies: spring-boot-starter-web

   - plugin: spring-boot-maven-plugin

   gradle - build.gradle

       buildscript {
               ext {
                       springBootVersion = '2.0.0.RC1'
               }
               repositories {
                       mavenCentral()
               maven { url "https://repo.spring.io/snapshot" }
                       maven { url "https://repo.spring.io/milestone" }
               }
               dependencies {
                       classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
               }
       }

       apply plugin: 'java'
       apply plugin: 'eclipse'
       apply plugin: 'org.springframework.boot'
       apply plugin: 'io.spring.dependency-management'

       version = '0.0.1-SNAPSHOT'
       sourceCompatibility = 1.8

       repositories {
               mavenCentral()
           maven { url "https://repo.spring.io/snapshot" }
               maven { url "https://repo.spring.io/milestone" }
       }

       dependencies {
               compile('org.springframework.boot:spring-boot-starter-web')
               testCompile('org.springframework.boot:spring-boot-starter-test')
       }

9. Create the domain io.pivotal.workshop.directory.domain.Person class.

   io.pivotal.workshop.directory.domain.Person.java

       package io.pivotal.workshop.directory.domain;

       import java.text.ParseException;
       import java.text.SimpleDateFormat;
       import java.util.Date;
       import java.util.UUID;

       import javax.validation.constraints.NotNull;

       public class Person {

               private SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd");

               private String id;

               @NotNull
               private String email;
               @NotNull
               private String name;
               @NotNull
               private String password;
               private Date birthday;
               private Date created;
               private Date modified;

               public Person(){
                       this.id = UUID.randomUUID().toString().replaceAll("-", "");
                       this.created = new Date();
                       this.modified = new Date();
               }

               public Person(String email, String name, String password, String birthday) {
                       this();
                       this.email = email;
                       this.name = name;
                       this.password = password;

                       try {
                               this.birthday = date.parse(birthday);
                       } catch (ParseException e) {
                               this.birthday = null;
                       }
               }

               public Person(String email, String name, String password, Date birthday) {
                       this();
                       this.email = email;
                       this.name = name;
                       this.password = password;
                       this.birthday = birthday;
               }

               public String getId() {
                       return id;
               }

               public void setId(String id) {
                       this.id = id;
               }

               public String getEmail() {
                       return email;
               }

               public void setEmail(String email) {
                       this.email = email;
               }

               public String getName() {
                       return name;
               }

               public void setName(String name) {
                       this.name = name;
               }

               public String getPassword() {
                       return password;
               }

               public void setPassword(String password) {
                       this.password = password;
               }

               public Date getBirthday() {
                       return birthday;
               }

               public void setBirthday(Date birthday) {
                       this.birthday = birthday;
               }

               public Date getCreated() {
                       return created;
               }

               public void setCreated(Date created) {
                       this.created = created;
               }

               public Date getModified() {
                       return modified;
               }

               public void setModified(Date modified) {
                       this.modified = modified;
               }

       }

10. Create the io.pivotal.workshop.directory.repository.DirectoryRepository class. This is you in-memory persistence.

    io.pivotal.workshop.directory.repository.DirectoryRepository.java

        package io.pivotal.workshop.directory.repository;

        import java.util.ArrayList;
        import java.util.List;

        import org.springframework.stereotype.Repository;

        import io.pivotal.workshop.directory.domain.Person;

        @Repository
        public class DirectoryRepository {

                @SuppressWarnings("serial")
                private List<Person> directory = new ArrayList<Person>(){{
                add(new Person("john@email.com","John S","password","1985-11-10"));
                        add(new Person("mike@email.com","Mike H","password","1984-12-02"));
                        add(new Person("dan@email.com","Dan B","password","1983-03-07"));
                        add(new Person("bill@email.com","Bill G","password","1983-06-12"));
                        add(new Person("mark@email.com","Mark S","password","1986-02-22"));
                }};

                public Iterable<Person> findAll(){
                        return this.directory;
                }

        }

11. Create the io.pivotal.workshop.directory.controller.DirectoryController class. This will handle your REST API.

    io.pivotal.workshop.directory.controller.DirectoryController.java

        package io.pivotal.workshop.directory.controller;

        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.http.ResponseEntity;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;

        import io.pivotal.workshop.directory.domain.Person;
        import io.pivotal.workshop.directory.repository.DirectoryRepository;

        @RestController
        public class DirectoryController {

                private DirectoryRepository repo;

                @Autowired
                public DirectoryController(DirectoryRepository repo){
                        this.repo = repo;
                }

                @RequestMapping("/directory")
                public ResponseEntity<Iterable<Person>> findAll(){
                        return ResponseEntity.ok(this.repo.findAll());
                }

        }

12. Run your application and test the /directory endpoint by open a browser and hit: http://localhost:8080/directory

Tip | If you are not using any IDE, then you can run your application with maven: ./mvnw spring-boot:run or if you are using gradle: ./gradlew bootRun

## Challenges

So far this is a very simple application, but still missing some of the HTTP request methods:

- Add a index.html page to be render as Home page (tip: src/main/resources/static).

- Add the POST method for adding a new person (tip: Use the @RequestBody annotation).

- Add the PUT method for updating a new person (tip: Use the @RequestBody annotation).

- Add the DELETE method for removing a person by id (tip: Use the @PathVariable annotation).

- Add a GET method for search by email (tip: Use the @RequestParam annotation).

- Add a GET method for finding by Id (tip: Use the @PathVariable annotation).

do any necessary changes to the classes.

### [EXTRA - OPTIONAL] Challenges

- Mask the password when getting a directory JSON object.

- The /directory endpoint response as a JSON object and the dates are show as a long type. Modify it to get a formatted 'yyyy-MM-dd' date.

- By default Spring Boot serialize automatically a JSON object, add a XML serialization too.

### HOMEWORK

- Add validation to the Person object when doing POST or UPDATE.