- 1. What is Spring?
- 2. Spring Initializr
- 3. REST Controller
- 4. Spring Projects
- 5. Spring Boot Projects
- 6. Spring Boot Starters
- 7. Spring Boot Dev Tools
- 8. Spring Boot Actuator
- 9. Custom Application Properties
- 10. Inversion of Control and Dependency Injection
- 10.1. Injection Types
- 10.2. Autowiring Example
- 10.3. Example Application
- 10.4. Development Process - Constructor Injection
- 10.5. Spring for Enterprise applications
- 10.6. Scanning for Component Classes
- 10.7. Annotations
- 10.8. More on Component Scanning
- 10.9. Setter Injection
- 10.10. @Primary annotation
- 10.11. Lazy Initialization
- 10.12. Bean Scopes
- 10.13. Additional Spring Bean Scopes
- 10.14. Bean Lifecycle Methods - Annotations
- 11. Spring Security
- 11.1. Servlet Filters
- 11.2. Security Concepts
- 11.3. Declarative Security
- 11.4. Programmatic Security
- 11.5. Enabling Spring Security
- 11.6. Authentication and Authorization
- 11.7. Spring Security Password Storage
- 11.8. Restrict Access Based on Roles
- 11.9. Cross-Site Request Forgery (CSRF)
- 11.10. Database Access
- 11.11. Password Storage
- 11.12. Spring Security Team Recommendation
- 11.13. How to Get a Bcrypt password
- 11.14. Spring Security Password Storage
- 11.15. Spring Security Login Process
- 11.16. Matchers
- 12. JPA
- 13. Commands - Run from Command-Line
- 14. Points of attention
- Very popular framework for building Java applications.
- Provides a large number of helper classes and annotations.
- Building a traditional Spring application is really HARD!!!
- Q: Which JAR dependencies do I need?
- Q: How do I set up configuration (xml or Java)?
- Q: How do I install the server? (Tomcat, JBoss etc...)
- And that's JUST the basics for getting started.
- Make it easier to get started with Spring development.
- Minimize the amount of manual configuration.
- Perform auto-configuration based on props files and JAR classpath.
- Help to resolve dependency conflicts (Maven or Gradle).
- Provide an embedded HTTP server so we can get started quickly.
- Tomcat, Jetty, Undertow, ...
- Spring Boot uses Spring behind the scenes
- Spring Boot simply makes it easier to use Spring
- No need to install a server separately.
- Self-contained unit Nothing else to install!
- Spring Boot apps can be run standalone (includes embedded server).
- Run the Spring Boot app from the IDE or command-line.
java -jar <name_jar_file>.jar
- Spring Boot apps can also be deployed in the traditional way.
- Deploy Web Application Archive (WAR) file to an external server:
- Tomcat, JBoss, WebSphere etc ...
- Q: Does Spring Boot replace Spring MVC, Spring REST etc ...?
- Q: Does Spring Boot run code faster than regular Spring code?
- No.
- Behind the scenes, Spring Boot uses same code of Spring Framework.
- Remember, Spring Boot is about making it easier to get started.
- Minimizing configuration etc ...
- Q: Do I need a special IDE for Spring Boot?
- No.
- We can use any IDE for Spring Boot apps ... even use plain text editor.
- The Spring team provides free Spring Tool Suite (STS) [IDE plugins].
- Some IDEs provide fancy Spring tooling support.
- Not a requirement.
- Quickly create a starter Spring Boot project.
- Select your dependencies.
- Creates a Maven/Gradle project.
- Import the project into your IDE.
- Eclipse, IntelliJ, NetBeans etc ...
- start.spring.io
- If we are building a Spring app that needs: Web, Security, ...
- Simply select the dependencies in the Spring Initializr.
- It will add the appropriate Spring Boot starters to your
pom.xml
.
- Alternative to start.spring.io.
- Basic structure:
@RestController public class HelloWorldController { @GetMapping("/") public String sayHello() { return "Hello World!"; } }
- Example
- Additional Spring modules built-on top of the core Spring Framework
- Only use what we need ...
- Spring Cloud, Spring Data.
- Spring Batch, Spring Security.
- Spring Web Services, Spring LDAP.
- others ...
mvnw
allows we to run a Maven project.- No need to have Maven installed or present on your path.
- If correct version of Maven is NOT found on your computer.
- Automatically downloads correct version and runs Maven.
- Two files are provided:
mvnw.cmd
for MS Windows.mvnw clean compile test
mvnw.sh
for Linux/Mac../mvnw clean compile test
- If we already have Maven installed previously.
- Just use Maven as you normally would.
mvn clean compile test
-
pom.xml includes info that you entered at Spring Initializr website.
<groupId>com.starterspringbootproject</groupId> <artifactId>starter-spring-boot-project</artifactId> <version>0.0.1-SNAPSHOT</version>
-
Spring Boot Starters, a collection of Maven dependencies (Compatible versions).
<dependencies> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ... </dependencies>
-
To package executable
jar
orwar
archive, can also easily run the app.<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
- The Problem...
- Building a Spring application is really HARD!!!
- Why Is It So Hard?
- It would be great if there was a simple list of Maven dependencies.
- Collected as a group of dependencies ... one-stop shop.
- So I don't have to search for each dependency.
- Spring Boot Starters
- A curated list of Maven dependencies.
- A collection of dependencies grouped together.
- Tested and verified by the Spring Development team.
- Makes it much easier for the developer to get started with Spring.
- Reduces the amount of Maven configuration.
- There are 30+ Spring Boot Starters from the Spring Development team.
Name Description spring-boot-starter-web Building web apps, includes validation, REST. Uses Tomcat as default embedded server. spring-boot-starter-security Adding Spring Security support. spring-boot-starter-data-jpa Spring database support with JPA and Hibernate. ... - Full list
- The Problem...
- When running Spring Boot applications.
- If you make changes to your source code.
- Then we have to manually restart your application.
- When running Spring Boot applications.
- Solution: Spring Boot Dev Tools.
spring-boot-devtools
to the rescue!- Automatically restarts your application when code is updated.
- Simply add the dependency to your POM file.
- No need to write additional code :-).
- For IntelliJ, need to set additional configurations...
- Adding the dependency to your POM file:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
- Automatically restarts your application when code is updated.
- IntelliJ Community Edition does not support DevTools by default.
- Select: File > Settings > Build, Execution, Deployment > Compiler.
- Check box: Build project automatically.
- Select: File > Settings > Advanced Settings.
- Check box: Allow auto-make to ...
- Apply IntelliJ configurations.
- Edit
pom.xml
and add spring-boot-devtools. - Add new REST endpoint to our app.
- Verify the app is automatically reloaded.
- Problem...
- How can we monitor and manage my application?
- How can we check the application health?
- How can we access application metrics?
- Solution: Spring Boot Actuator
- Exposes endpoints to monitor and manage your application.
- We easily get DevOps functionality out-of-the-box.
- Simply add the dependency to your POM file.
- REST endpoints are automatically added to your application.
- No need to write additional code!
- We get new REST endpoints for FREE!
- Adding the dependency to your POM file:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
- Automatically exposes endpoints for metrics out-of-the-box.
- Endpoints are prefixed with:
/actuator
.
/health
checks the status of your application.- Normally used by monitoring apps to see if your app is up or down.
- Health status is customizable based on your own business logic.
- By default, only
/health
is exposed. - The
/info
endpoint can provide information about your application. - To expose
/info
. - File:
src/main/resources/application.properties
.management.endpoints.web.exposure.include=health,info management.info.env.enabled=true
/info
gives information about your application.- Default is empty.
- Update
application.properties
with your app info. - File:
src/main/resources/application.properties
info.app.name=Actuator Project info.app.description=An example project using Spring Boot Actuator. info.app.version=1.0.0
- There are 10+ Spring Boot Actuator endpoints:
Name Description /auditevents Audit events for your application /beans List of all beans registered in the Spring application context /mappings List of all @RequestMapping paths ... ...
- By default, only
/health
is exposed. - To expose all actuator endpoints over HTTP.
- File:
src/main/resources/application.properties
# Use wildcard "*" to expose all endpoints # Can also expose individual endpoints with a comma-delimited list # management.endpoints.web.exposure.include=*
- Edit
pom.xml
and addspring-boot-starter-acuator
. - View actuator endpoints for:
/health
.http://localhost:8080/actuator/health
- Edit
application.properties
to customize/info
.
- What about Security?
- We may NOT want to expose all of this information.
- Solution
- Add Spring Security to project and endpoints are secured.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- Now when we access:
/actuator/beans
.- Spring Security will prompt for login.
- Default user name: user.
- Check console logs for password.
- We can override default user name and generated password.
- File:
src/main/resources/application.properties
spring.security.user.name=jefte spring.security.user.password=euamojesus
- We can customize Spring Security for Spring Boot Actuator.
- Use a database for roles, encrypted passwords etc...
- To exclude
/health
- File:
src/main/resources/application.properties
management.endpoints.web.exposure.exclude=health
- Edit
pom.xml
and addspring-boot-starter-security
. - Verify security on actuator endpoints for:
/beans
etc. - Disable endpoints for
/health
and/info
.
- Problem
- You need for your app to be configurable ... no hard-coding of values.
- You need to read app configuration from a properties file.
- Solution:
- Application Properties file.
- By default, Spring Boot reads information from a standard properties file.
- Located at:
src/main/resources/application.properties
- Standard Spring Boot file name.
- Located at:
- You can define ANY custom properties in this file.
- Your Spring Boot app can access properties using
@Value
.- No additional coding or configuration required.
- Define custom properties in
application.properties
.- File:
src/main/resources/application.properties
. -
books.name=Bible authors.name=God
- File:
- Inject properties into Spring Boot application using
@Value
.
@RestController
public class MyRestController {
@Value("${books.name}")
private String book;
@Value("${authors.name}")
private String author;
@GetMapping("/")
public String GetBook() {
return "Book: " + book + " By " + author;
}
}
- Spring Boot can be configured in the
application.properties
file. - Server port, context path, actuator, security etc ...
- Spring Boot has 1,000+ properties.
- The properties are roughly grouped into the following categories:
- Core
- Web
- Security
- Actuator
- Integration
- DevTools
- Data
- Testing
# Log levels severity mapping
logging.level.org.springframework=DEBUG
logging.level.org.hibernate=TRACE
logging.level.com.myfirstapp=INFO
# Log file name
logging.file.name=my-crazy-stuff.log
logging.file.path=c:/myapps/demo
# HTTP server port
server.port=7070
# Context path of the application
server.servlet.context-path=/my-first-app
# Default HTTP session time out
server.servlet.session.timeout=15m
# Endpoints to include by name or wildcard
management.endpoints.web.exposure.include=*
# Endpoints to exclude by name or wildcard
management.endpoints.web.exposure.exclude=beans,mapping
# Base path for actuator endpoints
management.endpoints.web.base-path=/actuator
# Default user name
spring.security.user.name=admin
# Password for default user
spring.security.user.password=admin@123
# JDBC URL of the database
spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce
# Login username of the database
spring.datasource.username=admin
# Login password of the database
spring.datasource.password=admin@123
- There are multiple types of injection with Spring.
- We will cover the two recommended types of injection
- Constructor Injection
- Setter Injection
- Constructor Injection
- Use this when you have required dependencies.
- Generally recommended by the spring.io development team as first choice.
- Setter Injection
- Use this when you have optional dependencies.
- If dependency is not provided, your app can provide reasonable default logic.
- Field Injection
- Not recommended by the spring.io development team.
- In the early days, field injection was popular on Spring projects.
- In recent years, it has fallen out of favor.
- In general, it makes the code harder to unit test.
- As a result, the spring.io team does not recommend field injection.
- However, you will still see it being used on legacy projects.
- For dependency injection, Spring can use
autowiring
. - Spring will look for a class that matches.
- matches by type: class or interface.
- Spring will inject it automatically ... hence it is
autowired
.
- Injecting a
Payment
implementation. - Spring will scan for
@Components
. - Any one implements the
Payment
interface??? - If so, let's inject them. For example:
PixPayment
.
- Define the dependency interface and class.
- Create Demo REST Controller.
- Create a constructor in your class for injections.
- Add
@GetMapping
for/discount
.
- Spring is targeted for enterprise, real-time / real-world applications.
- Spring provides features such as:
- Database access and Transactions.
- REST APIs and Web MVC.
- Security.
- etc ...
- Spring will scan your Java classes for special annotations.
@Component
, etc ...
- Automatically register the beans in the Spring container.
@SpringBootApplication
is composed of the following annotations:Annotation Description @EnableAutoConfiguration Enables Spring Boot's auto-configuration support. @ComponentScan Enables component scanning of current package also recursively scans sub-packages. @Configuration Able to register extra beans with or import other configuration classes.
- By default, Spring Boot starts component scanning.
- From same package as your main Spring Boot application.
- Also scans sub-packages recursively.
- This implicitly defines a base search package
- Allows you to leverage default component scanning.
- No need to explicitly reference the base package name.
- Constructor Injection.
- Setter Injection.
- Inject dependencies by calling setter method(s) on your class.
- Injecting a Payment implementation.
- Spring will scan
@Components
- Any one implements Payment interface???
- If so, let's inject them ... oops which one?
- Resolving issue with Multiple Payment implementations.
- In the case of multiple Payment implementations.
- We resolved it using
@Qualifier
- We specified a payment by name.
- We resolved it using
- Alternate solution available...
- In the case of multiple Payment implementations.
- Instead of specifying a payment by name using
@Qualifier
- I simply need a payment ... I don't care which payment
- If there are multiple payments
- Then we payments figure it out ... and tell me who's the
primary
payment
- When using
@Primary
, can have only one for multiple implementations. - If you mark multiple classes with @Primary ... umm, we have a problem.
- Mixing @Primary and @Qualifier
- If we mix
@Primary
and@Qualifier
@Qualifier
has higher priority
@Primary
leaves it up to the implementation classes.- Could have the issue of multiple
@Primary
classes leading to an error.
- Could have the issue of multiple
@Qualifier
allows to you be very specific on which bean you want.- In general, I recommend using
@Qualifier
- More specific.
- Higher priority.
- By default, when your application starts, all beans are initialized.
@Component
, etc ...
- Spring will create an instance of each and make them available.
- Instead of creating all beans up front, we can specify lazy initialization
- A bean will only be initialized in the following cases:
- It is needed for dependency injection
- Or it is explicitly requested
- Add the
@Lazy
annotation to a given class - To configure other beans for lazy initialization.
- We would need to add
@Lazy
to each class. - Turns into tedious work for a large number of classes.
- I wish we could set a global configuration property ...
- Advantages
- Only create objects as needed.
- May help with faster startup time if you have large number of components.
- Disadvantages
- May not discover configuration issues until too late.
- If you have web related components like @RestController, not created until requested.
- Need to make sure you have enough memory for all beans once created.
- Lazy initialization feature is disabled by default.
- You should profile your application before configuring lazy initialization.
- Avoid the common pitfall of premature optimization.
- Scope refers to the lifecycle of a bean.
- How long does the bean live?
- How many instances are created?
- How is the bean shared?
- Default scope is singleton
- Refresher: What's a Singleton?
- Spring Container creates only one instance of the bean, by default.
- It is cached in memory.
- All dependency injections for the bean.
- will reference the SAME bean.
Scope | Description |
---|---|
singleton | Create a single shared instance of the bean. Default scope. |
prototype | Creates a new bean instance for each container request. |
request | Scoped to an HTTP web request. Only used for web apps. |
session | Scoped to an HTTP web session. Only used for web apps. |
application | Scoped to a web app ServletContext. Only used for web apps. |
websocket | Scoped to a web socket. Only used for web apps. |
- We could use the Amazon S3 Client in our Spring application
- The Amazon S3 Client class was not originally annotated with @Component
- However, we configured the S3 Client as a Spring Bean using @Bean
- It is now a Spring Bean and we can inject it into other services of our application
- Make an existing third-party class available to Spring framework
- Spring Security Model
- Spring Security defines a framework for security.
- Implemented using Servlet filters in the background.
- Two methods of securing an app: declarative and programmatic.
- Servlet Filters are used to pre-process / post-process web requests.
- Servlet Filters can route web requests based on security logic.
- Spring provides a bulk of security functionality with servlet filters.
- Authentication
- Check user id and password with credentials stored in app / db.
- Authorization
- Check to see if user has an authorized role.
- Define application's security constraints in configuration.
- All Java config:
@Configuration
.
- All Java config:
- Provides separation of concerns (SoC) between application code and security.
- Spring Security provides an API for custom application coding.
- Provides greater customization for specific app requirements.
- Edit
pom.xml
and addspring-boot-starter-security
.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
-
This will automagically secure all endpoints for application.
- Now when we access our application.
- Spring Security will prompt for login.
- Default user name: user
- Check console logs for password.
-
We can override default user name and generated password.
- File:
src/main/resources/application.properties
spring.security.user.name=jefte
spring.security.user.password=master@123
- In-memory.
- JDBC.
- LDAP.
- Custom / Pluggable.
- Others...
- In Spring Security, passwords are stored using a specific format:
{id}encodedPassword
ID | Description |
---|---|
noop | Plain text passwords |
bcrypt | BCrypt password hashing |
... | ... |
INSERT INTO `authorities`
VALUES
('brenno', 'ROLE_TEACHER'),
('barbara', 'ROLE_TEACHER'),
('barbara', 'ROLE_COORDINATOR'),
('jefte', 'ROLE_TEACHER'),
('jefte', 'ROLE_COORDINATOR'),
('jefte', 'ROLE_ADMIN');
- Spring Security can protect against CSRF attacks.
- Embed additional authentication data/token into all HTML forms.
- On subsequent requests, web app will verify token before processing.
- Primary use case is traditional web applications (HTML forms etc ...).
- The Spring Security team recommends.
- Use CSRF protection for any normal browser web requests.
- Traditional web apps with HTML forms to add/modify data.
- If we are building a REST API for non-browser clients.
- We may want to disable CSRF protection.
- In general, not required for stateless REST APIs.
- That use POST, PUT, DELETE and/or PATCH.
- Example
http.csrf(csrf -> csrf.disable());
- In general, CSRF is not required for stateless REST APIs that use POST, PUT, DELETE and/or PATCH.
- Spring Security can read user account info from database.
- By default, you have to follow Spring Security's predefined table schemas.
- Can also customize the table schemas.
- Useful if you have custom tables specific to your project / custom.
- We will be responsible for developing the code to access the data.
- JDBC, JPA/Hibernate etc ...
- So far, our user passwords are stored in plaintext.
- But not for production / real-time project.
INSERT INTO `users` VALUES ('brenno', '{noop}master@123', 1), ('barbara', '{noop}master@123', 1), ('jefte', '{noop}master@123', 1);
- The best practice is store passwords in an encrypted format.
INSERT INTO `users` VALUES ('brenno', '{bcrypt}$2a$10$a2eZLPE1rSQ7ZIqnD2IxPOoBedWMBgNpU.s14k7IPq6EsDixn/5SC', 1), ('barbara', '{bcrypt}$2a$10$KQsIaTz9PeTB9kb3S05dhec6qhsCFjjIU/0kecWapur5V3B98vNDy', 1), ('jefte', '{bcrypt}$2a$10$pexiL67R6kwy/rHOSClyZO3ZIh/uPuDoFd3EQB0WS42l1q2BDOTVm', 1);
- Spring Security recommends using the popular bcrypt algorithm.
- bcrypt
- Performs one-way encrypted hashing.
- Adds a random salt to the password for additional protection.
- Includes support to defeat brute force attacks.
- We have a plaintext password and you want to encrypt using bcrypt.
- Option 1: Use a website utility to perform the encryption.
- Option 2: Write Java code to perform the encryption.
- In Spring Security, passwords are stored using a specific format:
{bcrypt}encodedPassword
- Password column must be at least 68 chars wide
{bcrypt}
- 8 chars- encodedPassword - 60 chars
- Retrieve password from db for the user.
- Read the encoding algorithm id (bcrypt etc).
- For case of bcrypt, encrypt plaintext password from login form (using salt from db password).
- Compare encrypted password from login form WITH encrypted password from db.
- If there is a match, login successful.
- If no match, login NOT successful.
- Note: The password from db is NEVER decrypted Because bcrypt is a one-way encryption algorithm.
requestMatchers("/**")
- The
/**
pattern matches all routes, allowing unrestricted access.
- The
- During development we spend most of our time in the IDE.
- However, we may want to run our Spring Boot app outside of the IDE.
- One approach is running from the command-line.
- When running from the command-line.
- No need to have IDE open/running.
- Since we using Spring Boot, the server is embedded in our JAR file.
- No need to have separate server installed/running .
- Spring Boot apps are self-contained.
- Two options for running the app
- Option 1: Use
java -jar <my_jar_file.jar>
- Option 2: Use Spring Boot Maven plugin
mvnw spring-boot:run
- Run from command prompt!
- Create new Maven project
mvn archetype:generate -DgroupId=com.packagename -DartifactId=ClassName -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
- Rum Spring Boot project
mvn spring-boot:run
- Test...
mvn clean install -U
- List of possibilities
spring init --list
- Create new Maven project with Spring Boot
spring init --type=maven-project --javaVersion=22 --artifactId=starter-spring-boot-project --groupId=com.starterpringbootproject
spring init --type=maven-project --javaVersion=22 --artifactId=starter-rest-controller --groupId=com.starterrestcontroller --dependencies=web,devtools,actuator,security
- spring-boot-devtools
- spring-boot-starter-web
- spring-boot-starter-security
- spring-boot-starter-actuator
- To use
ObjectMapper (com.fasterxml.jackson.core)
class without@Bean
is necessary:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
- Otherwise... compilation error
- Parameter 1 of constructor in com.example.SecretsManagerApplication required a bean of type 'com.fasterxml.jackson.databind.ObjectMapper' that could not be found.