Spring Boot
24-03-10 CMPT 213 Slides 13 © Dr. B. Fraser 1
Topics
1) What is dependency injection? Why should I care?
2) How can Spring Boot give me a REST API?
3) Is handling errors hard?
24-03-10 2
Intro to Dependency Injection
&
Spring Boot
24-03-10 3
Dependency Injection (DI)
●
Dependency Injection (DI)
– ..
tightly coupled to a
– Separates.. concrete class
from.. loosely coupled,
supporting
polymorphism
●
POJO
..
– we'll differentiate this from using frameworks like
Spring Boot
24-03-10 4
DI Example
class AccountManager() {
private Logger logger;
private Database db;
AccountManager() { Without Dependency Injection:
logger = new Logger(); Class instantiates everything itself
db = new Database();
}
AccountManager(Logger logger, Database db) {
[Link] = logger;
With Dependency Injection:
[Link] = db; Class is passed necessary objects
}
}
●
DI loosely couples classes:
Client passes object in, so this class
..
24-03-10 5
What is Spring?
●
Spring is..
– To instantiate an AccountManager, we must have a
reference to the Logger and Database to give it.
– All parts of our code that instantiate an
AccountManager need a logger and a database!
– This can be burdensome!
●
Instead, how about a "automatic" way of saying:
"Here's a Logger; please give it to every class
wanting it"
– That's what DI framework does.
24-03-10 6
What is DI Framework?
●
DI Framework decouples our classes
– the framework is told of objects to pass around
(beans)
– the framework instantiates our AccountManager
class and passes in logger & DB (beans)
●
Benefits of DI
– ..
– Easy to mock out objects for unit testing
●
Benefits of DI Framework
– creates the necessary object graph for us
24-03-10 7
What is Spring Boot?
●
What is Spring Boot?
– It is a dependency injection framework with built in
packages of functionality.
●
Adds pre-configured packages to Spring
– Easily add and configure DB, authentication, web,
JSON, etc.
●
Using Spring Boot feels a bit like magic:
not just POJO!
24-03-10 8
REST APIs
with
Spring Boot
24-03-10 9
Back-end architecture
Our API code goes here Business Logic
Define REST API No dependence on
Call our Model REST API or Spring Boot
Use data
transmission
objects (DTO)
24-03-10 10
My Controller
HTTP
Request class MyController { class MyModel {
... Has-a model ...
} }
Response
object
Expose REST API
end-points (URLs) Business logic
Extract parameters: Store data
- path variables
- query string May use DB
- HTTP Body
Perform logic for API
24-03-10 11
Spring Boot Hello World
●
Demo: HelloWorld
– No model; just a controller
– GET / POST API via annotations
– Parameter via body (POST)
●
Usage
– 1. View default message
curl -s -i -X GET [Link]
– 2. Set 'name'
curl -s -i -H "Content-Type: application/json" \
-X POST -d 'Dr. Evil' [Link]
– 3. See full Greeting
curl -s -i -X GET [Link]
24-03-10 12
Spring Boot Endpoint Annotations
●
Creating an endpoint
@GetMapping("/minion")
public Minion getMinion() {
return minion; // ‘minion’ just my field
}
– Method name is irrelevant: think of it as a comment
to the programmer
– ..
●
all its public fields and public getters included.
24-03-10 13
Endpoint Arguments: Path
●
Path variables to API specified in annotation
@GetMapping("/quotes/{id}")
public Quote getQuoteById(@PathVariable("id") long id) {
for (Quote quote : quotes) {
if ([Link]() == id) {
return quote;
}
}
return null;
}
– Can have multiple path variables in path
(give each a unique name)
24-03-10 14
Endpoint Arguments: Body
●
HTTP body comes to us as an object:
@PostMapping("/name")
public String getName(@RequestBody String name) {
[Link] = name;
return name;
}
– Commonly used for POST / PUT
●
Can have any (serializable) object as body
– Body is a JSON object: Spring de-serializes it into
your fully formed object.
24-03-10 15
Endpoint Argument: Query String
●
For a GET you can support query strings:
@GetMapping("/quotes/")
Quote foo(
@RequestParam(value="search", defaultValue="") String strSearch,
@RequestParam(value="location", defaultValue="") String strLocation
){
[Link](“Searching for “ + strSearch
+ “ in location “ + strLocation);
...
return new Quote(....);
}
●
Arguments in headers also possible, but not
covered.
24-03-10 16
Demo
●
Demo Quote Tracker
– Show end points
– Demo with curl (commands in /doc)
●
Demo Some Changes
– Move Quote into a new model package
– Add a QuoteManager class (POJO)
●
Move much of the logic from controller into
QuoteManager class (in model)
24-03-10 DEMO: QuoteTracker 17
HTTP Response Codes
&
Error handling
24-03-10 19
HTTP Response Codes
●
API methods send HTTP 200 (OK) by default.
●
Can change function to send specific code:
@PostMapping("/quotes")
@ResponseStatus([Link])
public Quote newQuote(@RequestBody Quote quote) {
// Set new quote's ID
[Link](nextId);
nextId++;
// Store quote
[Link](quote);
// Return full quote so user gets ID
return quote;
}
24-03-10 20
Error Handling
●
Use exceptions to indicate errors
– Uncaught exceptions generate
..
– Use..
to generate other HTTP responses such as
400 (bad request) or 404 (not found)
24-03-10 21
Error Handling – Custom Exceptions
●
Create custom exception with HTTP status code
// Support returning errors to client
@ResponseStatus(HttpStatus.BAD_REQUEST)
static class BadRequest extends RuntimeException {
}
●
Throw the custom exception
@PostMapping("/quotes")
public Quote newQuote(@RequestBody Quote quote) {
// validate data
if ([Link]().isEmpty()) {
throw new BadRequest("Person must not be empty");
}
... // do something useful!
24-03-10 } 22
Error Handling Demo
●
Demo
– Change Quote Tracker to handle errors:
Return 404 (File Not Found) when requesting an
invalid ID on GET.
●
Hint: Have exception handle a message
– Use an exception similar to this:
@ResponseStatus(HttpStatus.BAD_REQUEST)
static class BadRequest extends RuntimeException {
public BadRequest() {}
public BadRequest(String str) {
super(str);
}
}
24-03-10 23
FYI: Return ResponseEntity
●
Endpoints can have full control of HTTP response
@PostMapping("/quotes")
public ResponseEntity<Quote> newQuote() {
// ...
return ResponseEntity
.status([Link])
.body(myNewQuote);
}
24-03-10 24
FYI: Assign code to exception
●
Can assign an HTTP response code to an existing
exception (such as IllegalArgumentException)
– Useful if code throws exceptions you don’t control
but you want to set the response code.
@ResponseStatus(value=HttpStatus.BAD_REQUEST,
reason="Invalid parameter")
@ExceptionHandler([Link])
public void errorHandleIllegalArg() {
// Nothing to do
}
24-03-10 25
Summary
●
Dependency Injection (DI)
– Pass an object the references it needs; don’t let it
instantiate the objects itself.
●
Spring Boot
– A DI framework which provides packages of
functionality.
●
Spring annotations to create API
– @GetMethod(“/path”), ...
●
HTTP response codes
– @ResponseStatus([Link])
– Custom exceptions with status codes
24-03-10 26