Voando nas nuvens com VRaptor 4: Heroku e OpenShift

Hospedar sua aplicação numa nuvem é uma alternativa cada vez mais interessante. Os serviços são cada vez mais baratos, versáteis e fáceis de usar. Esse cenário fica ainda mais interessante quando podemos usar um framework como o VRaptor para escrever nossa aplicação.

Já escrevemos anteriormente aqui como colocar uma aplicação escrita com VRaptor 3 no Heroku de forma bem simples. Na sua quarta versão, o VRaptor passou por algumas mudanças arquiteturais, entre elas o uso da especificação CDI para controlar e injetar as dependências da aplicação. Isso significa que o VRaptor consegue aproveitar melhor os recursos de um servidor de aplicação como Glassfish ou Wildfly. Porém isso significa também que precisamos mudar um pouco a forma de fazer o deploy da aplicação num servidor na nuvem.

Neste post, veremos como criar uma aplicação simples do VRaptor e colocá-la para funcionar em dois serviços populares de hospedagem na nuvem: o Heroku e o Openshift, do qual já falamos aqui anteriormente. Para facilitar o gerenciamento de dependências da aplicação, usaremos o Maven.

A aplicação base

Vamos usar uma aplicação bem simples para realizar os testes. Ela vai ter um único método que responde "Olá" em texto puro:

@Controller
public class OlaController {
    @Inject private Result result;

    @Get("/")
    public void ola() {
        result.use(Results.http()).body("Olá").setStatusCode(200);
    }
}

O arquivo pom.xml com as dependências do projeto precisa basicamente apontar para o VRaptor e para o javax.inject, que contém as anotações da especificação CDI:

<dependencies>
	<dependency>
		<groupId>br.com.caelum</groupId>
		<artifactId>vraptor</artifactId>
		<version>4.1.4</version>
	</dependency>
	<dependency>
		<groupId>javax.inject</groupId>
		<artifactId>javax.inject</artifactId>
		<version>1</version>
		<scope>provided</scope>
	</dependency>
</dependencies>

Repare que a dependência javax.inject está declarada como provided. Declaramos ela assim pois, quando colocarmos a aplicação no Wildfly, por exemplo, ela já estará lá. Precisamos dela apenas para compilar o projeto.

Com isso, já conseguimos executar nossa aplicação localmente ou mesmo num servidor configurado por nós mesmos. Porém para que ela funcione no Openshift, precisamos fazer alguns ajustes.

Executando no Openshift

O Openshift já executa as aplicações Java usando o Wildfly como servidor. E mais: usa o Maven para compilar o projeto e gerar o WAR. Bastam alguns pequenos ajustes na configuração do Maven para que o Openshift consiga executar nossa aplicação corretamente.

O primeiro passo é criar uma aplicação no Openshift usando o cartridge com o Wildfly já instalado. Se você tiver a ferramenta de linha de comando rhc instalada, basta executar o comando

rhc create-app <nome-da-app> jboss-wildfly-8

Isso vai criar uma pasta com o nome da sua aplicação com um projeto Java já configurado lá dentro. Podemos usar esse projeto como base para a nossa aplicação com o VRaptor simplesmente adicionando-o como dependência no arquivo pom.xml e colocando nossas classes dentro de src/main/java.

Se quiser, também é possível adaptar o projeto criado anteriormente. Você só precisa garantir que o Maven gerará um arquivo chamado ROOT.war dentro da pasta deployments ao final do build. Para isso, você pode adicionar o seguinte trecho ao seu pom.xml:

<profiles>
	<profile>
		<id>openshift</id>
		<build>
			<finalName>vr4wildflytest</finalName>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.3</version>
					<configuration>
						<failOnMissingWebXml>false</failOnMissingWebXml>
						<outputDirectory>deployments</outputDirectory>
						<warName>ROOT</warName>
					</configuration>
				</plugin>
			</plugins>
		</build>
	</profile>
</profiles>

E pronto, simples assim! Basta um commit e um git push para que sua aplicação usando VRaptor 4 esteja rodando no Openshift.

Executando no Heroku

No Heroku, também temos o Maven construindo nosso projeto a cada git push. Porém, nossas facilidades acabam por aí: não temos nenhum servidor instalado lá para nós, apenas o Java (o Maven só está disponível durante a construção do WAR).

Nesse cenário, podemos recorrer a um servidor embarcado na nossa aplicação (o Jetty tem uma API muito boa para isso). Conseguimos rodar o VRaptor 4 no Jetty com alguns ajustes na nossa aplicação (a documentação explica como), mas o ideal seria não precisar fazer nenhum ajuste na nossa aplicação para que ela seja colocada na nuvem.

