Spring Framework Stereotypes
- Stereotype - a fixed general image or ser of characteristics which represent a particular type of person or thing
- Spring Stereotypes are
class
level annotations used to define Spring Beans- when classes annotated with Spring Stereotypes are detected via the component scan, an instance of the class will be added to the Spring context
- Available Spring Stereotypes
@Component
@Controller
@RestController
@Repository
@Service
Annotation | Description |
---|---|
@Component | Indicates that an annotated class is a component and it will be created as a bean |
@Controller | indicates that an annotated class has the role of a Spring MVC controller |
@RestController | convenience annotation which extends @Controller and @ResponseBody |
@Repository | indicates class is a Repository, a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects |
@Service | indicates that an annotated class is a Service, an operation offered as an interface that stands alone in the model, with no encapsulated state |
Spring Component Scan
- Spring Beans defined with Spring Stereotypes are detected with Spring component scan
- On startup, Spring is told to scan packages for classes with Spring Stereotype annotations
- This configuration is Spring Framework specific, not Spring Boot
- Spring Boot’s auto configuration will tell Spring to perform a component scan of the package of the main class
- this includes all sub packages of the main class package
- when using Spring Boot, if class is outside of the main class package tree, you must declare the package scan manually
Spring Bean Scopes
Singleton
- (default) only one instance of the bean is created in the IoC containerPrototype
- A new instance is created each time the bean is requestedRequest
- For web app, a single instance per http request, only valid in the context of a web aware Spring applicationContextSession
- for web app, a single instance per http session, only valid in the context of a web aware Spring applicationContextGlobal-session
- a single instance per global session, typically only used in a Portlet context, only valid in the context of a web aware Spring applicationContextApplication
- bean is scoped to the lifecycle of a ServletContext, only valid in the context of web awareWebSocket
- scopes a single bean definition to the lifecycle of a WebSocket, only valid in the context of a web aware Spring applicationContextCustom Scope
- Spring Scopes are extensible, and you can define your own scope by implementing Spring’s scope interface
Declaring Bean Scope
- No declaration needed for singleton scope
- in Java configuration use
@Scope
annotation - in XML configuration file scope is an XML attribute of the bean tag
- 99% of the time singleton scope is fine
External Properties
- Why use External Properties?
- hard coding values which can change is considered a bad practice
- makes your application rigid and hard to change
- you want your application to be portable
- deployment artifact (jar, war) should be deployable to different environments
- what can change?
- usernames, passwords, urls, API keys, paths, queue names etc…
which property files to use
- using application.properties or application.yml in packaged JAR or WAR
- using profile specific properties or YAML files for profile specific properties
- for deployments, override properties that change with environment variables
- typically 70 - 80% of values do not change, only override what is needed
- environment variables offer a secure way of seeing sensitive values such as passwords
Properties Setting Hierarchy (from low to high)
- application.properties
- environment variables
- command line variables
Thymeleaf
- Thymeleaf is a Java template engine producing XML, XHTML and HTML5
- Thymeleaf is a replacement of JSPs
- Thymeleaf is a natural template engine (the templates are viewable in a web browser)
- is not tied to web environment (can be used for producing HTML for emails)
- Thymeleaf is not a web framework
Request Methods
- GET
- is a request for a resource (html file, javascript file, image, etc…)
- is used when you visit a website
- HEAD
- is like GET, but only asks for meta information without the body
- POST
- is used to post data to the server
- typical use case for POST is to post form data to the server (like a checkout form)
- POST is a create request
- PUT
- is a request for the enclosed entity be stored at the supplied URI, if the entity exists, it is expected to be updated
- PUT is a create OR update request
- DELETE
- is a request to delete the specified resource
- TRACE
- will echo the received request, can be used to see if request was altered by intermediate servers
- OPTIONS
- returns the HTTP methods supported by the server for the specified URL
Safe methods
- safe methods are considered safe to use because they only fetch information and do not cause changes on the server
- the safe methods are: GET, HEAD, OPTIONS, and TRACE
Idempotent methods
- a quality of an action such that repetitions of the action have no further effect on the outcome
- PUT and DELETE are Idempotent methods
- safe methods (GET, HEAD, OPTIONS and TRACE) are also Idempotent
- being truly idempotent is not enforced by the protocol
Non-Idempotent methods
- POST is NOT idempotent
- multiple POSTs are likely to create multiple resources
- Ever seen websites asking you to click submit only once?
HTTP Status Codes
- 100 series are information in nature
- 200 series indicate successful request
- 200 Okay, 201 Created, 204 Accepted
- 300 series are redirections
- 301 Moved Permanently
- 400 series are client errors
- 400 Bad Request, 401 Not Authorized, 404 Not Found
- 500 series are server side errors
- 500 Internel Server Error, 503 Service Unavailable
Developer Tools
- added to project via artifact ‘spring-boot-devtools’
- developer tools are automatically disabled when running a packaged application
- by default, not included in repackaged archives
Features
- by default you need to select Build -> Make project
- there is an advanced setting you can change to make this more seamless
Template caching
- by default templates are cached for performance
- but caching will require a container restart to refresh the cache
- developer tools will disable template caching so the restart is not required to see changes
LiveReload
- LiveReload is a technology to automatically trigger a browser refresh when resources are changed
- Spring boot developer tools includes a LiveReload server
Entity Relationships
- One to One
- One entity is related to one other entity
- One to Many
- One entity is related to many entities (List, Set, Map, SortedSet, SortedMap)
- Many to One
- the inverse relationship of one to many
- Many to Many
- many entities are related to many entities
- each has a list or set reference to the other
- a join table us used to define the relationships (mapping table)
Unidirectional vs Bidirectional
- Unidirectional is one way
- mapping is only done one way, one side of the relationship will not know about the other
- Bidirectional is two way
- both sides know about each other
- generally recommended to use bidirectional, since you can navigate the object graph in either direction
Owning side
- the Owning side in the relationship will hold the foreign key in the database
- one to one is the side where the foreign key is specified
- one to many and many to one is the
Many
side - mappedBy is used to define the field with
owns
the reference of the relationship
Fetch type
- Lazy - data is not required until referenced
- Eager - data is queried up front
JPA Cascade Types
- JPA Cascade types control how state changes are cascaded from parent objects to child objects
- Types
- PERSIS
- MERGE
- REFRESH
- REMOVE
- DETACH
- ALL
- by default, no operations are cascaded
Embeddable Types
- JPA / Hibernate support embeddable types
- these are used to define a common set of properties
- for example, an order might have a billing address and a shipping address
- an embeddable type could be used for the address properties for reuse
Inheritance
- mappedSuperclass - entities inherit from a super class, a database table IS NOT created for the super class
- Single Table - default - one table is used for all subclasses
- Joined Table - base class and subclasses have their own tables, fetching subclass entities require a join to the parent table (subclasses will not have the common properties from the parent class)
- Table Per Class - each subclass has its own table (no table for parent class. common properties will exist in all subclasses)
Create and Update Timestamps
- often a best practice to use create and update timestamps on your entities for audit purposes
- JPA supports
@PrePersist
and@PreUpdate
which can be used for support audit timestamps via JPA lifecycle callbacks - hibernate provides
@CreationTimestamp
and@UpdateTimestamp
Hibernate DDL Auto
- DDL - Data Definition Language
- DML - Data Manipulation Language
- Hibernate property is set by the Spring property
- options are
- none
- validate - check if there is any table or columns that are missing
- update - find missing table and columns and update the existing DB, not good for PROD environment
- create - create the DB
- create-drop - create the DB and drop the DB when application instance stops running.
- Spring boot will use create-drop for embedded databases (HSQL, H2, Derby) or none
DDL vs DML
- DDL is used to define database structures such as tables and indexes, while DML is used with data operations such as inserts and updates
Initialize with Hibernate
- data can be loaded from
import.sql
, this is a file that can be created in the root path - Hibernate feature, not Spring specific
- must be on root of class path
- only executed if Hinernate’s DDL auto property is set to
create
orcreate-drop
Spring JDBC
- Spring’s datasource initializer via Spring Boot will by default load
schema.sql
anddata.sql
from the root of the class path - Spring Boot will also load from
schema-${platform}.sql
anddata-${platform}.sql
- must set
spring.datasource.platform
property - may conflict with Hinernate DDL auto property
- if using Spring datasource initializer, should set DDL auto property to
none
orvalidate
- if using Spring datasource initializer, should set DDL auto property to
Spring Data JPA Query Method
- define method in interface
- method name rules: findBy +
<PROPERTY_NAME>
- it will create the query based on method name and query the database to find the data and return to us.
- no manual implementation needed.
Repository layer and Service layer
- All your business logic should be in the Service Layer.
- Any access to the Database (any storage) should go to the Repository Layer.
- Lets take an Example. You have to save an entity(Person). But before saving the Person you want to make sure that the Person’s FirstName does not exist already.
So the validation part should go to the business layer.
In the service Layer
1 | PersonRepository repository; |
-
And in your Repository Layer just concentrate on DB Operation.
-
View<-->Controller( create instance of Model class)<-->Service<--->Repository
Lombok
- hooks in via the annotation processor API
- the raw source code is passed to Lombok for code generation before the Java complier continues
- thus, produces properly compiled Java code in conjunction with the Java compiler
- under the classes you can view the compiled class files
- IntelliJ will decompile to show you the source code
IDEs
- since compiled code is change, and source files are not, IDE’s can get confused by this
- more of an issue for IDEs several years old
- modern IDEs such as IntelliJ, Eclipse support Project Lombok
- Plug in Installation may be necessary
- IntelliJ
- verify you have enabled annotation processing under compiler settings
features
val
- local variables declared finalvar
- mutable local variables@NonNull
- Null check, will throw NPE if parameter is null@Cleanup
- will call close() on resource/connection in finally block@Getter
- creates getter methods for all properties@Setter
- creates setter for all non-final properties@ToString
- generates String of classname, and each field separated by commas
- optional parameter to include field names
- optional parameter to include call to the super toString method
@EqualsAndHashCode
- generates implementations of
equals(Object other)
andhashCode()
- by default will use all non-static, non-transient properties
- can optionally exclude specific properties
- generates implementations of
@NoArgsConstructor
- generates no args constructor
- will cause compiler error if there are final fields
- can optionally force, which will initialize final fields with 0 / false / null
@RequiredArgsConstructor
- generates a constructor for all fields that are final or marked @NonNull
- constructor will throw a NullPointerException if any
@NonNull
fields are null
@AllArgsConstructor
- generates a constructor for all properties of class
- any @NotNull properties will have null check
@Data
- generates typical boilerplate code for POJOs
- combines -
@Getter
,@Setter
,@ToString
,@EqualsAndHashCode
,@RequiredArgsConstructor
- no constructor is generated if constructors have been explicitly declared
@Value
- the immutable variant of
@Data
- all fields are made private and final by default
- the immutable variant of
@NonNull
- set on parameter of method or constructor and a NullPointerException will be thrown if parameter is null
@Builder
- implements the builder pattern for object creation
@SneakyThrows
- throw checked exceptions without declaring in calling method’s throws clause
@Synchronized
- a safer implementation of Java’s synchronized
@Getter(lazy = true)
- for expensive getters
- will calculate value first time and cache
- additional gets will read from cache
@Log
- creates a Java util logger
@Slf4j
- creates a SLF4J logger
- recommended - SLF4J is a generic logging facade
- spring boot’s default logger is LogBack
Testing Terminology
- Code under test
- this is the code you are testing
- Test fixture
- a test fixture is a fixed state of a set of objects used as a baseline for running tests. The purpose of a test fixture is to ensure that there is a well known and fixed environment in which tests are run so that results are repeatable
- includes: input data, mock objects, loading database with known data etc…
Unit Tests
- code written to test code under test
- designed to test specific sections of code
- percentage of lines of code tested is code coverage
- ideal coverage is in the 70-80% range
- should be unity and execute very fast
- should have no external dependencies
- no databases, no Spring Context etc…
Integration tests
- designed to test behaviors between objects and parts of the overall system
- much larger scope
- can include Spring Context, database, and message brokers
- will run much slower than unit tests
Functional tests
- typically means you are testing the running application
- application is live, likely deployed in a known environment
- functional touch points are tested
- i.e. using a web driver, calling web services, sending / receiving messages etc…(Selenium)
TDD
- test driven development
- write tests first, which will fail, then code to fix the tests
BDD
- behavior driven development
- builds on TDD and specifies that tests of any unit of software should be specified in terms of desired behavior of the unit
- often implemented with DSLs to create natural language tests
- JBehave, Cucumber, Spock
Mock
- a fake implementation of a class used for testing, like a test double
Spy
- a partial mock, allowing you to override select methods of a real class
Testing goals
- generally, you will want the majority of your tests to be unit tests
- bringing up the Spring Context makes your tests exponentially slower
- try to test specific business logic in unit tests
- use Integration tests to test interactions
- think of a pyramid, base is unit tests, middle is integration tests, top is functional tests
Test scope dependencies
- using spring-boot-starter-test
- JUnit - the default standard for unit testing Java applications
- Spring test and Spring boot Test - utilities and integration test support for Spring Boot applications
- AssertJ - a fluent assertion library
- Hamcrest - a library of matcher objects
- Mockito - a Java mocking framework
- JSONassert - an assertion library for JSON
- JSONPath - XPath for JSON
JUnit Annotations
Annotation | Description |
---|---|
@Test | identifies a method as a test method |
@Before | executed before each test, it is used to prepare the test environment (e.g. read input data, initialize the class) |
@After | executed after each test, it is used to cleanup the test environment, it can also save memory by cleaning up expensive memory structures |
@BeforeClass | executed once, before the start of all tests, methods marked with this annotation need to be defined as static to work with JUnit |
@AfterClass | executed once, after all tests have been finished, methods annotated with this annotation need to be defined as static to work with JUnit |
@Ignore | marks that the test should be ignored |
@Test(expected = Exception.class) | fails if the method does not throw the named exception |
@Test(timeout = 10) | fails if the method takes longer than 100 milliseconds |
Spring Boot Annotations
Annotation | Description |
---|---|
@RunWith(SpringRunner.class) | run test with Spring Context |
@SpringBootTest | search for Spring boot application for configuration |
@TestConfiguration | specify a Spring configuration for you test |
@MockBean | injects Mockito mock |
@SpyBean | injects Mockito Spy |
@JsonTest | creates a Jackson or Gson object mapper via Spring boot |
@WebMvcTest | used to test web context without a full http server |
@DataJpaTest | used to test data layer with embedded database |
…
ArgumentCaptor
- ArgumentCaptor allows us to capture an argument passed to a method in order to inspect it. This is especially useful when we can’t access the argument outside of the method we’d like to test.
- For example, consider an EmailService class with a send method that we’d like to test:
1 | public class EmailService { |
- In EmailService.send, notice how platform.deliver takes a new Email as an argument. As part of our test, we’d like to check that the format field of the new Email is set to Format.HTML. In order to do this, we need to capture and inspect the argument that is passed to platform.deliver.
Set up the unit test
- First, let’s create our unit test class:
1 | RunWith(MockitoJUnitRunner.class) |
- We’re using the @Mock annotation to mock DeliveryPlatform, which is automatically injected into our EmailService with the @InjectMocks annotation.
Add an ArgumentCaptor field
- Second, let’s add a new ArgumentCaptor field of type Email to store our captured argument:
1 | @Captor |
Capture the argument
1 | Mockito.verify(platform).deliver(emailCaptor.capture()); |
- We can then get the captured value and store it as a new Email object:
1 | Email emailCaptorValue = emailCaptor.getValue(); |
Inspect the captured value
1 | @Test |
Exception Handling in Spring MVC
HTTP status code
- HTTP 5XX server error
- HTTP 500 - internal server error
- generally, any unhandled exception
- other 500 errors are generally not used with Spring MVC
- HTTP 4XX client errors - generally checked exceptions
- 400 bad request - cannot process due to client error
- 401 unauthorized - authentication required
- 404 not found - resource not found
- 405 method not allowed, HTTP method not allowed
@ResponseStatus
- allows you to annotate custom exception classes to indicate to the framework the HTTP status you want returned when that exception is thrown
- global to the application
@ExceptionHandler
- works at the controller level
- allows you to define custom exception handling
- can be used with
@ResponseStatus
for just printing a http status - can be used to return a specific view
- also can take total control and work with the Model and View
- Model cannot be a parameter of an ExceptionHandler method
@HandlerExceptionResolver
- is an interface you can implement for custom exception handling
- used internally by Spring MVC
- note Model is not passed
Docker
What is Docker?
- Docker is a standard for Linux containers
- a Container is an isolated runtime inside of Linux
- a Container provides a private machine like space under Linux
- Containers will run under any modern Linux Kernel
Containers can
- Have their own process space
- their own network interface
- run processes as Root (inside the container)
- have their own disk space
- can share with host too
- Container is not a VM
Docker Terminology
- Docker Image - the representation of a Docker container, kind of like a JAR or WAR file in Java
- Docker Container - the standard runtime of Docker, effectively a deployed and running Docker image, like a Spring Boot Executable JAR
- Docker Engine - the code which manages Docker stuff, creates and runs Docker containers
Notes about Docker Images and Containers
- Containers are like snapshots of Docker images
- Docker images are built by Docker files which contains multiple layers, each layer is a Command and will generate a file for the image. The layers will be re-created everytime when we run a new container for an image.
- e.g. when you
docker run -d mongo
, a new container for the imagemongo
will be created, and there is a layer for this container where you can store data in it. But when youdocker stop <Container_ID>
and re-start usingdocker run -d mongo
, a new container with different Container ID will be created, so your old data in the previous container will not show in your new container. You can map a storage path to the container, so the current container and all future containers will save data into the directory you setup. Which will make the data persistence.
Docker housekeeping
Cleaning up after Docker
- with development use docker can leave behind a lot of files
- these files will grow and consume a lot of disk space
- this is less of an issue on production systems where containers aren’t being built and restarted all the time
- there are 3 key areas of house keeping
- containers
- images
- volumes
MySQL
MySQL features
- Stored procedures
- a piece of code inside of the database that execute against the database, runs locally on the database
- Triggers
- when something happens in the database e.g. insert a record, the trigger will run before or after that transaction
- Cursors
- point a place in a large set of data so you can scroll through it and look into the next record or previous record.
- Updated views
- a virtual table, stored inside the database
- Query cache
- database is going to remember in memory the result of your query, when you ask for that data again, it doesn’t have to go back to the file system to get the data.
- Subselects
- nested queries.
ACID compliance
- atomicity - all or nothing
- consistency - transactions are valid to rules of the DB
- isolation - results of transactions are as if they are done end to end
- durability - once a transaction is committed, it remains so (DB will not losing data)
RDBMS deployment architectures
- typically is driven by needs of scalability and availability
- can be done on a single non-dedicated server or many dedicated servers
- communication is typically over a network socket (MySQL: 3306)
- the client will need software called a
driver
to talk to the database over the network socket.
MySQL data types
- a data type defines the data type of a column
- MySQL does support the standard ANSI SQL data types
- data types are broken down into the following categories
- numeric
- date and time
- string
- spatial (location, places)
- JSON
MySQL installation options
Native installation
- meaning install on your opearting system
Running MySQL in a Container
- MySQL can also be run inside a technology called containers
- Docker is a highly popular container technology
- through Docker, you can run MySQL locally using pre built image from Docker hub
Connecting to MySQL
- Local connection
- connecting to MySQL from the command line on the machine running MySQL
- to login to docker:
docker exec -it yuan-mysql bash
- to connect to mysql server in Docker:
mysql --user=root -p
- remote / client connection
- using some type of client software on the same machine running MySQL
- or connecting to the MySQL server from a different machine over the network
Mongo DB
About Mongo DB
- Mongo DB is a document oriented database
- developed in C++
- MongoDB is a NoSQL database
- MongoDB documents are stored in BSON
- binary JSON
Why use Mongo DB?
- MongoDB is great for high insert systems
- such as sensor readings, social media systems, advertising systems
- good when you need schema flexibility
- can also support a high number of reads per second
Why avoid MongoDB?
- MongoDB has no concept of transactions
- No ACID
- no locking for transactional support, hence faster inserts
- not good for concurrent updates
Reactive Manifesto
Responsive
- the system responds in a timely manner
- responsiveness is the cornerstone of useability and utility
- responsiveness also means problems may be detected quickly and dealt with effectively
- responsive systems provide rapid and consistent response times
- consistent behavior simplifies error handling, builds end user confidence, and encourages further interaction
Resilient
- system stays responsive in the face of failure
- resilience is achieved by replication, containment, isolation and delegation
- failures are contained within each component
- parts of the system can fail, without compromising the system as a whole
- recovery of each component is delegated to another
- high availability is ensured by replication where necessary
Elastic
- the system stays responsive under varying workload
- reactive systems can react to changes in the input rate by increasing or decreasing resources allocated to service inputs
- reactive systems achieve elasticity ina cost effective way on commodity hardware and software platforms
Message Driven
- reactive systems rely on asynchronous message passing to establish a boundary between components
- this ensures loose coupling, isolation, and location transparency
- message passing enables load management, elasticity, and flow control
- location transparent messaging makes management of failure possible
- non blocking communication allows recipients to only consume resources while active, leading to less system overhead.
reactive programming with reactive systems
- reactive programming is a useful implementation technique
- reactive programming focuses on non-blocking, asynchronous execution - a key characteristic of reactive systems
- reactive programming is just one tool in building reactive systems
Reactive Programming
- reactive programming is an asynchronous programming paradigm focused on streams of data
- reactive programs also maintain a continuous interaction with their environment, but at a speed which is determined by the environment, not the program itself. Interactive programs work at their own pace and mostly deal with communication, while reactive programs only work in response to external demands and mostly deal with accurate interrupt handling, real time programs are usually reactive.
Common use cases
- external service calls
- highly concurrent message consumers
- spreadsheets
- abstraction over asynchronous processing
- abstract whether or not your program is synchronous or asynchronous
features opf reactive programming
- data streams
- asynchronous
- non-blocking
- backpressure
- failures as messages
data streams
- data streams can be just about anything
- mouse clicks, or other user interactions
- JMS messages, RESTful service calls, Twitter feed, Stock trades, list of data from a database
- a stream is a sequence of events ordered in time
- events you want to listen to
Asynchronous
- events are captured asynchronously
- a function is defined to execute when an event is emitted
- another function is defined if an error is emitted
- another function is defined when complete is emitted
Observer pattern
- you have a subject and an observer
- when the subject is going to change, it will notify the observer
Non-blocking
- the concept of using non blocking is important
- in blocking, the code will stop and wait for more dta (reading from disk, network etc…)
- non blocking in contrast, will process available data, ask to be notified when more is available, then continue
back pressure
- the ability of the subscriber to throttle data
failures as messages
- exceptions are not thrown in a traditional sense
- would break processing of stream
- exceptions are processed by a handler function
Reactive Streams
Spring Reactive Types
- two new reactive types are introduced with Spring framework 5
Mono
is a publisher with zero or one elements in data streamFlux
is a publisher with zero or MANY elements in the data stream- both types implement the reactive streams publisher interface
WebFlux
web MVC | webFlux |
---|---|
@Controller, @RequestMapping | Router functions |
spring-webmvc | spring-webflux |
Servlet API | HTTP / Reactive Streams |
Servlet Container | Tomcat, Jetty, Netty, Undertow |
RESTful web services
- because of their simplicity and versatility, RESTful web services have become the de facto standard for web services
- REST - representational state transfer
- representational - typically JSON or XML
- state transfer - typically via HTTP
terminology
- verbs - HTTP methods: GET, PUT, POST, DELETE
- messages - the payload of the action(JSON / XML)
- URI - uniform resource identifier
- a unique string identifying a resource
- URL - uniform resource locator
- a URI with network information
- Idempotence
- the property of certain operations in mathematics and computer science that they can be applied multiple times without changing the result beyond the initial application
- in other words, you can exercise the operation multiple times, without changing the result
- example: refreshing a web page (HTTP GET operation)
- Stateless - service does not maintain any client state
- HATEOAS - hypermedia as the engine of application state
- a REST client should then be able to use server-provided links dynamically to discover all the available actions and resources it needs, as access proceeds, the server responds with text that includes hyperlinks to other actions that are currently available
GET
- use: to read data from resource
- read only
- idempotent
- safe operation - does not change state of resource
PUT
- use: to insert or update
- idempotent - multiple PUT will not change result
- like saving a file multiple times
- not safe operation - does change state of resource
POST
- use: to create new object
- non-idempotent - multiple POSTs is expected to create multiple objects
- not safe operation - does change state of resource
- only non-idempotent, non-safe HTTP verb
DELETE
- use: to delete an object
- idempotent - multiple DELETEs will have same effect / behavior
- not safe operation, does change the state of resource
MapStruct
- MapStruct is a code generator for Java bean mapping
- helps reduce coding for type conversions
- when dealing with Rest services, a common use case is to expose API data using DTOs (Data Transfer Object)
- as project grows bigger, it is not good to expose POJO directly to Rest services. MapStruct is helping us to convert POJO to DTOs, then export DTOs to Rest service to be consumed by public
Content Negotiation
Content Negotiating view resolver
- used by Spring MVC to determine view handler to use
- auto configured by Spring boot
- the content negotiating view resolver will determine the view to use to render the data of the model to the client
Content type
- view to use is determined by Content Type in HTTP header
- application/json, application/xml, text/html
- if view for requested Content type is not found, HTTP status 406 not acceptable is returned.
Helper Library and Classes
Structure
- the project should follow a structure from database to frontend: Database -> Repository -> Service -> Controller -> View
JPA
- H2 in memory database
Thymeleaf
- frontend template engine, model can be added to view dynamically
Dependency Injection
- Repositories and Services can be injected when needed, use Annotations @Service, @Component
- classes marked as @Component, @Service and @Controller will be managed by Spring Application Context, it will inject necessary class to the right place when needed. (Beans)
Configuration
- config files can be Java, YAML, or XML
- application.properties can define project profiles
JPA entity relationships
- One to Many
- Many to One
- Many to Many (needs mapping table)
JPA Query methods
- e.g. findByDescription
- this is done by the library, findBy + property name
- library will do the implementations for you
Project Lombok
- will do the constructors, getters, setters and even builder patterns for you
JUnit
- Unit Test framework
Mockito
- for unit tests, we do not want to bring in Spring Application Context
- so to manage Repositories and Services, we need Mockito to create some Mock component for us
- when(), thenReturn(), verify(), ArgumentCaptor, MockMvc…
WebJars
- bring in bootstrap library
Web Data Binder
- binds HTTP variables to Java object
- specifically handling form posts and binding form variables to Java data objects
- whereas Rest service we could use RestTemplate
Validations
- @NotBlank, @NotNull, @Max, @Min…
- annotations to data models, for form validations
Exceptions
- @ResponseStatus
- @ControllerAdvice
- dealing with exceptions and custom error messages
Reactive Programming
- Mono, Flux
- WebFlux
- Reactive vs Servlet
RestTemplate
- bind Rest Response to Java objects
WebClient
- performing web request
MapStruct
- auto mapper