TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at - Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Similaire à TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at - Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Similaire à TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at - Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC (20)
TDC2017 | São Paulo - Trilha Java EE How we figured out we had a SRE team at - Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
1. TRILHA JAVA EE
CONSTRUINDO APIS DE FORMA PRODUTIVA COM
SPRING BOOT, SPRING DATA E SPRING MVC
Emmanuel Neri
12. SPRING MVC
SIMPLICIDADE NA
EXPOSIÇÃO DE APIS
ABSTRAÇÃO NA
SERIALIZAÇÃO /
DESERIALIZAÇÃO
FACILIDADE NA
LEITURA DE
PARÂMETROS
TRATAMENTO DE
ERROS
CONSTRUÇÃO
SIMPLES
ESTRUTURA DE
RETORNO
13. SIMPLICIDADE NA EXPOSIÇÃO DE APIS
@RestController
@RequestMapping("/customers")
public class CustomerController {
@RequestMapping(method = RequestMethod.GET)
public List<Customer> findAll() {
return customerService.findAll();
}
}
http://localhost:8080/customers
14. ABSTRAÇÃO NA SERIALIZAÇÃO / DESERIALIZAÇÃO
@RequestMapping(method = RequestMethod.GET)
public List<Customer> findAll() {
return customerService.findAll();
}
@RequestMapping(method = RequestMethod.POST)
public void save(@RequestBody BillDTO billDTO) {
billService.save(billDTO);
}
15. ABSTRAÇÃO NA SERIALIZAÇÃO / DESERIALIZAÇÃO
import com.fasterxml.jackson.annotation.JsonFormat;
public final class BillDTO {
@JsonFormat(pattern = "yyyy-MM")
private YearMonth yearMonth;
16. FACILIDADE NA LEITURA DE PARÂMETROS
@RequestMapping(value = "/byUk/{customerId}/{identifier}/{yearMonth}",
method = RequestMethod.GET)
public Bill findByUk(@PathVariable("customerId") Long customerId,
@PathVariable("identifier") String identifier,
@PathVariable("yearMonth") YearMonth yearMonth) {
return billService.findByUk(customerId, identifier, yearMonth);
}
@RequestMapping(value = "/search", method = RequestMethod.GET)
public List<Customer> search(
@RequestParam(value = "id", required = false) Long id,
@RequestParam(value = "name", required = false) String name){
return customerService.search(new CustomerSearchTO(id, name));
}
18. TRATAMENTO DE ERROS
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Set<ExceptionTO>>
handleError(ConstraintViolationException ex) {
final Set<ExceptionTO> erros = ex.getConstraintViolations().stream()
.map(c -> new ExceptionTO(c.getMessage()))
.collect(Collectors.toSet());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(erros);
}
@ExceptionHandler(Exception.class)
public ResponseEntity handleError(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("O sistema se encontra indisponível”);
}
21. ABSTRAÇÃO NO ACESSO AOS DADOS
public Customer save(Customer customer) {
return customerRepository.save(customer);
}
public List<Customer> findAll() {
return customerRepository.findAll();
}
public Page<Customer> findPaginable(int page, int size) {
final Sort sort = new Sort(Sort.Direction.DESC, "name");
return customerRepository.findAll(
new PageRequest(page, size, sort));
}
22. ABSTRAÇÃO NO ACESSO AOS DADOS
Bill findByCustomerIdAndIdentifierAndYearMonth(Long customerId,
String identifier, YearMonth yearMonth);
Hibernate: select bill… from bill bill0_ where bill0_.customer_id=? and bill0_.identifier=? and
bill0_.year_month=?
@Modifying
@Query("delete from BillItem where bill.id = :#{#billId}")
void deleteByBillItem(@Param("billId") Long billId);
Hibernate: delete from bill where id=?
23. ABSTRAÇÃO NO ACESSO AOS DADOS
‣ Integração com QueryDSL
public interface BillRepository extends JpaRepository<Bill, Long>,
QueryDslPredicateExecutor<Bill> {
public Page<Bill> search(BillSearchTO searchTO) {
return billRepository.findAll(searchTO.toPredicate(),
new PageRequest(searchTO.getPage(), searchTO.getSize(),
new Sort(Sort.Direction.DESC, "id")));
}
public class BillSearchTO {
public BooleanBuilder toPredicate() {
final QBill qBill = QBill.bill;
final BooleanBuilder predicate = new BooleanBuilder();
if(!Strings.isNullOrEmpty(identifier)) {
predicate.and(qBill.identifier.eq(identifier));
}
24. ACESSO AOS DADOS
‣ Repositorios customizados
public interface BillRepositoryCustom {
Page<BillDTO> findAll(BillSearchTO searchTO);
}
public class BillRepositoryImpl implements BillRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Override
public Page<BillDTO> findAll(BillSearchTO searchTO) {
final JPQLQuery jpaQuery = new JPAQuery(entityManager)
.from(qBill)
.join(qBill.carrier).fetchJoin()
.join(qBill.customer).fetchJoin()
.join(qBill.items).fetchJoin();
...
25. ACESSO AOS DADOS
‣ Repositorios customizados
public interface BillRepository extends JpaRepository<Bill, Long>,
QueryDslPredicateExecutor<Bill>, BillRepositoryCustom {
...
26. SUPORTE A DIFERENTE FONTES DE DADOS
‣ Módulos Spring
‣ Módulos da comunidade
JPA LDAP
REST
27. SUPORTE A DIFERENTE FONTES DE DADOS
public interface BillFileRepository extends MongoRepository<BillFile, String> {
}
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "bill_file")
@Getter
public class BillFile {
@Id
private String id;
private String date;
private String content
28. CACHE
‣ JSR-107
‣ Caffeine
‣ Guava cache
‣ EhCache
‣ GemFire
@SpringBootApplication
@EnableCaching
public class AppConfig {
@Cacheable("carriers")
public List<Carrier> findAll() {
return carrierRepository.findAll();
}