Uma outra alternativa nesse cenário seria instalar o Wildfly no Heroku. Isso é possível e na verdade o próprio Maven pode cuidar disso para a gente. Basta adicionarmos algumas linhas à seção de plugins do pom.xml instruindo-o a baixar e descompactar o Wildfly na fase package da construção da nossa aplicação:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-dependency-plugin</artifactId>
	<version>2.10</version>
	<executions>
		<execution>
			<id>unpack</id>
			<phase>package</phase>
			<goals>
				<goal>unpack</goal>
			</goals>
			<configuration>
				<artifactItems>
					<artifactItem>
						<groupId>org.wildfly</groupId>
						<artifactId>wildfly-dist</artifactId>
						<version>8.2.0.Final</version>
						<type>zip</type>
						<overWrite>false</overWrite>
						<outputDirectory>target</outputDirectory>
					</artifactItem>
				</artifactItems>
			</configuration>
		</execution>
	</executions>
</plugin>

Com isso, já teremos o Wildfly disponível. Falta apenas fazer com que nossa aplicação seja executada dentro desse Wildfly. Para isso, podemos configurar o plugin do Maven que gera o WAR para que ele gere esse WAR dentro da pasta deployments do Wildfly. Os arquivos .war dentro dessa pasta são automaticamente processados pelo Wildfly.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-war-plugin</artifactId>
	<version>2.3</version>
	<configuration>
		<failOnMissingWebXml>false</failOnMissingWebXml>
		<outputDirectory>target/wildfly-8.2.0.Final/standalone/deployments</outputDirectory>
		<warName>ROOT</warName>
	</configuration>
</plugin>

No código acima, também configuramos o Maven para que ele gere nosso arquivo com o nome ROOT.war. Dessa forma, nossa aplicação subirá com o contexto / dentro do servidor. Ou seja, localmente, conseguiremos testar nossa aplicação acessando http://localhost:8080.

Por fim, o Heroku precisa saber qual comando executar para subir nossa aplicação. Dizemos isso a ele no arquivo Procfile, que fica na raiz do nosso projeto. Para o nosso caso, o conteúdo desse arquivo será:

web: target/wildfly-8.2.0.Final/bin/standalone.sh -Djboss.http.port=$PORT -b 0.0.0.0

Repare que passamos dois parâmetros ao Wildfly: a porta na qual ele deve subir (o Heroku muda essa porta a cada vez que a aplicação sobe) e o parâmetro -b, dizendo que o Wildfly deve receber requisições de qualquer endereço (por padrão ele recebe requisições apenas da própria máquina).

Pronto! Agora, a cada git push, nossa aplicação será atualizada automaticamente no Heroku. E mais: novos desenvolvedores no time não precisarão se preocupar com a instalação e a configuração do servidor na própria máquina, já que um simples mvn package já vai baixar o servidor e colocar a aplicação no lugar certo para que eles comecem a trabalhar!

Outras nuvens

Em alguns casos, usar um serviço como Heroku ou Openshift pode não ser uma opção. Às vezes sua aplicação precisa de uma infraestrutura muito específica, que esses serviços mais automatizados não podem prover. Nesses casos, podemos seguir uma estrutura bem parecida com a que fizemos para executar a aplicação no Heroku, mas teremos que cuidar da atualização da aplicação e dos outros serviços dos quais nossa aplicação depender, como bancos de dados ou servidores de e-mail.

Uma nuvem que te dá esse poder é a nuvem da Amazon, que você pode conhecer melhor na trilha de infraestrutura do Alura. Lá também você pode conhecer outras ferramentas que facilitam o trabalho de manutenção numa infraestrutura desse tipo, ou mesmo nos seus próprios servidores!

6 Comentários

  1. Caio Ribeiro Pereira 05/02/2015 at 10:50 #

    Muito bom o post, só faltou citar o Getup Cloud, que é baseado no OpenShit e é brasileiro.

  2. Luiz Corte Real 05/02/2015 at 13:25 #

    Verdade, Caio. Obrigado por lembrar! Acabei trabalhando só com Heroku e OpenShift mas deve ser bem tranquilo fazer funcionar no Getup também!

  3. Samuel 05/02/2015 at 23:18 #

    Muito bom!!! Tava enganchando no pom.xml pro openshift!

    Parabéns pelo material!

  4. Ururai 27/02/2015 at 18:42 #

    Excelente artigo… Parabéns…

  5. Felipe Assis 02/06/2015 at 11:09 #

    Ótimo artigo e salvou minha vida rs!

    Começei a usar o OpenShfit a poucos dias e hoje eu fiz meu primeiro commit. Consegui fazê-lo, porém minha aplicação não está rodando com as atualizações que commitei e lendo o artigo percebi que não deu certo porque não comitei o ROOT.war. Vivendo e aprendendo! Vou testar o Heroku também.

  6. Esther 27/08/2015 at 17:48 #

    tentei usar o heroku, mas aparece so o caminho da minha pagina inicial, poderia me ajudar?

Deixe uma resposta