Se ha denunciado esta presentación.
Se está descargando tu SlideShare. ×

Workshop Microservices - Construindo APIs RESTful com Spring Boot

Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio

Eche un vistazo a continuación

1 de 144 Anuncio
Anuncio

Más Contenido Relacionado

Presentaciones para usted (20)

Similares a Workshop Microservices - Construindo APIs RESTful com Spring Boot (20)

Anuncio

Más de Rodrigo Cândido da Silva (17)

Más reciente (20)

Anuncio

Workshop Microservices - Construindo APIs RESTful com Spring Boot

  1. 1. Workshop Microservices Construindo APIs RESTful com Spring Boot
  2. 2. Objetivos • Ao final desta unidade você irá: • Implementar a primeira aplicação utilizando Spring Boot • Compreender as funcionalidades adicionais do Spring Boot • Compreender como implementar serviços REST utilizando Spring MVC • Implementar persistência de dados utilizando Spring Data • Expor os repositórios como serviços utilizando Spring Data REST • Implementar segurança utilizando Spring Security • Explorar os demais projetos do ecossistema Spring
  3. 3. Agenda • Spring Boot • Spring MVC • Spring REST • Spring Data • Spring Data REST • Spring Security • Demais projetos • Batch, Cache, Messaging, Integration, WebSockets, …
  4. 4. Spring Ecosystem
  5. 5. Spring Boot • Micro-framework para criação aplicações standalone • Boot com embedded Java container • Indicado para criação de micro-serviços • Fornece várias funcionalidades por padrão • Utiliza o conceito de configuração por “defaults” • Ótima integração com toda plataforma Spring • Spring MVC, Spring Data, Spring Security, … • Suporta empacotamento JAR ou WAR
  6. 6. Spring Boot • O que NÃO é: • Plugins para IDE • Você pode utilizar Spring Boot com qualquer IDE • Ferramenta para geração de código • Um novo container Java EE • Arquitetura “ready” para Microservices
  7. 7. Spring Boot
  8. 8. Spring Boot (configuração inicial) <project> <!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.3.RELEASE</version> </parent> <!-- Add typical dependencies for a web application --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <!-- Package as an executable jar --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
  9. 9. Spring Boot • Como rodar a aplicação? • IDE (Spring Tool Suite) • Import… -> Existing Maven Projects • Relaunch / Run • Maven plugin • mvn spring-boot:run • export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M • Standalone “fat JAR” • java -jar target/myproject-0.0.1-SNAPSHOT.jar • java -Xdebug - Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/myproject-0.0.1-SNAPSHOT.jar
  10. 10. Spring Boot (deployment) • Pode ser realizado via standalone “fat JAR”, ou por meio de um WAR web package • Suporta deployment em Java EE containers • Tomcat, Jetty, Wildfly, TomEE, Glassfish, Weblogic • Permite a configuração de “executable JARs” • Podem ser configurados como serviços UNIX / Linux / Windows • UNIX/Linux services via init.d ou systemd • Windows services via winsw • Compatível com diferentes PaaS Cloud providers • Cloud Foundry, Heroku, OpenShift, AWS, Boxfuse, Google App Engine
  11. 11. Spring Boot (deployment) • Configuração para deployment via WAR em um container @SpringBootApplication public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } <project> <!-- ... --> <packaging>war</packaging> <!-- ... --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <!-- ... --> </dependencies> </project>
  12. 12. Spring Boot (deployment) • Configurando JAR executável no ambiente UNIX • Fedora / CentOS • sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp • service myapp start • Debian • update-rc.d myapp defaults <priority> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin>
  13. 13. Spring Boot (containers) Container Servlet Version Java Version Tomcat 8 3.1 Java 7+ Tomcat 7 3.0 Java 6+ Jetty 9.3 3.1 Java 8+ Jetty 9.2 3.1 Java 7+ Jetty 8 3.0 Java 6+ Undertow 1.3 3.1 Java 7+
  14. 14. Spring Boot (containers) <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <!-- OR --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
  15. 15. Laboratório 1 (boot-lab01) • Criando uma primeira aplicação com Spring Boot
  16. 16. Spring Boot (starters) • spring-boot-starter-web • spring-boot-starter-data-jpa • spring-boot-starter-data-rest • spring-boot-starter-jdbc • spring-boot-starter-websocket • spring-boot-starter-cache • spring-boot-starter-batch • spring-boot-starter-hateoas • spring-boot-starter-test • spring-boot-starter-integration • spring-boot-starter-validation • spring-boot-starter-mobile…
  17. 17. Spring Boot (auto-configuration) • AopAutoConfiguration • JpaRepositoriesAutoConfiguration • HibernateJpaAutoConfiguration • DataSourceAutoConfiguration • JmsTemplateAutoConfiguration • MongoAutoConfiguration • RedisAutoConfiguration • WebMvcAutoConfiguration • SecurityAutoConfiguration • …
  18. 18. Spring Boot (configuration) • Permite que você externalize as configurações da aplicação em arquivos properties, YAML, variáveis de ambiente, argumentos de linha de comando • Oferece uma lista bastante extensa de possíveis configurações • https://docs.spring.io/spring-boot/docs/current/reference/html/common-application- properties.html • Propriedades podem ser injetadas utilizando @Value ou acessadas via Spring Environment • Pode ser configurado também via @ConfigurationProperties • Podem ser ativadas e alternadas utilizando profiles de aplicação • application-{profile}.properties • Suporta o uso de expressões e oferece recursos como • Valores randômicos: ${random.long} • Referências internas: ${anotherproperty.value} • Variáveis de ambiente: ${VARIABLE}
  19. 19. Spring Boot (configuration) • YAML file • Properties file spring: application: name: cruncher datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost/test server: port: 9000 my: servers: - dev.bar.com - foo.bar.com spring.application.name=cruncher spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost/test server.port=9000 my.servers[0]=dev.bar.com my.servers[1]=foo.bar.com
  20. 20. Spring Boot (configuration) email=test@email.com thread-pool=12 @Component public class GlobalProperties { @Value("${thread-pool}") private int threadPool; @Value("${email}") private String email; @Autowired private Environment env; public String getEmail() { return env.getProperty("email"); } public int getThreadPool() { return env.getProperty("thread-pool"); } //getters and setters } • Exemplo utilizando @Value e Spring Environment application.properties
  21. 21. Spring Boot (configuration) @ConfigurationProperties( locations = "classpath:mail.properties", prefix = "mail") public class MailProperties { public static class Smtp { private boolean auth; private boolean starttlsEnable; // ... getters and setters } @NotBlank private String host; private int port; private String from; private String username; private String password; @NotNull private Smtp smtp; // ... getters and setters } mail.host=localhost mail.port=25 mail.smtp.auth=false mail.smtp.starttls-enable=false mail.from=me@localhost mail.username= mail.password= • Exemplo utilizando @ConfigurationProperties mail.properties
  22. 22. Spring Boot (profiles) • Fornece uma maneira de segmentar a configuração da aplicação por diferentes ambientes de execução • Qualquer @Component, @Configuration por ser anotado com @Profile • Para sinalizar um profile, basta utilizar: • Propriedade: spring.profiles.active=dev • CLI: --spring.profiles.active=dev • JVM: -Dspring.profiles.active=dev • Java: SpringApplication.setAdditionalProfiles(…) • Podem ser sobrescritos e/ou combinados utilizando uma regra de maior prioridade • spring.profiles.active=default,dev
  23. 23. Spring Boot (profiles) @Configuration @Profile("production") public class ProductionConfiguration { // ... } server: port: 9000 --- spring: profiles: development server: port: 9001 --- spring: profiles: production server: port: 0 @Configuration @Profile(“!production") public class NonProductionConfiguration { // ... } • Exemplo de utilização @Profile application.yml
  24. 24. Spring Boot (logging) • Implementação interna via Commons Logging • Por padrão utiliza Logback, mas suporta outros providers, como Java Util Logging e Log4J • Pode habilitar o level por execução • java -jar myapp.jar --debug • Formato padrão do log utilizado • Date and Time, Log Level, Process ID, Thread Name, Logger Name, Log Message 2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52 2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat]. [localhost].[/] : Initializing Spring embedded WebApplicationContext 2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms 2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
  25. 25. Spring Boot (logging) • Configuração customizada de níveis de log logging.level.root=WARN logging.level.org.springframework.web=DEBUG logging.level.org.hibernate=ERROR application.properties @Component public class Service { private final Logger logger = LoggerFactory.getLogger(this.getClass()); public void doSomething(String param) { try { logger.debug("Trying to do something using param {}", param); // process something } catch (Exception ex) { logger.error("Error to do something", ex); } } // other methods }
  26. 26. Spring Boot (actuator) • Ajuda gerenciar e monitorar as aplicações em produção • Acessível via HTTP, JMX ou remote shell • Fornece uma lista de endpoints para gerenciar Spring Boot app • Publica as propriedades e Spring Beans em formato JSON view <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
  27. 27. Spring Boot (actuator) • /info • Informação da aplicação • /health • Status da aplicação (UP/DOWN) • /beans • Lista de Spring Beans na aplicação • /env • Propriedades externas configuradas • /dump • Realiza um thread dump • /metrics • Métricas da aplicação corrente (número de requests, consumo memória, etc) • /mappings • Lista de todos os @RequestMapping’s da aplicação • /trace • Demonstra o trace dos últimos 100 requests • /autoconfig • Relatório de auto-configuração da aplicação • /shutdown • Realiza o shutdown da aplicação (não ativado por padrão)
  28. 28. Spring Boot (actuator) • Customizando health indicator @Component public class MyHealthIndicator implements HealthIndicator { @Override public Health health() { int errorCode = check(); // perform some specific health check if (errorCode != 0) { return Health.down().withDetail( "Error Code", errorCode).build(); } return Health.up().build(); } }
  29. 29. Spring Boot (dev tools) • Conjunto de ferramentas para facilitar o processo de desenvolvimento e deployment das apps • Principais funcionalidades • Property defaults • Automatic restart • Live reload • Global settings • Remote applications <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies>
  30. 30. Laboratório 2 (boot-lab02) • Explorando os recursos do Spring Boot
  31. 31. Spring Boot (testing) • Fornece diversos utilitários e implementações para implementação de testes unitários • Habilitado via spring-boot-starter-test • Módulos spring-boot-test (core), spring-boot-test- autoconfigure (auto-configuração) • Dependências • JUnit - Biblioteca de unit testing em Java • Spring Test - Utilitários para testes integração com Spring Boot • AssertJ - Biblioteca para fluent assertion • Hamcrest - Biblioteca para matcher objects (constraints / predicates) • Mockito - Mock objects framework • JSONassert - Biblioteca para JSON assertion • JsonPath - Biblioteca para XPath para JOSN
  32. 32. Spring Boot (testing) • Habilitado utilizando a anotação @SpringBootTest e via JUnit SpringRunner • Simula um webEnvironment que pode configurado como: • MOCK, RANDON_PORT, DEFINED_PORT, NONE @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @Import(MyTestsConfiguration.class) public class MyTests { @Test public void exampleTest() { ... } }
  33. 33. Spring Boot (testing) • Suporta a utilização de Mock objects via Mockito • Basta injetar objetos com uso da anotação @MockBean @RunWith(SpringRunner.class) @SpringBootTest public class MyTests { @MockBean private RemoteService remoteService; @Autowired private Reverser reverser; @Test public void exampleTest() { // RemoteService has been injected into the reverser bean given(this.remoteService.someCall()).willReturn("mock"); String reverse = reverser.reverseSomeCall(); assertThat(reverse).isEqualTo("kcom"); } }
  34. 34. Spring Boot (testing) • Oferece uma boa alternativa para testar conteúdo JSON por meio da anotação @JsonTest • Utiliza por padrão Jackson como parser, mas pode ser configurado para suportar Gson @RunWith(SpringRunner.class) @JsonTest public class MyJsonTests { @Autowired private JacksonTester<VehicleDetails> json; @Test public void testSerialize() throws Exception { VehicleDetails details = new VehicleDetails("Honda", "Civic"); // Assert against a `.json` file in the same package as the test assertThat(this.json.write(details)).isEqualToJson("expected.json"); // Or use JSON path based assertions assertThat(this.json.write(details)).hasJsonPathStringValue("@.make"); assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make") .isEqualTo("Honda"); } }
  35. 35. Laboratório 3 (boot-lab03) • Testando uma aplicação Spring Boot
  36. 36. Spring MVC • Web MVC action framework suportado pelo Spring Boot • Utilizado para implementação de aplicações Web content e também para REST APIs
  37. 37. Spring MVC • DispatcherServlet • Implementação do design pattern FrontController • Recebe todas as requisições e delega para os controllers respectivos • Utiliza ViewResolver para resolver qual a tela deverá ser retornada
  38. 38. Spring MVC (controller) • @Controller é o componente principal do Spring MVC • Define os server endpoints da aplicação Web • Aplicações REST pode ser utilizado @RestController @Controller public class GreetingController { @RequestMapping("/greeting") public String greeting( @RequestParam(required=false) String name, Model model) { model.addAttribute("name", name); return "greeting"; } }
  39. 39. Spring MVC (annotations) • @RequestMapping • Define os server endpoints à serem processados pela aplicação @Controller @RequestMapping("/appointments") public class AppointmentsController { @Autowired AppointmentBook appointmentBook; @RequestMapping(method = RequestMethod.GET) public Map<String, Appointment> get() { return appointmentBook.getAppointmentsForToday(); } @RequestMapping(method = RequestMethod.POST) public String add(@Valid AppointmentForm appointment, BindingResult result) { if (result.hasErrors()) { return "appointments/new"; } appointmentBook.addAppointment(appointment); return "redirect:/appointments"; } }
  40. 40. Spring MVC (annotations) • RequestMapping possui variações para melhor suportar as operações HTTP • @GetMapping, @PostMapping, @PutMapping @DeleteMapping, @PatchMapping @Controller @RequestMapping("/appointments") public class AppointmentsController { @Autowired AppointmentBook appointmentBook; @GetMapping public Map<String, Appointment> get() { return appointmentBook.getAppointmentsForToday(); } @PostMapping public String add(@Valid AppointmentForm appointment, BindingResult result) { if (result.hasErrors()) { return "appointments/new"; } appointmentBook.addAppointment(appointment); return "redirect:/appointments"; } }
  41. 41. Spring MVC (annotations) • @RequestParam • Recuperação de um parâmetro da requisição • @RequestBody • Define o acesso para o conteúdo do corpo da requisição (ex: JSON, XML, etc) • @ResponseBody • Define o retorno do conteúdo como corpo da resposta (ex; JSON, XML, etc) • @PathVariable • Recuperação de um atributo como parte do path da requisição • @ModelAttribute • Recuperação de um grupo de atributos submetidos na requisição • @SessionAttribute • Referência e/ou recuperação de um atributo da sessão (HttpSession) • @RequestAttribute • Referência e/ou recuperação de um atributo da requisição • @CookieValue • Recuperação de um cookie na requisição • @RequestHeader • Recuperação de um cabeçalho da requisição
  42. 42. Spring MVC (annotations) @Controller public class PetController { @PostMapping(path = "/pets", consumes=“application/json”, produces="application/json") @ResponseBody public Pet addPet(@RequestBody Pet pet, Model model) {...} @GetMapping(path = "/pets/setup") public String setupForm(@RequestParam("petId") int petId, ModelMap model) {} @PostMapping(path = "/owners/{ownerId}/pets/{petId}/edit") public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) {...} @GetMapping(path = "/display/cookie") public void displayCookie(@CookieValue("JSESSIONID") String cookie) {...} @GetMapping(path = "/display/header") public void displayHeader(@RequestHeader("Accept-Encoding") String encoding, @RequestHeader("Keep-Alive") long keepAlive) {...} @GetMapping(path = "/user") public String handleUser(@SessionAttribute User user) {...} } • Exemplos de utilização das anotações
  43. 43. Spring MVC (error handling) • Spring Boot oferece /error endpoint como página global de erros, para tratar erros de maneira geral • Oferece implementação de tratadores de execução customizados via @ExceptionHandler • Pode ser utilizado como método do @Controller ou por via @ControllerAdvice @Controller public class SimpleController { // @RequestMapping methods omitted ... @ExceptionHandler(IOException.class) @ResponseBody public ResponseEntity<String> handleIOException(IOException ex) { // prepare responseEntity return responseEntity; } }
  44. 44. Spring MVC (error handling) • Páginas de erros podem ser customizadas de maneira estática ou utilizando templates src/ +- main/ +- java/ | + <source code> +- resources/ +- public/ +- error/ | +- 404.html +- <other public assets> src/ +- main/ +- java/ | + <source code> +- resources/ +- templates/ +- error/ | +- 5xx.ftl +- <other templates>
  45. 45. Spring MVC (static content) • Por padrão Spring Boot irá buscar conteúdo estático nos seguintes diretórios • /static, /public, /resources ou /META-INF/resources • A partir do diretório /src/main/resources (Maven) • Não utilize o diretório /src/main/webapp • Funciona apenas para empacotamento WAR • Fornece LiveReload para browser refresh automático • Apenas quando DevTools está habilitado no Spring Boot • Suporta a utilização de WebJars • http://www.webjars.org/
  46. 46. Spring MVC (view templates) • Suporta uma variedade de ferramentas de view templates para processamento conteúdo Web dinâmico • FreeMaker • Groovy • Thymeleaf • Mustache • JSP • Os templates serão buscados a partir do diretório template na aplicação Spring Boot • /src/main/resources/templates
  47. 47. Spring MVC (CORS) • Pode ser customizado via configuração customizada @Configuration public class MyConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://domain2.com") .allowedMethods("PUT", "DELETE") .allowedHeaders("header1", "header2") .exposedHeaders("header1", "header2") .allowCredentials(false).maxAge(3600); } }; } }
  48. 48. Spring MVC (CORS) • Fornece a anotação @CrossOrigin para ser utilizada diretamente nos controllers @Controller @RequestMapping("/account") public class AccountController { @CrossOrigin @RequestMapping("/{id}") public Account retrieve(@PathVariable Long id) { // ... } @RequestMapping(method = RequestMethod.DELETE, path = "/{id}") public void remove(@PathVariable Long id) { // ... } } @CrossOrigin(origins = "http://domain2.com", maxAge = 3600) @Controller @RequestMapping("/account") public class AccountController {...}
  49. 49. Spring MVC (testing) • Oferece uma customização especial para testes utilizando a anotação @WebMvcTest • Possui integração com frameworks de teste funcional (HtmlUnit, Selenium) @RunWith(SpringRunner.class) @WebMvcTest(UserVehicleController.class) public class MyControllerTests { @Autowired MockMvc mvc; @MockBean UserVehicleService userVehicleService; @Test public void testExample() throws Exception { given(this.userVehicleService.getVehicleDetails("sboot")) .willReturn(new VehicleDetails("Honda", “Civic")); this.mvc.perform(get("/sboot/vehicle") .accept(MediaType.TEXT_PLAIN)) .andExpect(status().isOk()) .andExpect(content().string("Honda Civic")); } }
  50. 50. Laboratório 4 (boot-lab04) • Desenvolvimento Web com Spring MVC
  51. 51. Web Services APIs
  52. 52. Arquitetura REST
  53. 53. Arquitetura REST • ︎Protocolo cliente/servidor sem estado (HTTP) • ︎Operações bem definidas • GET • POST • PUT • DELETE, etc • ︎Sintaxe universal para identificação de recursos (URL) • ︎Transferência de informações em formato padrão (XML, HTML, JSON)
  54. 54. Richardson Maturity Model
  55. 55. RESTful Services
  56. 56. Spring REST • @RestController • Define uma anotação específica para controllers REST @RestController @RequestMapping(value="/users") public class MyRestController { @RequestMapping(value="/{user}", method=RequestMethod.GET) public User getUser(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}/customers", method=RequestMethod.GET) List<Customer> getUserCustomers(@PathVariable Long user) { // ... } @RequestMapping(value="/{user}", method=RequestMethod.DELETE) public User deleteUser(@PathVariable Long user) { // ... } }
  57. 57. Spring REST • Fornece flexibilidade para configuração na negociação de conteúdo @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false). favorParameter(true). parameterName("mediaType"). ignoreAcceptHeader(true). useJaf(false). defaultContentType(MediaType.APPLICATION_JSON). mediaType("xml", MediaType.APPLICATION_XML). mediaType("json", MediaType.APPLICATION_JSON); } } curl http://localhost:8080/spring-mvc-java/employee/10?mediaType=[json/xml] <employee> <contactNumber>999-999-9999</contactNumber> <id>10</id> <name>Test Employee</name> </employee> { "id": 10, "name": "Test Employee", "contactNumber": "999-999-9999" }
  58. 58. Spring REST • Unit testing é implementado utilizando @WebMvcTest @RunWith(SpringRunner.class) @WebMvcTest(GreentingController.class) public class GreetingControllerTests { @Autowired private MockMvc mvc; @Test public void givenGreetURIWithQueryParameter() { this.mockMvc.perform(get("/greetWithQueryVariable") .param("name", "John Doe")).andDo(print()).andExpect(status().isOk()) .andExpect(content().contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.message").value("Hello World John Doe!!!")); } @Test public void givenGreetURIWithPost() { this.mockMvc.perform(post("/greetWithPost")).andDo(print()) .andExpect(status().isOk()).andExpect(content() .contentType("application/json;charset=UTF-8")) .andExpect(jsonPath("$.message").value("Hello World!!!")); } }
  59. 59. Spring REST • É possível utilizar especificação JAX-RS na implementação dos REST endpoints • Basta incluir a dependência spring-boot-starter-jersey • Implementado via Jersey 2.x • Para cada REST endpoint é necessário defini-los como um bean gerenciado pelo Spring • Configurado com a anotação @Component @Component public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(Endpoint.class); } } @Component @Path("/hello") public class Endpoint { @GET public String message() { return "Hello"; } }
  60. 60. HATEOAS • Hypermedia As The Engine of Application State • Descrevem o estado atual da aplicação e como navegar para o próximo estado
  61. 61. Hypermedia
  62. 62. Spring HATEOAS • Adiciona suporte HATEOAS para REST endpoints • Basta incluir a dependência spring-boot-starter-hateoas • Definida pelos componentes Links e Resources Link link = new Link("http://localhost:8080/something"); assertThat(link.getHref(), is("http://localhost:8080/something")); assertThat(link.getRel(), is(Link.SELF)); class PersonResource extends ResourceSupport { String firstname; String lastname; } PersonResource resource = new PersonResource(); resource.firstname = "Dave"; resource.lastname = "Matthews"; resource.add(new Link("http://myhost/people")); { firstname : "Dave", lastname : "Matthews", links : [ { rel : "self", href : "http://myhost/people" } ] }
  63. 63. Spring HATEOAS public class Greeting { String name; // getters and setters } public class GreetingResource extends Resource<Greeting> { public GreetingResource(Greeting greeting, Link... links) { super(greeting, links); } } public class GreetingResourceAssembler extends ResourceAssemblerSupport<Greeting, GreetingResource> { public GreetingResourceAssembler() { super(Greeting.class, GreetingResource.class); } @Override public GreetingResource toResource(Aluno aluno) { return new GreetingResource(aluno, linkTo(methodOn(GreetingController.class).get(greeting.getName())).withSelfRel()); } @Override protected GreetingResource instantiateResource(Greeting aluno) { return new GreetingResource(greeting); } }
  64. 64. Spring HATEOAS @RestController public class GreetingController { GreetingResourceAssembler assembler = new GreetingResourceAssembler(); @RequestMapping("/greeting") public ResponseEntity<GreetingResource> greeting( @RequestParam(value = "name", required = false) String name) { Greeting greeting = new Greeting("Hello, " + name); return new ResponseEntity<>(assembler.toResource(greeting), HttpStatus.OK); } } { "content":"Hello, User!", "_links":{ "self":{ "href":"http://localhost:8080/greeting?name=User" } } } curl http://localhost:8080/greeting?name=User
  65. 65. Swagger • Alternativa para documentação da REST API • Possui ótima integração com Spring Boot • SpringFox - https://springfox.github.io/springfox/ • Oferece uma ferramenta para navegação Web • Swagger UI - http://swagger.io/swagger-ui/ • Possui também uma ferramenta para modelagem da API • Swagger Editor - http://swagger.io/swagger-editor/
  66. 66. Swagger (spring boot) • Basta adicionar as dependências Maven • springfox-swagger-ui e springfox-swagger2 • Habilitar suporte Swagger na aplicação via @EnableSwagger2 • Documentar os REST controllers utilizando anotações • @ApiOperation • Documentação de um REST endpoint • @ApiParam, @ApiImplicitParam • Documentação dos parâmetros do REST endpoint • @ApiResponse • Documentação da resposta do REST endpoint • @ApiModel, @ApiModelProperty • Documentação do modelo de dados de resposta do REST endpoint • @Authorization • Documentação do modelo de autorização do REST endpoint • @ResponseHeader • Documentação dos headers de resposta do REST endpoint
  67. 67. Swagger (spring boot) @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build(); } } <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.1</version> </dependency> • Exemplo de integração Swagger com Spring Boot
  68. 68. Swagger (spring boot) @RestController public class GreetingController { @ApiOperation(value = "getGreeting", nickname = "getGreeting") @RequestMapping(method = RequestMethod.GET, path="/greeting", produces = "application/json") @ApiImplicitParams({ @ApiImplicitParam(name = "name", value = "User's name", required = false, dataType = "string", paramType = "query") }) @ApiResponses(value = { @ApiResponse(code = 200, message = "Success", response = Greeting.class), @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 403, message = "Forbidden"), @ApiResponse(code = 404, message = "Not Found"), @ApiResponse(code = 500, message = "Failure")}) public Greeting greeting(@RequestParam(value="name") String name) { return new Greeting(new AtomicLong().incrementAndGet(), String.format("Hello, %s!", name)); } } • Exemplo de documentação utilizando as anotações Swagger
  69. 69. Swagger UI
  70. 70. Laboratório 5 (boot-lab05) • Implementando RESTful com Spring Boot
  71. 71. Spring Data • Abstração para implementação de repositórios de persistência de dados integrada ao Spring Boot • Suporta diferentes modelos de persistência • JDBC, JPA, MongoDB, LDAP, Redis, Gemfire, Cassandra • DynamoDB, Couchbase, Solr, Elasticsearch, Neo4j,… • Implementa ações de CRUD em repositórios abstratos • Fornece queries dinâmicas criadas a partir nomes de métodos dos repositórios • Oferece flexibilidade para customização de repositórios • Suporta configurações de auditoria
  72. 72. Spring Data
  73. 73. Spring Data
  74. 74. Spring Data public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> { <S extends T> S save(S entity); T findOne(ID primaryKey); Iterable<T> findAll(); Long count(); void delete(T entity); boolean exists(ID primaryKey); } • Definição dos repositórios abstratos public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable); } interface Repository<T, ID> extends Serializable> {}
  75. 75. Spring Data public interface UserRepository extends PagingAndSortingRepository<User, Long> { // other methods } • Utilização dos repositórios abstratos @Component public class SomeClient { @Autowired private UserRepository repository; public void doSomething() { PagingAndSortingRepository<User, Long> repository = // … get access to a bean Page<User> users = repository.findAll(new PageRequest(1, 20)); } }
  76. 76. Spring Data interface UserRepositoryCustom { public void someCustomMethod(User user); } interface UserRepository extends CrudJpaRepository<User, Long>, UserRepositoryCustom { // Declare query methods here } • Implementação de repositórios “customizados" class UserRepositoryImpl implements UserRepositoryCustom { public void someCustomMethod(User user) { // Your custom implementation } }
  77. 77. Spring Data • Mecanismo de geração de consultas dinâmicas • Definição por DSL • Via nome dos métodos • Suporta diferentes variações • ByProperty • ByPropertyAsc • ByPropertyDesc • ByProp1AndProp2 • ByProp1OrProp2 • ByPropertyContaining • …
  78. 78. Spring Data (queries) • Definição das consultas dinâmicas public interface PersonRepository extends Repository<User, Long> { List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // Enables the distinct flag for the query List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enabling ignoring case for an individual property List<Person> findByLastnameIgnoreCase(String lastname); // Enabling ignoring case for all suitable properties List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // Enabling static ORDER BY for a query List<Person> findByLastnameOrderByFirstnameAsc(String lastname); List<Person> findByLastnameOrderByFirstnameDesc(String lastname); }
  79. 79. Spring Data (queries) Logical keyword Keyword expressions AND And OR Or AFTER After, IsAfter BEFORE Before, IsBefore CONTAINING Containing, IsContaining, Contains BETWEEN Between, IsBetween ENDING_WITH EndingWith, IsEndingWith, EndsWith EXISTS Exists FALSE False, IsFalse GREATER_THAN GreaterThan, IsGreaterThan GREATER_THAN_EQUALS GreaterThanEqual, IsGreaterThanEqual IN In, IsIn IS Is, Equals, (or no keyword) IS_NOT_NULL NotNull, IsNotNull
  80. 80. Spring Data (queries) Logical keyword Keyword expressions IS_NULL Null, IsNull LESS_THAN LessThan, IsLessThan LESS_THAN_EQUAL LessThanEqual, IsLessThanEqual LIKE Like, IsLike NEAR Near, IsNear NOT Not, IsNot NOT_IN NotIn, IsNotIn NOT_LIKE NotLike, IsNotLike REGEX Regex, MatchesRegex, Matches STARTING_WITH StartingWith, IsStartingWith, StartsWith TRUE True, IsTrue WITHIN Within, IsWithin
  81. 81. Spring Data (queries) • Limitação nos resultados de consulta public interface PersonRepository extends Repository<User, Long> { User findFirstByOrderByLastnameAsc(); User findTopByOrderByAgeDesc(); Page<User> queryFirst10ByLastname(String lastname, Pageable pageable); Slice<User> findTop3ByLastname(String lastname, Pageable pageable); List<User> findFirst10ByLastname(String lastname, Sort sort); List<User> findTop10ByLastname(String lastname, Pageable pageable); }
  82. 82. Spring Data JPA • Oferece suporte à JPA • Basta adicionar a dependência • spring-boot-starter-data-jpa • Habilitar por padrão Hibernate como JPA provider • Oferece integração QueryDSL • Suporte à paginação, execução dinâmica de consultas, integração com repositórios customizados, etc
  83. 83. Spring Data JPA
  84. 84. Spring Data JPA public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { List<T> findAll(); List<T> findAll(Sort sort); List<T> findAllById(Iterable<ID> ids); <S extends T> List<S> saveAll(Iterable<S> entities); void flush(); <S extends T> S saveAndFlush(S entity); void deleteInBatch(Iterable<T> entities); void deleteAllInBatch(); T getOne(ID id); } • Definição do repositório JPA abstrato
  85. 85. Spring Data JPA @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name = "username") private String name; private String password; @OneToOne private Person person; // getters and setters } public interface UserRepository extends JpaRepository<User, Long> { User findByName(String name); List<User> findByNameContaining(String name); } • JPA Entity e repositório Spring Data JPA
  86. 86. Spring Data JPA Keyword Sample JPQL snippet And findByLastnameAndFirstnam e … where x.lastname = ?1 and x.firstname = ?2 Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2 Is,Equals findByFirstname … where x.firstname = ?1 Between findByStartDateBetween … where x.startDate between ?1 and ?2 LessThan findByAgeLessThan … where x.age < ?1 LessThanEqual findByAgeLessThanEqual … where x.age <= ?1 GreaterThan findByAgeGreaterThan … where x.age > ?1 GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1 After findByStartDateAfter … where x.startDate > ?1
  87. 87. Spring Data JPA @Entity @NamedQuery(name = "User.findByEmailAddress", query = "select u from User u where u.emailAddress = ?1") public class User { // Implementation } public interface UserRepository extends JpaRepository<User, Long> { List<User> findByLastname(String lastname); User findByEmailAddress(String emailAddress); } • Utilizando @NamedQuery's
  88. 88. Spring Data JPA public interface UserRepository extends JpaRepository<User, Long> { // JP-QL sample @Query("select u from User u where u.emailAddress = ?1") User findByEmailAddress(String emailAddress); // JP-QL with named parameters @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname") User findByLastnameOrFirstname(@Param("lastname") String lastname, @Param("firstname") String firstname); // Native SQL query @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true) User findByEmailAddress(String emailAddress) // Native SQL query for paging @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1", countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1", nativeQuery = true) Page<User> findByLastname(String lastname, Pageable pageable); } • Utilizando @Query’s customizadas
  89. 89. Spring Data JPA public interface UserRepository extends JpaRepository<User, Long> { // JP-QL sample with ordering @Query("select u from User u where u.lastname like ?1%") List<User> findByAndSort(String lastname, Sort sort); // Delete query sample @Modifying @Query("delete from User u where user.role.id = ?1") void deleteInBulkByRoleId(long roleId); // Update query sample @Modifying @Query("update User u set u.firstname = ?1 where u.lastname = ?2") int setFixedFirstnameFor(String firstname, String lastname); // Using query hints @QueryHints(value = { @QueryHint(name = "name", value = "value")}, forCounting = false) Page<User> findByLastname(String lastname, Pageable pageable); } • Utilizando @Query’s customizadas
  90. 90. Spring Data JPA • Executando Stored Procedures /; DROP procedure IF EXISTS plus1inout /; CREATE procedure plus1inout (IN arg int, OUT res int) BEGIN ATOMIC set res = arg + 1; END /; @Entity @NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = { @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class), @StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) }) public class User {} public interface UserRepository extends JpaRepository<User, Long> { @Procedure("plus1inout") Integer explicitlyNamedPlus1inout(Integer arg); @Procedure(name = "User.plus1IO") Integer entityAnnotatedCustomNamedProcedurePlus1IO(@Param("arg") Integer arg); }
  91. 91. Spring Data JPA (specification) public class CustomerSpecs { public static Specification<Customer> isLongTermCustomer() { return new Specification<Customer>() { public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder builder) { LocalDate date = new LocalDate().minusYears(2); return builder.lessThan(root.get(_Customer.createdAt), date); } }; } } public interface CustomerRepository extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {...} public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder); } List<Customer> customers = customerRepository.findAll(isLongTermCustomer());
  92. 92. Spring Data JPA (query by example) public interface QueryByExampleExecutor<T> { <S extends T> S findOne(Example<S> example); <S extends T> Iterable<S> findAll(Example<S> example); // … more functionality omitted. } public class PersonService { @Autowired PersonRepository personRepository; public List<Person> findPeople(Person probe) { return personRepository.findAll(Example.of(probe)); } } public interface PersonRepository extends JpaRepository<Person, String> { … } Person person = new Person(); person.setFirstname("Dave"); ExampleMatcher matcher = ExampleMatcher.matching() .withIgnorePaths("lastname") .withIncludeNullValues() .withStringMatcherEnding(); Example<Person> example = Example.of(person, matcher);
  93. 93. Spring Data JPA (transactional) public interface UserRepository extends JpaRepository<User, Long> { // Transaction support @Transactional(timeout = 10) public List<User> findAll(); } @Service class UserManagementImpl implements UserManagement { @Autowired UserRepository userRepository; @Autowired RoleRepository roleRepository; @Transactional public void addRoleToAllUsers(String roleName) { // Step 1 Role role = roleRepository.findByName(roleName); // Step 2 for (User user : userRepository.findAll()) { user.addRole(role); userRepository.save(user); } } • Suporte transacional
  94. 94. Spring Data JPA (auditing) class Customer { @CreatedBy private User user; @CreatedDate private DateTime createdDate; // … further properties omitted } • Controle de auditoria class SpringSecurityAuditorAware implements AuditorAware<User> { public User getCurrentAuditor() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return null; } return ((MyUserDetails) authentication.getPrincipal()).getUser(); } } @Configuration @EnableJpaAuditing class Config { @Bean public AuditorAware<AuditableUser> auditorProvider() { return new AuditorAwareImpl(); } }
  95. 95. Spring Data JPA (testing) @RunWith(SpringRunner.class) @DataJpaTest public class UserRepositoryTests { @Autowired TestEntityManager entityManager; @Autowired UserRepository repository; @Test public void findByUsernameShouldReturnUser() { this.entityManager.persist(new User("sboot", "123")); User user = this.repository.findByUsername("sboot"); assertThat(user.getUsername()).isEqualTo("sboot"); assertThat(user.getVin()).isEqualTo("123"); } } • Unit testing com @DataJpaTest e TestEntityManager
  96. 96. Project Lombok • Oferece anotações para substituir “boilerplate code” nos beans da aplicação • Fornece geração automática à diversas implementações • Getters/setters, Constructors, Equals/hashcode • ToString, Builder’s, Immutable classes, Synchronized,… • Implementação por meio de anotações • @Getter, @Setter, @EqualsAndHashCode, @ToString • @NoArgsConstructor, @RequiredArgsConstructor • @AllArgsContructor, @Data, @Builder, @Log • @Synchronized, @Value, @NonNull, @Cleanup
  97. 97. Project Lombok • Basta adicionar a dependência no projeto • Implementar os beans utilizando as anotações <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.16</version> </dependency> @Data @Builder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode @ToString public class User implements Serializable { Long id; String name; String password; }
  98. 98. Spring Boot (datasources) • Oferece suporte à diferentes RDBMS • MySQL, PostgreSQL, Oracle, SQLServer, H2, … • É necessário configurá-los via spring.datasource.* • Suporta diferentes tipos de definição para data sources • Hikari, Tomcat, C3P0, DBCP2, JNDI spring.datasource.url=jdbc:mysql://localhost/test spring.datasource.username=dbuser spring.datasource.password=dbpass spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.hikari.maximum-pool-size=5 spring.datasource.hikari.connection-timeout=10
  99. 99. Spring Boot (H2) • Embedded in-memory RDBMS • Rápido, opensource e suporta 100% JDBC API • Small footprint (cerca 1.5 MB de tamanho) • Pode ser instalado como server, e persistência em arquivo • Ideal para utilização em testes de integração • Oferece uma aplicação Web para administração • Para habilitá-lo, basta adicionar a dependência <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <scope>runtime</scope> </dependency>
  100. 100. Spring Boot (H2) • Para habilitar no Spring Boot, basta adicionar a dependência e habilitar interface Web, se desejado • spring.h2.console.enabled = true • http://boot/h2-console
  101. 101. Laboratório 6 (boot-lab06) • Persistindo dados com Spring Data JPA
  102. 102. MongoDB • NoSQL database orientado à documentos • Persistência de dados no formato JSON • Armazenamento em formato BSON (binary JSON) • Suporte à full indexação, auto sharding, map reduce, replicação e tolerância à falhas db.createCollection('contato') db.contato.insert({ name: 'Rodrigo', email: 'rodrigo@email.com', mensagem: 'Inserindo dados no MongoDB' }) db.contato.find() db.contato.update({name: 'Rodrigo'}, {$set: {email: 'rodrigo@new-email.com'}}) db.contato.remove({name: 'Rodrigo'}) db.contato.drop() db.dropDatabase()
  103. 103. Spring Data MongoDB • Suporte à persistência dados no MongoDB via Spring • Basta adicionar a dependência no Spring Boot • spring-boot-starter-data-mongodb • Oferece helper classes para integração com MongoDB • MongoTemplate, MongoOperations • Anotações para mapeamento de entidades • @Id, @Document, @DBRef, @Indexed, • @CompoundIndex, @GeoSpatialIndexed, @Language • @TextIndexed, @Transient, @Value, @Field spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345/test spring.data.mongodb.host=mongoserver spring.data.mongodb.port=27017
  104. 104. Spring Data MongoDB • Definição de repositório abstrato MongoRepository public interface MongoRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { @Override <S extends T> List<S> save(Iterable<S> entites); @Override List<T> findAll(); @Override List<T> findAll(Sort sort); <S extends T> S insert(S entity); <S extends T> List<S> insert(Iterable<S> entities); @Override <S extends T> List<S> findAll(Example<S> example); @Override <S extends T> List<S> findAll(Example<S> example, Sort sort); }
  105. 105. Spring Data MongoDB @Document public class Person { @Id private String id; @Indexed private Integer ssn; private String firstName; @Indexed private String lastName; // getters and setters } public interface PersonRepository extends MongoRepository<Person, String> { List<Person> findByLastname(String lastname); Page<Person> findByFirstname(String firstname, Pageable pageable); Person findByShippingAddresses(Address address); Stream<Person> findAllBy(); } @Service public class PersonService { @Autowired PersonRepository repository; public void doSomething() { Page<Person> persons = repository.findAll( new PageRequest(1, 20)); // do something } }
  106. 106. Spring Data MongoDB Keyword Sample Logical result After findByBirthdateAfter(Date date) {"birthdate" : {"$gt" : date}} GreaterThan findByAgeGreaterThan(int age) {"age" : {"$gt" : age}} GreaterThanEqual findByAgeGreaterThanEqual(int age) {"age" : {"$gte" : age}} Before findByBirthdateBefore(Date date) {"birthdate" : {"$lt" : date}} LessThan findByAgeLessThan(int age) {"age" : {"$lt" : age}} LessThanEqual findByAgeLessThanEqual(int age) {"age" : {"$lte" : age}} Between findByAgeBetween(int from, int to) {"age" : {"$gt" : from, "$lt" : In findByAgeIn(Collection ages) {"age" : {"$in" : [ages… ]}} NotIn findByAgeNotIn(Collection ages) {"age" : {"$nin" : [ages… ]}} IsNotNull, findByFirstnameNotNull() {"firstname" : {"$ne" : null}} IsNull, Null findByFirstnameNull() {"firstname" : null}
  107. 107. Spring Data MongoDB • Suporte à JSON based @Query’s public interface PersonRepository extends MongoRepository<Person, String> @Query("{ 'firstname' : ?0 }") List<Person> findByThePersonsFirstname(String firstname); @Query(value="{ 'firstname': ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}") List<Person> findByThePersonsFirstname(String firstname); @Query("{ 'lastname': ?#{[0]} }") List<Person> findByQueryWithExpression(String param0); @Query("{'id': ?#{ [0] ? {$exists :true} : [1] }}") List<Person> findByQueryWithExpressionAndNestedObject(boolean param0, String param1); }
  108. 108. Spring Data MongoDB • Exemplo utilizando MongoTemplate object public class DomainRepositoryImpl implements DomainRepositoryCustom { @Autowired MongoTemplate mongoTemplate; @Override public int updateDomain(String domain, boolean displayAds) { Query query = new Query(Criteria.where("domain").is(domain)); Update update = new Update(); update.set("displayAds", displayAds); WriteResult result = mongoTemplate.updateFirst(query, update, Domain.class); if(result!=null) return result.getN(); else return 0; } }
  109. 109. Laboratório 7 (boot-lab07) • Persistindo NoSQL com Spring Data MongoDB
  110. 110. Spring Data REST • Publica Spring Data Repo como RESTful API’s • Expõe operações CRUD, consultas dinâmicas, paginação, relacionamentos,… • Incrementa o suporte HATEOAS • HAL, ALPS, JSON Schema, URI templates, etc • Permite • Suporta • JPA, MongoDB, GemFire, Neo4j, Solr, Cassandra • Demais estão por vir
  111. 111. Spring Data REST
  112. 112. Spring Data REST $ curl “http://localhost:8080/persons/1”
  113. 113. Spring Data REST @CrossOrigin(origins = "http://domain2.com", methods = { RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE }, maxAge = 3600) @RepositoryRestResource(path = "people") interface PersonRepository extends CrudRepository<Person, Long> { @RestResource(path = "names") List<Person> findByName(String name); @RestResource(exported = false) Person findByEmail(String email); @Override @RestResource(exported = false) void delete(Person entity); } • Exemplo de customização dos REST endpoints
  114. 114. HAL "Convenção para definição de REST hypermedia"
  115. 115. HAL Browser • Utilitário para navegar nos REST endpoints gerados
  116. 116. Laboratório 8 (boot-lab08) • Expondo os repositórios com Spring Data REST
  117. 117. Spring Security • Solução de segurança para as aplicações Spring e/ou Java EE-based • Implementa os procedimentos autenticação e autorização • Suporta autenticação em diferentes tecnologias • HTTP BASIC, Digest, X.509, LDAP, Form-based, OpenID • CAS, HttpInvoker, JAAS, Kerberos… • Ótimo suporte aos protocolos OAuth2 e JWT • Configuração facilitada por meio de anotações • Oferece suporte à diferentes funcionalidades • Remember-me, Run-as, CSRF, CORS, Crypto, ACL
  118. 118. Spring Security • Basta adicionar a seguinte dependência no projeto • Por padrão será habilitado a segurança HTTP BASIC • Para acesso deve ser utilizando usuário user e a senha gerada dinamicamente • Caso queira customizar o usuário e senha, pode ser definido via properties <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> Using default security password: 12aa6b86-08a7-4894-b899-3b2ebb1de248 security.user.name=root security.user.password=t0ps3cr3t
  119. 119. Spring Security • É possível implementar uma tela de login customizada • src/main/resources/templates/login.html @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated() .and().formLogin().loginPage("/login").permitAll() .and().logout().permitAll(); } } <form th:action="@{/login}" method="post"> <div><label> User Name : <input type="text" name="username"/> </label></div> <div><label> Password: <input type="password" name="password"/> </label></div> <div><input type="submit" value="Sign In"/></div> </form>
  120. 120. Spring Security • Autenticação pode ser configurada globalmente (In Memory) • Ou pode ser configurada via JDBC datasource @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("barry").password("t0ps3cr3t").roles("USER"); } } @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired DataSource dataSource; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(dataSource) .withDefaultSchema() .withUser("barry").password("t0ps3cr3t").roles("USER"); } }
  121. 121. Spring Security • Autorização pode ser configurada globalmente • Ou pode ser customizada via anotações @Secured, @PreAuthorize @Configuration public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/foo/**") .authorizeRequests() .antMatchers("/foo/bar").hasRole("BAR") .antMatchers("/foo/spam").hasRole("SPAM") .anyRequest().isAuthenticated(); } } @SpringBootApplication @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) public class Application {...}
  122. 122. Spring Security • Exemplos de uso das anotações @Secured, @PreAuthorize public interface BankService { @Secured("IS_AUTHENTICATED_ANONYMOUSLY") public Account readAccount(Long id); @Secured("ROLE_TELLER") public Account post(Account account, double amount); @PreAuthorize("isAnonymous()") public Account readAccount(Long id); @PreAuthorize("hasAuthority('ROLE_TELLER')") public Account post(Account account, double amount); @PreAuthorize("hasRole('ADMIN') AND hasRole('ROLE_TELLER')") public void deleteAccount(Long id); }
  123. 123. Laboratório 9 (boot-lab09) • Habilitando segurança com Spring Boot
  124. 124. Spring Batch • Lightweight Batch framework para desenvolvimento de processos robustos com grande quantidade de dados • Não é um scheduler, mas pode ser integrado • Quartz, Spring Scheduler, Tivoli, CRON, Control-M • Oferece diversas funcionalidades • Logging/tracing, gerenciamento de transação, estatísticas, job restart, skip, particionamento, gestão de concorrência, gerenciamento de recursos (memória, cpu) • Forte integração com demais projetos Spring • Utilizado geralmente em use cases particulares • ETL, exportação/importação de dados, cálculos,…
  125. 125. Spring Batch • Basta adicionar a seguinte dependência no projeto • Para habilitar processamento batch na aplicação Spring Boot deve-ser utilizar @EnableBatchProcessing <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> @SpringBootApplication @EnableBatchProcessing public class SpringBatchApplication { public static void main(String[] args) { SpringApplication.run(SpringBatchApplication.class, args); } }
  126. 126. Spring Batch • Chunk vs. Tasklet • Implementam step dentro do job • Chunk • Encapsula padrão ETL • Single Reader, Processor e Writer • Executado por pedaços de dados (chunk) • Chunk output é escrito unitariamente • Tasklet • Promove a execução de um único e simples processo • Executado até o fim produzindo um código de retorno
  127. 127. Spring Batch Chunk Tasklet
  128. 128. Spring Batch • ItemReader • ItemWriter • ItemProcessor public interface ItemReader<T> { T read() throws Exception, UnexpectedInputException, ParseException; } public interface ItemWriter<T> { void write(List<? extends T> items) throws Exception; } public interface ItemProcessor<I, O> { O process(I item) throws Exception; }
  129. 129. Spring Batch • Exemplo de configuração do job na aplicação @Configuration @EnableBatchProcessing public class BatchConfig { @Autowired JobBuilderFactory jobBuilderFactory; @Autowired StepBuilderFactory stepBuilderFactory; @Bean public Job job() { return jobBuilderFactory.get("job") .incrementer(new RunIdIncrementer()) .flow(step1()).end().build(); } @Bean public Step step1() { return stepBuilderFactory.get("step1").chunk(1) .reader(new Reader()) .processor(new Processor()) .writer(new Writer()).build(); } }
  130. 130. Spring Batch • Exemplo de execução job na aplicação @RestController public class JobLauncherController { @Autowired JobLauncher jobLauncher; @Autowired Job job; @RequestMapping("/launchjob") public String handle() throws Exception { Logger logger = LoggerFactory.getLogger(this.getClass()); try { JobParameters jobParameters = new JobParametersBuilder() .addLong("time", System.currentTimeMillis()) .toJobParameters(); jobLauncher.run(job, jobParameters); } catch (Exception e) { logger.info(e.getMessage()); } return "Done"; } }
  131. 131. Spring Cache • Oferece uma abstração para implementação de cache de dados nas aplicações Spring • Suporta diferente cache providers • Generic, JCache, EhCache, Hazelcast, Infinitspan, Couchbase, Redis, Caffeine, Guava, Simple • Possui integração com Spring Data e JPA • Ativação simples e fácil nas aplicações Spring Boot • Basta adicionar a dependência spring-boot-starter-cache • Ativar o sistema de cache com a anotação @EnableCaching • Utilizar os objetos CacheManager e Cache • Utilizar a anotação @Cachable
  132. 132. Spring Cache • Exemplo de implementação de cache na aplicação @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } @Component public class SimpleBookRepository implements BookRepository { @Override @Cacheable("books") public Book getByIsbn(String isbn) { simulateSlowService(); return new Book(isbn, "Some book"); } }
  133. 133. Spring Messaging • Processamento mensagens assíncronas na aplicação Spring Boot • Suporta diferentes tipos de protocolos mensagens • JMS, AMQP, STOMP • Suporte também diferentes providers de mensagens • ActiveMQ, Artemis, RabbitMQ, Apache Kafka, … • Oferece anotações e propriedades customizadas para trabalhar com provedores de mensagens • @JmsListener, @RabbitListener, @KafkaListener • Basta adicionar a dependência desejada • spring-boot-starter-activemq • spring-boot-starter-amqp • spring-boot-starter-kafka
  134. 134. Spring Messaging @SpringBootApplication @EnableRabbit public class MessagingApplication { @Bean public Queue fooQueue() { return new Queue("foo"); } } @Service public class CustomService { @RabbitListener(queues = "foo") public void process(@Payload String foo) { System.out.println(new Date() + ": " + foo); } } public class Sender { @Autowired RabbitTemplate rabbitTemplate; public void send() { this.rabbitTemplate.convertAndSend("foo", "hello"); } } • Exemplo de consumo e envio de mensagens RabbitMQ
  135. 135. Spring Integration • Implementação de design patterns de integração (EIP) • Endpoint, Channel, Aggregator, Filter, Transformer, Bus,… • http://www.enterpriseintegrationpatterns.com/ • Oferece integração com diversos protocolos e sistemas • FTP, sFTP, Twitter, Web Services (SOAP/REST), MQTT • Feed, JMS, AMQP, Email, TCP/UDP, XMPP, WebSocket,… • Expões objetos via JMX para monitoramento • Para configurar, basta adicionar a dependência • spring-boot-starter-integration • Oferece anotações para facilitar a implementação • @MessagingGateway, @Gateway, @ServiceActivator, @MessageEndpoint, @InboundChannelAdapter, @OutboundChannelAdapter
  136. 136. Spring Integration @SpringBootApplication public class Application { @Bean @InboundChannelAdapter(value = "feedChannel", poller = @Poller(maxMessagesPerPoll = "100", fixedRate = "10000")) public MessageSource<SyndEntry> feedAdapter() throws MalformedURLException { return new FeedEntryMessageSource( new URL("http://feeds.abcnews.com/abcnews/topstories"), "feedAdapter"); } @MessageEndpoint public static class Endpoint { @ServiceActivator(inputChannel = "feedChannel") public void log(Message<SyndEntry> message) { SyndEntry payload = message.getPayload(); logger.info(payload.getPublishedDate() + " - " + payload.getTitle()); } } @Bean public MessageChannel feedChannel() { return new QueueChannel(500); } } • Exemplo de consumo de dados via feed RSS
  137. 137. Spring WebSockets • Fornece suporte ao protocolo WebSockets aos web containers auto-contidos • Tomcat, Jetty, Undertow • Suportado pelos protocolos STOMP e SockJS • http://stomp.github.io/stomp-specification-1.2.html • https://github.com/sockjs/sockjs-protocol • Integrado aos controllers Spring MVC • Para configurar na aplicação • Adicionar a configuração spring-boot-starter-websocket • Habilitar @EnableWebSocketMessageBroker
  138. 138. Spring WebSockets • Exemplo de configuração endpoint via WebSocket @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/gs-guide-websocket").withSockJS(); } } @Controller public class GreetingController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); // simulated delay return new Greeting("Hello, " + message.getName() + "!"); } }
  139. 139. Spring WebSockets • Exemplo de cliente WebSocket em Javascript function connect() { var socket = new SockJS('/gs-guide-websocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function (greeting) { showGreeting(JSON.parse(greeting.body).content); }); }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); }
  140. 140. Laboratório 10 (boot-lab10) • Explorando recursos adicionais no Spring Boot
  141. 141. Conclusões • Spring Boot fornece diversos utilitários e facilitadores para implementação com Microservices • Spring Data e Data REST são projetos que aceleram a implementação e exposição na camada de persistência como serviços REST • Spring Security tem um ótima infra-estrutura para lidar com requisitos de segurança em aplicações Web • Existem diversos outros projetos que podem ser incorporados no boot da aplicação Spring, como Batch, Cache, Messaging, Integration, WebSockets, etc • Enjoy it ;)
  142. 142. Revisão Nessa unidade você teve a oportunidade de compreender como: • Implementar a primeira aplicação utilizando Spring Boot • Compreender as funcionalidades adicionais do Spring Boot • Compreender como implementar serviços REST utilizando Spring MVC • Implementar persistência de dados utilizando Spring Data • Expor os repositórios como serviços utilizando Spring Data REST • Implementar segurança utilizando Spring Security • Explorar os demais projetos do ecossistema Spring
  143. 143. Referências • https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ • https://github.com/eugenp/tutorials/tree/master/spring-mvc-java • http://www.restapitutorial.com/httpstatuscodes.html • https://spring.io/guides/tutorials/bookmarks/ • http://docs.spring.io/spring-hateoas/docs/current/reference/html/ • http://docs.spring.io/spring-data/jpa/docs/current/reference/html/ • https://docs.spring.io/spring-data/rest/docs/current/reference/html/ • https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/ • https://spring.io/guides/gs/securing-web/ • https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-messaging.html • https://spring.io/guides/gs/messaging-rabbitmq/ • http://docs.spring.io/spring-integration/reference/html/index.html • https://spring.io/guides/gs/integration/ • http://docs.spring.io/spring-batch/reference/html/index.html • https://spring.io/guides/gs/batch-processing/ • https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html • https://spring.io/guides/gs/caching/ • https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html • https://spring.io/guides/gs/messaging-stomp-websocket/

×