Java Servlets no Tomcat

Dezembro 11, 2011

Nesse post vou comentar um pouco sobre Servlets e um exemplo básico de utilização usando o Tomcat.

O que são Servlets?

Segundo a Wikipedia, um Servlet é uma classe Java usada para estender a funcionalidade de um servidor, sendo capaz de receber e enviar mensagens via um protocolo cliente-servidor (em geral HTTP).

Aplicações que utilizam a API de Servlets podem ser disponibilizadas na web através de um Web Container. Há diversos Web Container’s grátis, como por exemplo, o GlassFish (da própria Oracle), o JBoss AS (da Red Hat) e o Tomcat (da Apache). Podemos pensar em Web Conteiner’s como bibliotecas que implementam a API de Servlets.

A versão da API de Servlets que vamos utilizar é a 3.0 (Java EE6). Essa versão é suportada pelas seguintes versões dos Web Container’s citados acima: GlasshFish +3, JBoss AS +7 e Tomcat +7. Em nosso exemplo usaremos o Tomcat 7.

O build e o deploy do código serão feitos através do Maven.

Tomcat 7

Antes de mais nada, vamos instalar e configurar o Tomcat 7. Para instalar, basta baixar os .jar diretamente do site do Tomcat em um diretório qualquer. A partir de agora vamos nos referir ao local de instalação como $TOMCAT_DIR. Na pasta $TOMCAT_DIR/bin, podemos iniciar o Tomcat através do script startup.sh.

Para verificar se o Tomcat foi corretamente iniciado, podemos entrar no endereço localhost:8080.

Podemos gerenciar o Tomcat via web, mas para isso, precisamos adicionar um usuário no arquivo $TOMCAT_DIR/conf/tomcat-users.xml. Nesse arquivo xml, adicione a seguinte entrada dentro da tag <tomcat-users>:

<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="nome-usuario" password="senha" roles="manager-gui, manager-script"/>

trocando "nome-usuario"/"senha" por valores adequados. É preciso reiniciar o Tomcat (shutdown.sh + startup.sh). Agora você deverá poder acessar a página localhost:8080/manager com o usuário e senhas cadastrados.

Servlet Java

A estrutura de diretórios do nosso exemplo é a seguinte:

|-- pom.xml
 `-- src
     `-- main
         |-- java
         |   `-- me
         |       `-- kuniga
         |           `-- main
         |               `-- MyApp.java
         |-- resources
         |
         `-- webapp
             `-- WEB-INF

A implementação da nossa única classe é baseada em [4]. Uma das novidades da API de Servlets 3.0 é o uso de anotações para configuração, como podemos ver no código a seguir:

@WebServlet("/MyApp")
public class MyApp extends HttpServlet {

  @Override
  protected void doGet(HttpServletRequest request,
                       HttpServletResponse response)
      throws ServletException, IOException {

    String nome = request.getParameter("nome");

    PrintWriter out = response.getWriter();
    out.println("Ola: " + nome);
  }
}

O argumento passado para a anotação WebServlet definirá a url de acesso à nossa aplicação. Já o método doGet será invocado quando uma requisição do tipo GET for feita. O conteúdo passado para o PrintWriter será retornado para o cliente.

Para compilar o código acima, devemos incluir a API 3.0 de Servlets. Podemos fazer isso incluindo uma dependência das APIs do Java EE6:

<dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-api</artifactId>
  <version>6.0</version>
  <scope>provided</scope>
</dependency>

É importante setar o escopo como provided para que o maven não coloque o .jar contendo as APIs do Java EE6 no arquivo .war. Isso porque no Tomcat esse .jar já está presente e a duplicata ocasiona erro. (Aliás, uma dica para debugar erros é iniciar o Tomcat através do comando ./catalina.sh run ao invés do ./startup.sh, pois desta forma as mensagens de log são exibidas no terminal).

Configurando plugins do Maven

Basicamente o que o maven fará é compilar o programa e compactá-lo em um arquivo .war e então fará o deploy desse arquivo no Tomcat.

Vamos primeiramente configurar o plugin maven-war-plugin, que é responsável por gerar o arquivo .war. Em versões anteriores da API de Servlets, era necessário um arquivo de configuração chamado web.xml que ia em webapp/WEB-INF. Agora, a configuração básica pode ser feita através de anotações na classe do servlet e o arquivo web.xml não é obrigatório.

Por padrão, o plugin maven-war-plugin gera um erro na ausência do web.xml, mas podemos modificar esse comportamento através da seguinte configuração no pom.xml:

<plugin>
  <artifactId>maven-war-plugin</artifactId>
  <configuration>
    <failOnMissingWebXml>false</failOnMissingWebXml>
  </configuration>
</plugin>

O outro plugin que iremos configurar é o tomcat-maven-plugin, responsável pelo deploy no tomcat. Para isso, ele precisa da url de acesso ao manager, bem como um login válido para acessá-la. Podemos passar os dados de login através do pom.xml.

Mais especificamente, adicionamos uma entrada no settings.xml do maven, que se encontra em ~/.m2/settings.xml (mais informações sobre esse arquivo aqui).

<server>
  <id>mytomcat</id>
  <username>nome-usuario</username>
  <password>senha</password>
</server>

Onde id é um identificador qualquer, e username e password são aqueles que usamos no cadastro de usuário no Tomcat. No pom.xml do projeto passamos essa informação de login e a url da página:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>tomcat-maven-plugin</artifactId>
  <configuration>
    <url>http://localhost:8080/manager/html</url>
    <server>mytomcat</server>
  </configuration>
</plugin>

A versão completa do pom.xml está aqui e também disponibilizei o projeto todo no github.

Agora podemos executar os seguintes goals do maven:

> mvn clean package tomcat:deploy

Rodando a aplicação

Para testar a aplicação em funcionamento, podemos acessar a seguinte url: http://localhost:8080/kservlet/MyApp?nome=mundo

Referências

[1] Java Servlet – Página oficial da Oracle
[2] Java Servlet – Wikipedia
[3] How do I deploy a maven web application to Tomcat?
[4] Blog Caelum – Java EE6: Começando com as Servlets 3.0
[5] Tomcat 6.0.32 + Maven undeploy via script not working