Começando com a magia do Spring Boot

No livro sobre Spring que escrevi para a Casa do Código e no SetupMyProject fiz a opção pelo uso normal das extensões do Spring. Para criar o projeto web, usei o Spring MVC no seu modo convencional configurando tudo que era necessário, assim como fiz para a parte da JPA, Spring Security etc. No fim acho realmente importante que as pessoas conheçam bem as tecnologias que usam, para terem um olhar crítico sobre a ferramenta e poderem achar os pontos de extensão necessários para os projetos do dia a dia.

Na época da escrita do livro, o time do Spring já tinha lançado uma outra extensão chamada Spring Boot, cujo objetivo era acelerar o processo de configuração da aplicação, estabelecendo configurações defaults baseadas nas experiências dos desenvolvedores do próprio Spring, assim como pelo feedback provido pelos usuários do framework. Optei por não usá-lo, justamente pelos motivos citados no primeiro parágrafo. Agora, com tudo mais sedimentado e com um conhecimento realmente bom do framework resolvi que era hora de começar a construir uma aplicação com o Spring Boot, já que, principalmente durante a escrita do livro, fui obrigado a navegar muito pelos internals do Spring e tudo mais. Peguei como exemplo a própria app do livro, ela possui regras boas o suficiente para me fazer passar por diversos problemas. O código inicial já está no github.

Então vamos começar! O primeiro passo, como não poderia ser diferente, é a criação do projeto. Você pode realizar este passo no próprio SetupMyProject. O zip vai vir com o mínimo configurado, mas é aí que você já vai perceber a diferença. Para conseguir subir o servidor e acessar a primeira rota, só precisamos de uma classe configurada no projeto.

	@SpringBootApplication
	@Controller
	public class CasadocodigoSpringbootApplication {

		@RequestMapping("/")
		@ResponseBody
		public String index(){
			return "funciona?";
		}

		public static void main(String[] args) {
			SpringApplication.run(CasadocodigoSpringbootApplication.class, args);
		}
	}

Aqui já temos um pouco de mágica. Você vai rodar sua aplicação web a partir de um bom e velho método main. A classe SpringApplication vai ler as configurações da classe passada como argumento e pronto, você tem a sua aplicação no ar. A outra parte da mágica acontece por conta da annotation @SpringBootApplication. Ela é um Sterotype do Spring Boot que já encapsula algumas outras annotations, como a @EnableAutoConfiguration. Essa última, por sua vez, carrega a AutoConfigurationPackages que é responsável por configurar os pacotes que devem ser escaneados, baseados na localização da sua classe.

Um outro ponto bem impressionante é o pom.xml criado, você vai perceber que ele possui pouquíssimas dependências! Vamos dar uma rápida olhada.

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.3.0.BUILD-SNAPSHOT</version>
	</parent>	

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

Perceba que você adiciona algumas dependências que eles chamam de starters. A grande sacada é fazer com esses artefatos já baixem tudo que você precisa. E aqui, eu preciso dizer que, pelo menos para mim, eles tomaram uma decisão bastante acertada. Ao invés de te dar a opção de escolher entre vários frameworks, servidores web, libs específicas e etc, eles tomaram algumas decisões e empurraram pra gente. Para a maioria dos projetos isso não muda e, se for preciso, você pode sobreescrever tudo que eles fizeram. A motivação deles foi a mesma que tivemos ao construir o SetupMyProject. Já estamos cheios de frameworks, precisamos é de uma maneira mais fácil de usá-los.

Por mais que já tenhamos o projeto configurado, provavelmente esse não é bem o modelo que vamos seguir. Os nossos controllers não vão ser declarados dentro da mesma classe de configuração. O normal é criar uma outra classe que representa este seu controller.

        @Controller
	@Transactional
	@RequestMapping("/produtos")
	public class ProductsController {

		@Autowired
		private ProductDAO products;
		@Autowired
		private FileSaver fileSaver;
		@Autowired
		private ServletContext ctx;
		@Autowired
		private InternalResourceViewResolver resolver;

		@RequestMapping(method=RequestMethod.GET)
		@Cacheable(value="lastProducts")
		public ModelAndView list() throws ServletException, IOException{
			System.out.println("ola");
			ModelAndView modelAndView = new ModelAndView("products/list");
			modelAndView.addObject("products", products.findAll());
			return modelAndView;
		}

		...

	}

E agora é só pedir para escanear o pacote… Opa, não precisa mais! Como eu criei esse classe em um pacote abaixo do pacote da classe de configuração, todas as classes já vão ser escaneadas de maneira automática. Agora é necessário configurar o acesso a JPA e, nesse momento, nossos corações vão ficar felizes novamente. O nosso único trabalho é adicionar um starter no pom.xml. 

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
	</dependency>

Quase tudo que você acha que deveria fazer para configurar o acesso ao banco com a JPA, vai ser feito automagicamente. Não será necessário configurar persistence.xml, EntityManagerFactory, EntityManager, PlatformTransactionManager nem nada, tudo vai ser feito pra você. A única coisa que você precisa entregar a ele é o DataSource com os  dados de acesso ao banco. Podemos criar um método com essa configuração na própria classe que contém nosso main. 

@SpringBootApplication
	public class CasadocodigoSpringbootApplication {
		@Bean
		public DataSource dataSource(Environment environment) {
			DriverManagerDataSource dataSource = new DriverManagerDataSource();
			dataSource.setDriverClassName("com.mysql.jdbc.Driver");
			dataSource.setUrl("jdbc:mysql://localhost:3306/casadocodigo");
			dataSource.setUsername("root");
			dataSource.setPassword("");
			return dataSource;
		}

		public static void main(String[] args) {
			SpringApplication.run(CasadocodigoSpringbootApplication.class, args);
		}
	}

