Full Stack Build Part 1 - Building and Deploying an API
What you will learn
- Creating an API
- Setting Cors Headers
- Testing an API
- Deploying an API
Setup
- In VSCode use the Command Palette to generate a new spring project
- Add Spring Web, JPA and Postgres as dependencies
- add your database settings to application.properties
- reopen vscode in your projects folder
- hit f5 and try out your development server
Creating the API
Creating Our Todo Entitry
- Create an Entities Folder with Todo.Java
package learning.java.demo.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Todo {
//**************************************** */
// Entity Properties
//**************************************** */
@Id //Denotes this property as the id/primary key
@GeneratedValue(strategy = GenerationType.AUTO) //auto generates
public Integer id;
public String subject;
public String details;
//**************************************** */
// Constructors
//**************************************** */
public Todo(){
}
public Todo(String subject, String details){
this.subject = subject;
this.details = details;
}
//**************************************** */
// GETTERS AND SETTERS
//**************************************** */
public Integer getId(){
return this.id;
}
public void setId(Integer id){
this.id = id;
}
public String getSubject(){
return this.subject;
}
public void setSubject(String subject){
this.subject = subject;
}
public String getDetails(){
return this.details;
}
public void setDetails(String details){
this.details = details;
}
}
Create a New Repository
package learning.java.demo.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import learning.java.demo.entities.Todo;
// Our Repository, the two types in <> are the Entity and type of the ID
public interface TodoRepository extends JpaRepository<Todo, Integer>{
}
Creating Our Controller
Last we make our controller, this time we'll add the @CrossOrigins annotation to enable CORS Headers so our frontend can access the page.
package learning.java.demo.controllers;
import java.util.List;
import java.util.Optional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import learning.java.demo.repositories.TodoRepository;
import learning.java.demo.entities.Todo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
@RestController
public class TodoController {
// Property to hold Todo Repository
public TodoRepository Todos;
// Receive Todo Repository via Dependency Injection
public TodoController(TodoRepository Todos){
this.Todos = Todos;
}
// get request to /Todos
@CrossOrigin // Enable CORS <-
@GetMapping("/todos")
public List<Todo> index(){
return Todos.findAll();
}
// get request to /Todos/:id
@CrossOrigin // Enable CORS <-
@GetMapping("/todos/{id}")
public Optional<Todo> show(@PathVariable Integer id){
return Todos.findById(id);
}
@CrossOrigin // Enable CORS <-
@PostMapping("/todos")
public List<Todo> create(@RequestBody Todo newTodo){
Todos.save(newTodo); // Create the New Todo
return Todos.findAll();
}
@CrossOrigin // Enable CORS <-
@PutMapping("/todos/{id}")
public List<Todo> update(@RequestBody Todo fixTodo, @PathVariable Integer id){
// Find Todo by it's then use map to update it
Todos.findById(id).map(Todo -> {
Todo.setSubject(fixTodo.getSubject());
Todo.setDetails(fixTodo.getDetails());
Todos.save(Todo);
return Todo;
});
// return all Todos
return Todos.findAll();
}
@CrossOrigin // Enable CORS <-
@DeleteMapping("/todos/{id}")
public List<Todo> destroy(@PathVariable Integer id){
Todos.deleteById(id);
return Todos.findAll();
}
}
Testing the API
- Turn on your server with f5 (run > debugging)
- create 3 Todos with posts request to /todos
- see those todos with get request to /todos
- try and one todo with a get request to /todos/:id
- update a todo with a put request /todos/:id
- delete a todo with a delete request to /todos/:id
Deploying the API
- in the root of your project where the pom.xml lives add a system.properties file with the follow:
java.runtime.version=11
- Update your application.properties to receive the database details from an env variable list so.
# Database Settings
# spring.datasource.url=jdbc:postgresql://localhost:5432/javaspringtest
spring.datasource.url=${DATABASE_URL}
# spring.datasource.username=test5
# spring.datasource.password=test5
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
- commit and push to github.com
- go to Heroku and create a new project
- under deploys select deploy by Github
- connect your repo
- enable automatic deploys
- trigger a manual deploy
Now test your deployed app and your ready to go!