04-spring-boot-rest-crud.pdf

Full Transcript

Customer Relationship Manager (CRM) App Get customers CRM CRM App Service (spring-rest) Customer list We will create...

Customer Relationship Manager (CRM) App Get customers CRM CRM App Service (spring-rest) Customer list We will create this code using Spring REST (SERVER) www.luv2code.com © luv2code LLC What do we call it? REST REST API REST Services Web Services RESTful RESTful API RESTful Services Web Services Generally, all mean the SAME thing www.luv2code.com © luv2code LLC What do we call it? REST REST API REST Services Web Services RESTful RESTful API RESTful Services Web Services Generally, all mean the SAME thing www.luv2code.com © luv2code LLC JSON Basics - Syntax m © luv2code LLC What is JSON? JavaScript Object Notation Lightweight data format for storing and exchanging data … plain text JSON is just Language independent … not just for JavaScript plain text data Can use with any programming language: Java, C#, Python etc … www.luv2code.com © luv2code LLC Simple JSON Example Curley braces define objects in JSON Name Value Object members are name / value pairs { "id": 14, Delimited by colons "firstName": "Mario", "lastName": "Rossi", "active": true } Name is always in double-quotes www.luv2code.com © luv2code LLC REST HTTP Basics m © luv2code LLC REST over HTTP Most common use of REST is over HTTP Leverage HTTP methods for CRUD operations HTTP Method CRUD Operation POST Create a new entity GET Read a list of entities or single entity PUT Update an existing entity DELETE Delete an existing entity www.luv2code.com © luv2code LLC HTTP Messages HTTP Request Client Message Server My CRM CRM REST App Service HTTP Response Message www.luv2code.com © luv2code LLC HTTP Request Message Request line: the HTTP command HTTP Request Message Header variables: request metadata Request line Message body: contents of message Header variables Message body www.luv2code.com © luv2code LLC HTTP Response Message Response line: server protocol and status code Header variables: response metadata HTTP Response Message Message body: contents of message Response line Header variables Message body www.luv2code.com © luv2code LLC HTTP Response - Status Codes Code Range Description 100 - 199 Informational 200 - 299 Successful 401 Authentication Required 300 - 399 Redirection 404 File Not Found 400 - 499 Client error 500 - 599 Server error 500 Internal Server Error www.luv2code.com © luv2code LLC Java JSON Data Binding m © luv2code LLC Java JSON Data Binding Data binding is the process of converting JSON data to a Java POJO Java JSON POJO Also known as Mapping Data Binding Serialization / Deserialization Marshalling / Unmarshalling www.luv2code.com © luv2code LLC JSON Data Binding with Jackson Spring uses the Jackson Project behind the scenes Jackson handles data binding between JSON and Java POJO Details on Jackson Project: https://github.com/FasterXML/jackson-databind www.luv2code.com © luv2code LLC Jackson Data Binding By default, Jackson will call appropriate getter/setter method { "id": 14, Java "firstName": "Mario", POJO "lastName": "Rossi", } "active": true Student www.luv2code.com © luv2code LLC JSON to Java POJO Convert JSON to Java POJO … call setter methods on POJO { Call "id": 14, setXXX Java methods "firstName": "Mario", POJO "lastName": "Rossi", } "active": true Jackson will do Student this work www.luv2code.com © luv2code LLC JSON to Java POJO Note: Jackson calls the setXXX methods It does NOT access internal private fields directly Convert JSON to Java POJO … call setter methods on POJO public class Student { private int id; private String firstName; private String lastName; private boolean active; { Call setId(…) public void setId(int id) { "id": 14, this.id = id; } Call setFirstName(…) public void setFirstName(String firstName) { "firstName": "Mario", this.firstName = firstName; } "lastName": "Rossi", Call setLastName(…) public void setLastName(String lastName) { this.lastName = lastName; Jackson will do } "active": true Call setActive(…) public void setActive(boolean active) { this work this.active = active; } } // getter methods } www.luv2code.com © luv2code LLC Java POJO to JSON Now, let’s go the other direction Convert Java POJO to JSON … call getter methods on POJO { "id": 14, Java "firstName": "Mario", POJO "lastName": "Rossi", Call getXXX } "active": true methods Student Jackson will do this work www.luv2code.com © luv2code LLC REST API Design For real-time projects, who will use your API? Also, how will they use your API? Design the API based on requirements www.luv2code.com © luv2code LLC API Design Process Step- By-S tep 1. Review API requirements 2. Identify main resource / entity 3. Use HTTP methods to assign action on resource www.luv2code.com © luv2code LLC API Requirements From the Boss Create a REST API for the Employee Directory REST clients should be able to Get a list of employees Get a single employee by id Add a new employee Update an employee Delete an employee www.luv2code.com © luv2code LLC Step 2: Identify main resource / entity To identify main resource / entity, look for the most prominent "noun" For our project, it is "employee" Convention is to use plural form of resource / entity: employees /api/employees www.luv2code.com © luv2code LLC Step 3: Use HTTP methods to assign action on resource HTTP Method CRUD Action POST Create a new entity GET Read a list of entities or single entity PUT Update an existing entity DELETE Delete an existing entity Full CRUD www.luv2code.com © luv2code LLC Employee Real-Time Project HTTP Method Endpoint CRUD Action POST /api/employees Create a new employee GET /api/employees Read a list of employees GET /api/employees/{employeeId} Read a single employee PUT /api/employees Update an existing employee DELETE /api/employees/{employeeId} Delete an existing employee Employee Service (spring-rest) www.luv2code.com © luv2code LLC Anti-Patterns DO NOT DO THIS … these are REST anti-patterns, bad practice /api/employeesList /api/deleteEmployee /api/addEmployee /api/updateEmployee Instead, use HTTP methods to assign actions Don't include actions in the endpoint www.luv2code.com © luv2code LLC Employee Real-Time Project HTTP Method Endpoint CRUD Action POST /api/employees Create a new employee GET /api/employees Read a list of employees GET /api/employees/{employeeId} Read a single employee PUT /api/employees Update an existing employee DELETE /api/employees/{employeeId} Delete an existing employee Employee Service (spring-rest) www.luv2code.com © luv2code LLC More API Examples On the following slides, we’ll look at APIs from other real-time projects PayPal GitHub SalesForce www.luv2code.com © luv2code LLC PayPal PayPal Invoicing API https://developer.paypal.com/docs/api/invoicing/ www.luv2code.com © luv2code LLC GitHub GitHub Repositories API https://developer.github.com/v3/repos/#repositories Create a new repository List your repositories Delete a repository Get a repository www.luv2code.com © luv2code LLC SalesForce REST API Industries REST API https://sforce.co/2J40ALH Retrieve All Individuals GET /services/apexrest/v1/individual/ Retrieve One Individual GET /services/apexrest/v1/individual/{individual_id} Create an individual POST /services/apexrest/clinic01/v1/individual/ Update an individual PUT /services/apexrest/clinic01/v1/individual/ www.luv2code.com © luv2code LLC Spring Boot REST API - Real Time Project © luv2code LLC Real-Time Project REST API with Spring Boot that connects to a database REST API with Spring Boot www.luv2code.com © luv2code LLC API Requirements From the Boss Create a REST API for the Employee Directory REST clients should be able to Get a list of employees Get a single employee by id Add a new employee Update an employee Delete an employee www.luv2code.com © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Application Architecture Employee Employee Employee REST Service DAO Controller www.luv2code.com © luv2code LLC Setup Database Table © luv2code LLC employee.sql 1. File: employee.sql 2. Create a new database table: employee 3. Load table with sample data Details on downloading the SQL file provided in next section www.luv2code.com © luv2code LLC Creating Spring Boot Project © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees Our Task 4. Get single employee by ID 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Create DAO in Spring Boot © luv2code LLC Application Architecture Employee Employee Employee REST Service DAO Controller Current task www.luv2code.com © luv2code LLC Development Process 1. Set up Database Dev Environment Step- By-S tep 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID 5. Add a new employee Let's build a DAO layer for this 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC DAO Interface public interface EmployeeDAO { List findAll(); } www.luv2code.com © luv2code LLC DAO Impl Same interface for consistent API @Repository public class EmployeeDAOJpaImpl implements EmployeeDAO { private EntityManager entityManager; @Autowired public EmployeeDAOJpaImpl(EntityManager theEntityManager) { entityManager = theEntityManager; } … } Automatically created Constructor by Spring Boot injection www.luv2code.com © luv2code LLC Get a list of employees @Override public List findAll() { // create a query TypedQuery theQuery = entityManager.createQuery("from Employee", Employee.class); // execute query and get result list List employees = theQuery.getResultList(); // return the results return employees; } www.luv2code.com © luv2code LLC Development Process Step- By-S tep 1. Update db configs in application.properties 2. Create Employee entity 3. Create DAO interface 4. Create DAO implementation 5. Create REST controller to use DAO www.luv2code.com © luv2code LLC Define Services with @Service © luv2code LLC Refactor: Add a Service Layer Employee Employee Employee Rest Service DAO Controller www.luv2code.com © luv2code LLC Purpose of Service Layer ✤ Service Facade design pattern ✤ Intermediate layer for custom business logic ✤ Integrate data from multiple sources (DAO/repositories) Employee Employee Employee Rest Service DAO Controller www.luv2code.com © luv2code LLC Integrate Multiple Data Sources Employee DAO Employee Employee Rest Service Controller Skills DAO Payroll DAO www.luv2code.com © luv2code LLC Most Times - Delegate Calls Employee Employee Employee Rest Service DAO Controller www.luv2code.com © luv2code LLC Specialized Annotation for Services Spring provides the @Service annotation @Component @RestController @Repository @Service www.luv2code.com © luv2code LLC Specialized Annotation for Services @Service applied to Service implementations Spring will automatically register the Service implementation thanks to component-scanning www.luv2code.com © luv2code LLC Employee Service Step- 1. Define Service interface By-S tep 2. Define Service implementation Inject the EmployeeDAO Employee Employee Employee Rest Service DAO Controller www.luv2code.com © luv2code LLC Step 1: Define Service interface public interface EmployeeService { List findAll(); } www.luv2code.com © luv2code LLC Step 2: Define Service implementation @Service - enables component scanning @Service public class EmployeeServiceImpl implements EmployeeService { // inject EmployeeDAO … @Override public List findAll() { return employeeDAO.findAll(); } } www.luv2code.com © luv2code LLC DAO: Find, Add, Update and Delete © luv2code LLC Service Layer - Best Practice ✤ Best practice is to apply transactional boundaries at the service layer ✤ It is the service layer’s responsibility to manage transaction boundaries ✤ For implementation code ✤ Apply @Transactional on service methods ✤ Remove @Transactional on DAO methods if they already exist www.luv2code.com © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID DAO methods 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC DAO: Get a single employee @Override public Employee findById(int theId) { // get employee Employee theEmployee = entityManager.find(Employee.class, theId); // return employee return theEmployee; } www.luv2code.com © luv2code LLC DAO: Add or Update employee Note: We don’t use @Transactional at DAO layer It will be handled at Service layer if id == 0 then save/insert @Override else update public Employee save(Employee theEmployee) { // save or update the employee Employee dbEmployee = entityManager.merge(theEmployee); // return dbEmployee return dbEmployee; } Return dbEmployee It has updated id from the database (in the case of insert) www.luv2code.com © luv2code LLC DAO: Delete an existing employee Note: We don’t use @Transactional at DAO layer It will be handled at Service layer @Override public void deleteById(int theId) { // find the employee by id Employee theEmployee = entityManager.find(Employee.class, theId); // delete the employee entityManager.remove(theEmployee); } www.luv2code.com © luv2code LLC DAO: Find, Add, Update and Delete © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID DAO methods 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Service: Find, Add, Update and Delete © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID Service methods 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Rest Controller Methods - Find and Add © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees 4. Get single employee by ID Rest Controller methods 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Read a Single Employee GET /api/employees/{employeeId} Employee REST REST Client Controller www.luv2code.com © luv2code LLC Create a New Employee Since new employee, we are not POST /api/employees passing id / primary key Employee REST REST Client Controller Response contains new id / primary key www.luv2code.com © luv2code LLC Sending JSON to Spring REST Controllers When sending JSON data to Spring REST Controllers For controller to process JSON data, need to set a HTTP request header Content-type: application/json Need to configure REST client to send the correct HTTP request header www.luv2code.com © luv2code LLC Postman - Sending JSON in Request Body Must set HTTP request header in Postman 1 2 3 Based on these configs, Postman will automatically set http://localhost:8080/api/employees the correct HTTP request header www.luv2code.com © luv2code LLC Rest Controller Methods - Update and Delete © luv2code LLC Development Process Step- By-S tep 1. Set up Database Dev Environment 2. Create Spring Boot project using Spring Initializr 3. Get list of employees Rest Controller 4. Get single employee by ID methods 5. Add a new employee 6. Update an existing employee 7. Delete an existing employee www.luv2code.com © luv2code LLC Update Employee ID of employee to update PUT /api/employees With updated info Employee REST REST Client Controller Response contains updated info (echoed) www.luv2code.com © luv2code LLC Delete Employee DELETE /api/employees/{employeeId} Employee REST REST Client Controller Deleted employee id - {employeeId} www.luv2code.com © luv2code LLC Spring Data JPA in Spring Boot © luv2code LLC Application Architecture Employee Employee Employee REST Service DAO Controller Spring Data JPAJPA Now use Previously used Spring Data JPA JPA API www.luv2code.com © luv2code LLC The Problem We saw how to create a DAO for Employee What if we need to create a DAO for another entity? Customer, Student, Product, Book … Do we have to repeat all of the same code again??? www.luv2code.com © luv2code LLC Creating DAO You may have noticed a pattern with creating DAOs Most of the code @Override is the same public Employee findById(int theId) { // get data Employee theData = entityManager.find(Employee.class, theId); // return data return theData; } Primary key Only difference is the Entity type entity type and primary key www.luv2code.com © luv2code LLC My Wish I wish we could tell Spring: Create a DAO for me Plug in my entity type and primary key Give me all of the basic CRUD features for free www.luv2code.com © luv2code LLC My Wish Diagram Entity: Entity: Employee Customer Product Primary key: Integer findAll() CRUD methods findById(…) save(…) deleteById(…) … others … www.luv2code.com © luv2code LLC Spring Data JPA - Solution Spring Data JPA is the solution!!!! https://spring.io/projects/spring-data-jpa Create a DAO and just plug in your entity type and primary key Spring will give you a CRUD implementation for FREE …. like MAGIC!! Helps to minimize boiler-plate DAO code … yaaay!!! More than 70% reduction in code … depending on use case www.luv2code.com © luv2code LLC JpaRepository Spring Data JPA provides the interface: JpaRepository Exposes methods (some by inheritance from parents) Entity: Employee Primary key: Integer findAll() findById(…) save(…) deleteById(…) … others … www.luv2code.com © luv2code LLC Development Process Step- By-S tep 1. Extend JpaRepository interface 2. Use your Repository in your app No need for implementation class www.luv2code.com © luv2code LLC Step 1: Extend JpaRepository interface Primary key Entity type public interface EmployeeRepository extends JpaRepository { // that's it... no need to write any code LOL! } Entity: Employee Primary key: Integer Get these methods for free findAll() No need for findById(…) save(…) implementation class deleteById(…) … others … www.luv2code.com © luv2code LLC JpaRepository Docs Full list of methods available … see JavaDoc for JpaRepository www.luv2code.com/jpa-repository-javadoc www.luv2code.com © luv2code LLC Step 2: Use Repository in your app @Service public class EmployeeServiceImpl implements EmployeeService { Our repository private EmployeeRepository employeeRepository; @Autowired public EmployeeServiceImpl(EmployeeRepository theEmployeeRepository) { employeeRepository = theEmployeeRepository; } @Override public List findAll() { return employeeRepository.findAll(); } … Magic method that is } available via repository www.luv2code.com © luv2code LLC Minimized Boilerplate Code Before Spring Data JPA After Spring Data JPA 1 File 3 lines of code! 2 Files 30+ lines of code No need for implementation class www.luv2code.com © luv2code LLC Advanced Features Advanced features available for Extending and adding custom queries with JPQL Query Domain Specific Language (Query DSL) Defining custom methods (low-level coding) www.luv2code.com/spring-data-jpa-defining-custom-queries www.luv2code.com © luv2code LLC Spring Data REST in Spring Boot © luv2code LLC Spring Data JPA Earlier, we saw the magic of Spring Data JPA This helped to eliminate boilerplate code www.luv2code.com © luv2code LLC Hmmm … Can this apply to REST APIs? www.luv2code.com © luv2code LLC The Problem We saw how to create a REST API for Employee Need to create REST API for another entity? Customer, Student, Product, Book … Do we have to repeat all of the same code again??? www.luv2code.com © luv2code LLC My Wish I wish we could tell Spring: Create a REST API for me Use my existing JpaRepository (entity, primary key) Give me all of the basic REST API CRUD features for free www.luv2code.com © luv2code LLC Spring Data REST - Solution Spring Data REST is the solution!!!! https://spring.io/projects/spring-data-rest Leverages your existing JpaRepository Spring will give you a REST CRUD implementation for FREE …. like MAGIC!! Helps to minimize boiler-plate REST code!!! No new coding required!!! www.luv2code.com © luv2code LLC Spring Data REST - How Does It Work? Spring Data REST will scan your project for JpaRepository Expose REST APIs for each entity type for your JpaRepository public interface EmployeeRepository extends JpaRepository { } www.luv2code.com © luv2code LLC REST Endpoints By default, Spring Data REST will create endpoints based on entity type Simple pluralized form First character of Entity type is lowercase More on Then just adds an "s" to the entity plural forms in later video public interface EmployeeRepository extends JpaRepository { } /employees www.luv2code.com © luv2code LLC Development Process Step- By-S tep 1. Add Spring Data REST to your Maven POM file That's it!!! Absolutely NO CODING required www.luv2code.com © luv2code LLC Step 1: Add Spring Data REST to POM file org.springframework.boot spring-boot-starter-data-rest That's it!!! Absolutely NO CODING required Spring Data REST will scan for JpaRepository www.luv2code.com © luv2code LLC In A Nutshell For Spring Data REST, you only need 3 items We already have these two 1. Your entity: Employee 2. JpaRepository: EmployeeRepository extends JpaRepository 3. Maven POM dependency for: spring-boot-starter-data-rest Only item that is new www.luv2code.com © luv2code LLC Application Architecture Before After Get these REST endpoints for free www.luv2code.com © luv2code LLC Minimized Boilerplate Code Before Spring Data REST After Spring Data REST 3 files 100+ lines of code www.luv2code.com © luv2code LLC HATEOAS Spring Data REST endpoints are HATEOAS compliant HATEOAS: Hypermedia as the Engine of Application State Hypermedia-driven sites provide information to access REST interfaces Think of it as meta-data for REST data https://spring.io/understanding/HATEOAS www.luv2code.com © luv2code LLC HATEOAS Get single Spring Data REST response using HATEOAS employee For example REST response from: GET /employees/3 Response { "firstName": "Avani", Employee data "lastName": "Gupta", "email": "[email protected]", "_links": { "self": { "href": "http://localhost:8080/employees/3" }, Response meta-data "employee": { "href": "http://localhost:8080/employees/3" Links to data } } } www.luv2code.com © luv2code LLC HATEOAS For a collection, meta-data includes page size, total elements, pages etc For example REST response from: GET /employees Get list of Response employees { "_embedded": { "employees": [ { JSON Array of employees "firstName": "Leslie",... },... ] }, "page": { "size": 20, More on "totalElements": 5, Response meta-data configuring page "totalPages": 1, "number": 0 Information about the page sizes later } } www.luv2code.com © luv2code LLC HATEOAS For details on HATEOAS, see https://spring.io/understanding/HATEOAS HATEOAS uses Hypertext Application Language (HAL) data format For details on HAL, see https://en.wikipedia.org/wiki/Hypertext_Application_Language www.luv2code.com © luv2code LLC Advanced Features Spring Data REST advanced features Pagination, sorting and searching Extending and adding custom queries with JPQL Query Domain Specific Language (Query DSL) https://spring.io/projects/spring-data-rest www.luv2code.com © luv2code LLC Spring Data REST Configuration, Pagination and Sorting © luv2code LLC REST Endpoints By default, Spring Data REST will create endpoints based on entity type Simple pluralized form First character of Entity type is lowercase Then just adds an "s" to the entity public interface EmployeeRepository extends JpaRepository { } /employees www.luv2code.com © luv2code LLC Pluralized Form Spring Data REST pluralized form is VERY simple Just adds an "s" to the entity The English language is VERY complex! Singular Plural Spring Data REST does NOT handle Goose Geese Person People Syllabus Syllabi … … www.luv2code.com © luv2code LLC Problem Spring Data REST does not handle complex pluralized forms In this case, you need to specify plural name What if we want to expose a different resource name? Instead of /employees … use /members www.luv2code.com © luv2code LLC Solution Specify plural name / path with an annotation @RepositoryRestResource(path="members") public interface EmployeeRepository extends JpaRepository { } http://localhost:8080/members www.luv2code.com © luv2code LLC Pagination By default, Spring Data REST will return the first 20 elements Page size = 20 You can navigate to the different pages of data using query param http://localhost:8080/employees?page=0 Pages are http://localhost:8080/employees?page=1 zero-based … www.luv2code.com © luv2code LLC Spring Data REST Configuration Following properties available: application.properties Name Description spring.data.rest.base-path Base path used to expose repository resources spring.data.rest.default-page-size Default size of pages spring.data.rest.max-page-size Maximum size of pages … … More properties available spring.data.rest.* www.luv2code.com/spring-boot-props www.luv2code.com © luv2code LLC Sample Configuration http://localhost:8080/magic-api/employees File: application.properties spring.data.rest.base-path=/magic-api spring.data.rest.default-page-size=50 Returns 50 elements per page www.luv2code.com © luv2code LLC Sorting You can sort by the property names of your entity In our Employee example, we have: firstName, lastName and email Sort by last name (ascending is default) http://localhost:8080/employees?sort=lastName Sort by first name, descending http://localhost:8080/employees?sort=firstName,desc Sort by last name, then first name, ascending http://localhost:8080/employees?sort=lastName,firstName,asc www.luv2code.com © luv2code LLC

Use Quizgecko on...
Browser
Browser