Além disso, ele também já inclui as dependências para a Spring Data JPA, para facilitar a criação dos seus DAOs. Para completar essa primeira parte da migração do projeto, foi necessário fazer uma pequena configuração extra para os jsps. O Spring Boot sugere que você use outra tecnologia de view, mas como o jsp era a utilizada no projeto do livro, eu resolvi ir com ela mesmo. Como o tomcat está sendo executado de forma embedded, é necessário que adicionemos uma nova dependência no pom, que é a do compilador de jsps para este tipo de cenário.

	<dependency>
		<groupId>org.apache.tomcat.embed</groupId>
		<artifactId>tomcat-embed-jasper</artifactId>
		<scope>provided</scope>
	</dependency>

Além disso, como é procedimento normal, precisamos configurar um prefixo e um sufixo para busca da nossa view. Podemos fazer isso do jeito tradicional, adicionando um método que retorna um InternalResourceViewResolver. Só que podemos aproveitar a oportunidade para já apresentar um outro detalhe que você pode tirar proveito, que são os arquivos de configuração externos. Você pode criar um arquivo chamado application.properties na raiz do seu classpath, geralmente em src/main/resources. Lá você pode colocar configurações específicas das tecnologias utilizadas no projeto, abaixo segue o meu exemplo.

  spring.mvc.view.prefix=/WEB-INF/jsp/
  spring.mvc.view.suffix=.jsp

  #hibernate
  spring.jpa.hibernate.ddl-auto=update

Perceba que ele é bem diferente de um spring-context.xml da vida. Você não tem que declarar um bean para ser usado, simplesmente configura as propriedades do bean já escolhido. 

Para fechar com chave de ouro, pelo menos para mim :), eles deram mais um passo pensando na vida fácil do usuário. Nessa semana eles lançaram um novo starter chamado de DevToolsUma facilidade adicionada foi a de recarregamento do projeto para cada mudança que você faz no código. Só que, como eles mesmos disseram, esse recarregamento é mais esperto do que um simples hot deploy de um servidor web tradicional. Além disso, ainda adicionaram o suporte para o Live Reloadque possibilita o recarregamento automático das páginas no seu navegador sempre que você alterar uma classe sua no servidor!

Ufa! Falei bastante hoje :). Acho o Spring Boot um projeto muito útil e que, com certeza, você devia dar uma olhada. É um approach que por muito eu esperava no mundo Java e espero que influencie outros projetos a fazer o mesmo. Por fim, acho importante lembrar que você deve continuar procurando o motivo do acontecimento das coisas, para não ficar um “programador de Spring Boot” ao invés de um programador  Java.

Advertisements

19 thoughts on “Começando com a magia do Spring Boot

  1. Como sempre, um excelente post. Particularmente estou gostando dos rumos que o Spring Boot esta tomando, principalmente para quem pensa em utilizar arquitetura Microservices a integração com NetflixOSS é fantástica.

    Like

  2. Oi Alberto,

    Concordo com você, o Spring Boot é um passo importante no mundo Java para mudarmos o pré-conceito por trás da comunidade Java, onde somos considerados burocráticos demais. Outros frameworks já tentaram o que o Spring Boot está tentando, como Grails e Play, porém eles não tiveram a força necessária para tal, talvez por serem considerados uma alternativa e não uma opção dentro do ecossistema Spring e/ou Java EE.

    Eu ainda pretendo usar o Spring Boot em projetos futuros, pois sou muito fã do ecossistema Spring. Enfim, excelente post e continue assim!

    Like

    • Oi Rafael,

      Tive bastante experiência com o Play também. Comparando os dois, posso dizer que a única coisa que sobrou melhor para o Play foi que ele ainda consegue escalar mais em única máquina, dado que o framework e o servidor web são bastante integrados. Caso a galera do Spring tente dar esse passo e se acople com algum servidor específico, acho que pode dar um jogo bom. O povo dos servidores de aplicação, tipo o Wildfly, tentaram fazer um pouco disso né? Widlfy + undertow, glassfish + grizzly… Mas as apis que usamos ainda são abstraídas.

      Like

  3. Ótimo post, eu sou dos que gosta de fazer a maneira antiga, sempre configuro tudo antes de começar o projeto, então só usei o Spring Boot em projetos pessoais, mas minha pergunta é simples, pelo que entendi o Spring Boot usa um Tomcat embed e se eu tiver que subir o projeto num servidor Weblogic por exemplo?

    Like

    • Oi Renato, a minha opinião é que você deve igualar os servidores de dev e de produção, para evitar surpresas. Você pode configurar o pom.xml para deixar seu projeto como um web project normal e deployar no weblogic em dev… Se não quiser igualar dev e produção, sugiro tem um ambiente de homologação. O Spring Boot só facilita a configuração, você customizar a sua vontade.

      Like

  4. Ótimo post Alberto, gostaria de saber se existe algum post seu sobre como utilizar AngularJS + Spring Boot ?

    Like

  5. Boa tarde Mestre.
    Estou acompanhando seu Livro Spring, tive problemas no final do capitulo 2. Erro devida dependências (NoSuchMethodError) Vou dar uma brincada com ele.
    Provavelmente conseguirei eliminar este erro substituindo e testando dependências, meu objetivo aqui é:

    Consigo eliminar toda configuração até o capitulo 2 do livro e colocar o Spring Boot para fazer este trabalho naquele Projeto ?

    Abraço

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s