O documento apresenta os tópicos a serem abordados em um workshop sobre microserviços utilizando Spring Boot, incluindo implementação de APIs RESTful, persistência de dados com Spring Data e segurança com Spring Security.
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. Agenda
• Spring Boot
• Spring MVC
• Spring REST
• Spring Data
• Spring Data REST
• Spring Security
• Demais projetos
• Batch, Cache, Messaging, Integration, WebSockets, …
6. 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
7. 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
9. 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>
10. 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
11. 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
12. 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>
13. 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>
19. 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}
21. 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
22. 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
23. 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
24. 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
25. 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:
[/*]
26. 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
}
27. 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>
28. 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)
29. 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();
}
}
30. 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>
32. 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
33. 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() {
...
}
}
34. 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");
}
}
35. 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");
}
}
37. 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
38. 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
39. 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";
}
}
40. 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";
}
}
41. 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";
}
}
42. 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
43. 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
44. 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;
}
}
45. 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>
46. 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/
47. 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
48. 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);
}
};
}
}
49. 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 {...}
50. 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"));
}
}
54. 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)
57. 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) {
// ...
}
}
58. 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"
}
59. 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!!!"));
}
}
60. 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";
}
}
61. HATEOAS
• Hypermedia As The Engine of Application State
• Descrevem o estado atual da aplicação e como navegar para
o próximo estado
63. 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" } ] }
64. 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);
}
}
65. 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
66. 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/
67. 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
68. 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
72. 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
75. 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> {}
76. 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));
}
}
77. 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
}
}
78. 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
• …
79. 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);
}
80. 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
81. 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
82. 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);
}
83. 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
85. 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
86. 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
87. 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
88. 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
89. 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
90. 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
91. 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);
}
92. 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());
93. 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);
94. 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
95. 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();
}
}
96. 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
97. 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
98. 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;
}
99. 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
100. 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>
101. 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
103. 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()
104. 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
105. 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);
}
106. 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
}
}
111. 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
118. 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
119. 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
120. 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>
121. 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");
}
}
122. 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 {...}
123. 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);
}
125. 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,…
126. 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);
}
}
127. 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
129. 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;
}
130. 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();
}
}
131. 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";
}
}
132. 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
133. 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");
}
}
134. 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
135. 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
136. 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
137. 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
138. 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
139. 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() + "!");
}
}
140. 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()}));
}
142. 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 ;)
143. 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