This motivation is taken from Google Guice Wiki https://github.com/google/guice/wiki/Motivation
Wiring everything together is a tedious part of application development. There are several approaches to connect data, service, and presentation classes to one another. To contrast these approaches, we'll write the billing code for online shop:
public interface BillingService {
/**
* Attempts to charge the order to the credit card. Both successful and
* failed transactions will be recorded.
*
* @return a receipt of the transaction. If the charge was successful, the
* receipt will be successful. Otherwise, the receipt will contain a
* decline note describing why the charge failed.
*/
Receipt chargeOrder(Order order, CreditCard creditCard);
}
Along with the implementation, we'll write unit tests for our code.
Here's what the code looks like when we just new up the credit card processor and transaction logger:
public class CreditCardBillingService implements BillingService {
public Receipt chargeOrder(Order order, CreditCard creditCard) {
CreditCardProcessor processor = new PaypalCreditCardProcessor();
TransactionLog transactionLog = new DatabaseTransactionLog();
try {
ChargeResult result = processor.charge(creditCard, order.getAmount());
transactionLog.logChargeResult(result);
return result.wasSuccessful()
? Receipt.forSuccessfulCharge(order.getAmount())
: Receipt.forDeclinedCharge(result.getDeclineMessage());
} catch (UnreachableException e) {
transactionLog.logConnectException(e);
return Receipt.forSystemFailure(e.getMessage());
}
}
}
This code poses problems for modularity and testability. The direct, compile-time dependency on the real credit card processor means that testing the code will charge a credit card! It's also awkward to test what happens when the charge is declined or when the service is unavailable.
To do:
- add all required classes
- use interfaces where possible
- create unit tests
To do:
- implement factories for
CreditCardProcessorandTransactionLog, factories should havesetInstanceandgetInstancestatic methods - create unit tests
To do:
- use constructor parameters for providing required dependencies
- create unit tests
To read:
To do:
- use Spring Core for dependency injection
- create unit tests
To read:
- Building an application with Spring Boot
- Building a RESTful Web Service
- Accessing data with MySQL
- Building REST Services with Spring
To do:
- add required Spring Boot & Spring Data dependencies (starters)
- create controllers, services and repositories for users, orders, receipts, transaction logs and other useful objects
- add unit tests
To read:
To do:
- use
RestTemplateto implementCreditCardProcessor, which will use REST API of another service - create Spring Boot application (called Credit Card Application) with REST API for charging credit cards
To read:
To do:
- in Credit Card Application create some controllers and views for credit card operations
To read:
To do:
- add security in Credit Card Application, only authorized users can use the application