SpringBoot - My First CRUD Web Server
Click here to view details about Spring annotations.
Generate Project
- Navigate to
start.spring.io
- Select the following dependencies:
Web Tools
Spring Data JPA
H2 Database
- Press the
Download
button - Navigate to the
~/Downloads
directory view the newly downloadeddemo.zip
file. - Unzip the
demo.zip
directory to extract the contents of the newly downloaded file to a folder nameddemo
. - Navigate to the newly extracted
demo
folder. - Execute
mvn spring-boot:run
from the root directory ofdemo
folder to verify that the application can be built by maven - Navigate to
localhost:8080
from a browser to ensure that theWhitelabel Page
is displayed.
Open In IDE
- Open the newly downloaded project in IntelliJ
- Ensure that the project is opened via the
pom.xml
. - Ensure that the
pom.xml
is opened as a project, not as a file.
Create an Entity
- Create a
Person
Entity.
@Entity
public class Person {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
private Date birthDate;
public Person() {
}
public Person(Long id, String firstName, String lastName, Date birthDate) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.birthDate = birthDate;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}
View the Entity
- Modify the
/resources/application.properties
file by adding the following configurations
server.port=8080
spring.h2.console.enabled=true
spring.h2.console.view=/h2-console
spring.datasource.url=jdbc:h2:mem:testdb
- Run the application
- Navigate to
localhost:8080/h2-console
to view the data-layer of the application
Create Repository
- Data Access Objects (DAOs) provide an abstraction for interacting with datastores.
- In the Spring framework, repositories act as a specific type of DAO which can access a respective database table.
- For example,
PersonRepository
can access a respectivePERSON
database table.
- For example,
- Typically DAOs include an interface that provides
- a set of finder methods for retrieving data such as
readById
,readAll
- and methods to persist and delete data such as
create
,updateById
, anddeleteById
- a set of finder methods for retrieving data such as
- It is customary to have one
Repository
permodel
object.
public interface PersonRepository extends CrudRepository<Person, Long> {
}
Prepopulate The Entity
- Populates the
Person
table in H2 with entities before the Web Server begins serving.
@Configuration
public class PersonConfig {
@Autowired
private PersonRepository repository;
@PostConstruct
public void setup() {
Person person1 = new Person();
person1.setFirstName("Leon");
person1.setLastName("Hunter");
Person person2 = new Person();
person2.setFirstName("John");
person1.setLastName("Doe");
repository.saveAll(Arrays.asList(
person1,
person2
));
}
}
- View the newly added records by
- restarting the application
- navigating to
localhost:8080/h2-console
- Executing query
SELECT * FROM PERSON
in theH2-Console
Create a Service
@Service
public class PersonService {
private PersonRepository repository;
@Autowired
public PersonService(PersonRepository repository) {
this.repository = repository;
}
public Person create(Person person) {
return repository.save(person);
}
public Person readById(Long id) {
return repository.findById(id).get();
}
public List<Person> readAll() {
Iterable<Person> allPeople = repository.findAll();
List<Person> personList = new ArrayList<>();
allPeople.forEach(personList::add);
return personList;
}
public Person update(Long id, Person newPersonData) {
Person personInDatabase = this.readById(id);
personInDatabase.setFirstName(newPersonData.getFirstName());
personInDatabase.setLastName(newPersonData.getLastName());
personInDatabase.setBirthDate(newPersonData.getBirthDate());
personInDatabase = repository.save(personInDatabase);
return personInDatabase;
}
public Person deleteById(Long id) {
Person personToBeDeleted = this.readById(id);
repository.delete(personToBeDeleted);
return personToBeDeleted;
}
}
constructor
- Set’s the service’s repository
@Autowired
public PersonService(PersonRepository repository) {
this.repository = repository;
}
create
Method
- Adds a new record to the table the service’s repository is accessing.
public Person create(Person person) {
return repository.save(person);
}
readById
Method
- Returns the record with the specified ID from the table the table that the service’s repository is accessing.
public Person readById(Long id) {
return repository.findById(id).get();
}
readAll
Method
- Returns all records from the table the service’s repository is accessing.
public List<Person> readAll() {
Iterable<Person> allPeople = repository.findAll();
List<Person> personList = new ArrayList<>();
allPeople.forEach(personList::add);
return personList;
}
updateById
Method
- Updates the record in the database with the specified
id
with the specifiednewData
public Person update(Long id, Person newPersonData) {
Person personInDatabase = this.readById(id);
personInDatabase.setFirstName(newPersonData.getFirstName());
personInDatabase.setLastName(newPersonData.getLastName());
personInDatabase.setBirthDate(newPersonData.getBirthDate());
personInDatabase = repository.save(personInDatabase);
return personInDatabase;
}
deleteById
Method
- Deletes the record in the database with the specified
id
public Person deleteById(Long id) {
Person personToBeDeleted = this.readById(id);
repository.delete(personToBeDeleted);
return personToBeDeleted;
}
Create a Controller
- Controllers define how to handle incoming requests from and outgoing responses to a client.
- Controllers provides all of the necessary endpoints to access and manipulate respective domain objects.
- REST resources are identified using URI endpoints.
- The aggregate of all controller endpoints exposed by a webserver is known as the webserver’s web API.
@Controller
public class PersonController {
private PersonService service;
@Autowired
public PersonController(PersonService service) {
this.service = service;
}
@PostMapping(value = "/create")
public ResponseEntity<Person> create(@RequestBody Person person) {
return new ResponseEntity<>(service.create(person), HttpStatus.CREATED);
}
@GetMapping(value = "/read/{id}")
public ResponseEntity<Person> readById(@PathVariable Long id) {
return new ResponseEntity<>(service.readById(id), HttpStatus.OK);
}
@GetMapping(value = "/readAll")
public ResponseEntity<List<Person>> readAll() {
return new ResponseEntity<>(service.readAll(), HttpStatus.OK);
}
@PutMapping(value = "/update/{id}")
public ResponseEntity<Person> updateById(
@PathVariable Long id,
@RequestBody Person newData) {
return new ResponseEntity<>(service.update(id, newData), HttpStatus.OK);
}
@DeleteMapping(value = "/delete/{id}")
public ResponseEntity<Person> deleteById(@PathVariable Long id) {
return new ResponseEntity<>(service.deleteById(id), HttpStatus.OK);
}
}
constructor
create
Method
- The
POST
verb functionality in acreate
method allows us to add a newPerson
record. - Take note that the method
- has a parameter of type
@RequestBody Person person
@RequestBody
tells Spring that the entire request body needs to be converted to an instance ofPerson
- delegates the
Person
persistence toPersonRepository
’s save method called by thePersonService
’screate
method.
- has a parameter of type
@PostMapping(value = "/create")
public ResponseEntity<Person> create(@RequestBody Person person) {
return new ResponseEntity<>(service.create(person), HttpStatus.CREATED);
}
readById
Method
- The code snippet below allows us to access an individual
Person
. - The value attribute in
@GetMapping
takes a URI template/read/{id}
. - The placeholder
{id}
along with@PathVarible
annotation allows Spring to examine the request URI path and extract thepollId
parameter value. - Inside the method, we use the
PersonService
’sreadById
finder method to retrieve the respectivePerson
from thePersonRepository
and pass the result to aResponseEntity
.
@GetMapping(value = "/read/{id}")
public ResponseEntity<Person> readById(@PathVariable Long id) {
return new ResponseEntity<>(service.readById(id), HttpStatus.OK);
}
readAll
Method
- The code snippet below allows us to access all
Person
records. - The value attribute in
@GetMapping
takes a URI template/read/{id}
. - The placeholder
{id}
along with@PathVarible
annotation allows Spring to examine the request URI path and extract thepollId
parameter value. - Inside the method, we use the
PersonService
’sreadById
finder method to retrieve the respectivePerson
from thePersonRepository
and pass the result to aResponseEntity
.
@GetMapping(value = "/readAll")
public ResponseEntity<List<Person>> readAll() {
return new ResponseEntity<>(service.readAll(), HttpStatus.OK);
}
update
Method
- The code snippet below enables us to update a
Person
with new data.
@PutMapping(value = "/update/{id}")
public ResponseEntity<Person> updateById(
@PathVariable Long id,
@RequestBody Person newData) {
return new ResponseEntity<>(service.update(id, newData), HttpStatus.OK);
}
deleteById
Method
- The code snippet below enables us to delete a
Person
@DeleteMapping(value = "/delete/{id}")
public ResponseEntity<Person> deleteById(@PathVariable Long id) {
return new ResponseEntity<>(service.deleteById(id), HttpStatus.OK);
}
Test Controller
- Launch the Postman app and enter the URI
http://localhost:8080/
and hit Send. - If your application cannot run because something is occupying a port, use this command with the respective port number specified:
kill -kill `lsof -t -i tcp:8080`