Overview of Micro Services architecture Springboot features Kafka (1)
================================================================
Day -1
Getting started with Spring Boot
Building RESTFul Microservices using Spring MVC
Interacting with database using Spring Data
Day -2
Introduction to Microservices Architecture
Apply 12 Factor methodology in Microservices using Spring Cloud
Day -3
Introduction to Publish Subscribe Messaging
Implementing Asynchronous Communication using Kafka
Introduction to Containerization
Building Docker Images for Microservices
Bankapplication applicatation
---------------------------
* Spring vs Spring boot, Spring boot introduction
* Spring DI Qucick recap
* AOP how to handle cross cutting concerns
* Spring boot rest
* spring boot data jpa
* Excpetion handling
* Validation
* Actuator
* logging
* Security
Advantage of spring boot , configuration spring boot
---------------------------------------------------
=> Auto-Configuration
=> Dependency Management
=> Externalized Configuration
bean can be configured through [Link] file
without touching java or xml config
=> Production support
We get health checking, application and jvm metrics,
jmx via http and a few more things for free
=> Runnable Jars
We can package your application as a runnable jar with embedded tomcat
included so it presents a self-contained deployment unit
=> Microservice
Getting started with spring boot:
--------------------------------
bank application 3 tier
controller layer -------------------- service layer ------------------- dao layer
--------------db
repository layer
Step 1: understading why we need DI?
------------------------------------
Dao layer:
--------------
public class Account {
private int id;
private String name;
private double balance;
}
public interface AccountDao {
public List<Account> getAll();
public Account getById(int id);
public void updateAccount(Account account);
public void addAccount(Account account);
public void deleteAccount(int id);
}
public class AccountDaoCollectionImpl implements AccountDao{
private Map<Integer, Account> accounts=new HashMap<>();
public AccountDaoCollectionImpl() {
[Link](1, new Account(1, "raj", 560000.00));
[Link](2, new Account(2, "ekta", 760000.00));
}
@Override
public List<Account> getAll() {
[Link]("getAll using hard coded collection...");
return new ArrayList<Account>([Link]());
}
@Override
public Account getById(int id) {
return [Link](id);
}
@Override
public void updateAccount(Account account) {
[Link]([Link](), account);
}
Service layer:
-----------------
public interface AccountService {
public List<Account> getAll();
public Account getById(int id);
public void addAccount(Account account);
public void deleteAccount(int id);
public void transfer(int fromAccId, int toAccId, BigDecimal amount);
public void deposit(int accId, BigDecimal amount);
public void withdraw(int accId, BigDecimal amount);
}
Step 6: using validation api
--------------------------------
4. using validation api
_____________________
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private int id;
@NotNull(message = "{[Link]}")
@Pattern(regexp = "[A-Za-z]+( [A-Za-z]+)*", message =
"{[Link]}")
private String name;
@NotNull(message = "{[Link]}")
@Range(min = 100, max = 100000, message = "{[Link]}")
private BigDecimal balance;
@Email(message = "{[Link]}")
@NotNull(message = "{[Link]}")
private String email;
@NotNull(message = "{[Link]}")
@Pattern(regexp = "[789][0-9]{9}", message = "{[Link]}")
private String phone;
public AccountDto(String name, BigDecimal balance, String email, String
phone) {
[Link] = name;
[Link] = balance;
[Link] = email;
[Link] = phone;
}
}
@RestControllerAdvice
public class AccountExceptionRestController {
@Autowired
private Environment environment;
// ---------handling 404 error------
@ExceptionHandler([Link])
public ResponseEntity<ErrorInfo>
handleAccountNotFound(AccountNotFoundException accountNotFoundException) {
ErrorInfo errorInfo = new
ErrorInfo().builder().dateTime([Link]()).toContact("masterbank@[Link]"
)
.errorCode(404).errorMessage([Link](accoun
[Link]())).build();
return [Link](HttpStatus.NOT_FOUND).body(errorInfo);
}
// ---------handling 500 error------
@ExceptionHandler([Link])
public ResponseEntity<ErrorInfo> handle500(Exception exception) {
ErrorInfo errorInfo = new
ErrorInfo().builder().dateTime([Link]()).toContact("masterbank@[Link]"
)
.errorCode(500).errorMessage([Link](except
[Link]())).build();
return
[Link](HttpStatus.INTERNAL_SERVER_ERROR).body(errorInfo);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler([Link])
public Map<String, String>
handleInvalidArgument(MethodArgumentNotValidException ex) {
Map<String, String> errorMap = new HashMap<>();
[Link]().getFieldErrors().forEach(error -> {
[Link]([Link](), [Link]());
});
return errorMap;
}
}
[Link]
-------------------------------
[Link]=Please provide email address
[Link]=Please provide valid email address
[Link]=Please provide customer name
[Link]=Name should contain only alphabets and space
[Link]=Please provide phone
[Link]=Please provide correct phone number of 10 digits
[Link]=Please provide initial balance
[Link]=Please provide correct initial balance bw 100 to 100000
spring boot reading property files:
---------------------------------
1. @Value annotation
2. Enviornment
3. @ConfigrationProperties
@EnableConfigurationProperties([Link])
@ConfigurationProperties(prefix = "msg")
Step 7: Aspect Oriented Programming, how it helps, configuration, examples
------------------------------------------------------------------
Applying logging advice to fund transfer application:
<aop:aspectj-autoproxy />
<dependency>
<groupId>[Link]</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
@Retention([Link])
@Target([Link])
public @interface Loggable {
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Component
@Aspect
public class MethodLogger {
private static final Logger
logger=[Link]([Link]);
@Around("@annotation(Loggable)")
public Object around(ProceedingJoinPoint point) throws Throwable {
long start = [Link]();
Object result = [Link]();
[Link]("Method call takes" +([Link]() - start));
return result;
}
}
// [Link]("start
"+[Link]([Link]()).getMethod().getName()+" is
called"+" takes+([Link]() - start));
Property file sample:
-------------------
[Link]=8090
[Link]-path=/bankapp
[Link]-class-name= [Link]
[Link]= [Link].MySQL5InnoDBDialect
[Link]-auto= update
[Link]=jdbc:mysql://localhost:3306/busycoder?useSSL=false
[Link]=root
[Link]=root
[Link]-sql=true
[Link].format_sql=true
[Link]-auto=update
# if u want to disable logging
#[Link]=OFF
#[Link]=OFF
#[Link]-mode=OFF
[Link]: DEBUG
[Link]: ERROR
[Link]: INFO
[Link]: INFO
[Link]= "%d{yyyy-MM-dd } [%thread] %-5level %logger{36} - %msg%n"
#logging pattern for file
[Link]= "%d{yyyy-MM-dd } [%thread] %-5level %logger{36} - %msg%n"
#i wnat to send logs to a specific file?
[Link]-sql=true
[Link]=
[Link]=true
[Link]=*
[Link]=*
[Link]=true
[Link]=UTF-8
[Link]=21
[Link]=21
[Link]=productapp
[Link]=amit ku
[Link]-details=always
[Link]=true
# livenessstate readinessstate
#[Link]=true
#[Link]=true
[Link]=default
[Link]=test
UserInterface.TRANSFER_SUCCESS=transfer done successfully
UserInterface.DEPOSIT_SUCCESS=amount deposit successfully
UserInterface.WITHDRAW_SUCCESS=amount withdraw successfully
Service.ACCOUNT_NOT_EXISTS=Account not exist
Service.FROM_ACCOUNT_NOT_EXISTS=From Account not exist
Service.TO_ACCOUNT_NOT_EXISTS=To Account not exist
Service.NOT_SUFFICIENT_BALANCE=Account dont have sufficient balance
[Link]=jdbc:h2:mem:testdb
[Link]=[Link]
[Link]=foo
[Link]=foo
[Link]-platform=[Link].H2Dialect
[Link]=true
# Custom H2 Console URL
[Link]=/h2
[Link]-auto=update