BT

Novidades no Servlet 3.1: suporte a cloud e escalabilidade em foco

por Rafael Sakurai em 30 Jul 2012 |

Foi liberada a versão inicial (early draft) da especificação Servlet 3.1 (JSR 340). Entre as melhorias estão o suporte ao desenvolvimento de aplicações em nuvem PaaS; aperfeiçoamentos em segurança e no gerenciamento de sessões e recursos; IO assíncrono baseado no NIO2, e simplificação da criação de servlets assíncronos. O Servlet 3.1, além disso, faz uso dos utilitários de concorrência do Java EE (JSR 236) e introduz suporte a WebSockets.

Suporte a ambientes em nuvem

O Servlet 3.1 atende ao objetivo principal do futuro Java EE 7: a execução de aplicações em ambientes de nuvem públicos e privados, seguindo o modelo de Plataforma como Serviço (PaaS).

Dentro de um container web, será possível compartilhar uma aplicação com múltiplos clientes, ou ter uma instância de aplicação instalada por cliente. Pode-se fazer o mapeamento dos clientes diretamente no container e garantir o isolamento das aplicações instaladas. Além disso, recursos de configuração personalizados poderão ser criados para cada cliente, além de se poder definir metadados para os serviços.

Para suportar PaaS efetivamente, são levados em consideração requisitos como segurança, estados das sessões, gerenciamento de recursos (ex.: conexões com bancos de dados, filas de mensagens e outros), além do isolamento das aplicações.

Servlets assíncronos

Com o processamento assíncrono de servlets, será possível fazer uma requisição para um servlet iniciar alguma tarefa em paralelo, enquanto é gerada a resposta para quem iniciou a solicitação.

Quando um processo assíncrono for iniciado através da chamada ao método request.startAsync() ou request.startAsync(request, response), uma nova thread ou método de retorno será responsável por gerar a resposta e por chamar o método complete(). Como alternativa, pode-se fazer uma requisição usando o método dispatch() da classe AsyncContext. Veja um exemplo:

@WebServlet(name = "Pedido", urlPatterns = {"/Pedido"}, asyncSupported = true)
public class Pedido extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request,
         HttpServletResponse response) throws ServletException, IOException {
      //Inicia um contexto assíncrono.
      AsyncContext ac = request.startAsync(request, response);
      ac.addListener(new AsyncListener() {
      @Override
      public void onComplete(AsyncEvent event) throws IOException {
        System.out.println("onComplete");
      }
      @Override
      public void onTimeout(AsyncEvent event) throws IOException {
        System.out.println("onTimeout");
      }
      @Override
      public void onError(AsyncEvent event) throws IOException {
        System.out.println("onError");
      }
      @Override
      public void onStartAsync(AsyncEvent event) throws IOException {
        System.out.println("onStartAsync");
      }
    });
    ScheduledThreadPoolExecutor executor = new
        ScheduledThreadPoolExecutor(10);
    executor.execute(new ProcessamentoAssincrono(ac));
  }
}

class ProcessamentoAssincrono implements Runnable {
  private AsyncContext ac;
  public ProcessamentoAssincrono(AsyncContext ac) {
    this.ac = ac;
  }
  @Override
  public void run() {
    //Executa o processamento assíncrono.
    //Quando terminar, avisa o contexto assíncrono que completou a tarefa.
    ac.complete();
  }
}

A especificação da classe AsyncContext deixa claro que ocorrerá uma IllegalStateException se os métodos getRequest() ou getResponse() forem chamados após a solicitação dos métodos complete() e dispatch().

IO assíncrono

Para auxiliar o IO (Entrada e Saída) assíncrono, foi adicionada a funcionalidade de IO sem bloqueio, que será usada pelos containers web para melhorar a escalabilidade. Esse tipo de IO permite aumentar o número de conexões que podem ser tratadas simultaneamente, além de trazer outras vantagens. Para isso, foram criadas novas interfaces, como ReadListener e WriteListener, que irão fornecer métodos para ler e escrever dados sem bloqueio.

Houve ainda alterações na classe ServletInputStream, para receber o ReadListener e informar quando os dados podem ser lidos sem bloqueio; a classe informa ainda se a leitura dos dados associados a um ServletReader ou ServletInputStream já terminou. E a classe ServletOutputStream foi alterada, para que possa receber um WriteListener, que será notificado quando o servlet puder gravar os dados, sem que haja o bloqueio.

Melhorias de segurança

Quando for especificado o uso de run-as (anotação @RunAs), os métodos init() e destroy() do Servlet também devem propagar esta regra de segurança quando um EJB for chamado. Por exemplo:

@RunAs("Admin")
@WebServlet(name="CalculatorServlet", urlPatterns={"/CalculatorServlet"})
public class CalculatorServlet extends HttpServlet {
  @EJB
  private ShoppingCart myCart;

  @Override
   public void destroy() {
      super.destroy();
      myCart.destroy();
   }

  @Override
  public void init() throws ServletException {
      super.init();
      myCart.init();
  }
}

Suporte a WebSockets

No Servlet 3.1 foi incluído o suporte necessário para utilização dos WebSockets e o uso de outros protocolos baseados no HTTP. Foi adicionado suporte ao cabeçalho Upgrade do HTTP/1.1, em que o cliente especifica o protocolo de comunicação que deseja usar com o servidor. Isso facilita o uso de diferentes protocolos nos WebSockets.

Para contemplar tal funcionalidade, foi adicionado o método upgrade(ProtocolHandler handler) na interface HttpServletRequest. O container não precisa conhecer o protocolo de comunicação, devendo apenas passar um WebConnection para o método ProtocolHandler.init() encapsular o protocolo.

Outras melhorias

Entre outras pequenas melhorias, a interface ServletRequest possui agora os métodos getContentLengthLong(), que obtém o tamanho em bytes do corpo da requisição, e o setContentLengthLong(long len) que define o tamanho do conteúdo do corpo da resposta da requisição.


Mais informações sobre a especificação Servlet 3.1 podem ser obtidas na página da JSR 340, na lista de discussão ou no site do projeto. Caso haja interesse em contribuir com a especificação, pode-se enviar um email para users@servlet-spec.java.net, com sugestões e críticas.

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber menssagens dessa discussão
Comentários da comunidade

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber menssagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber menssagens dessa discussão

Dê sua opinião

Conteúdo educacional

Feedback geral
Bugs
Publicidade
Editorial
InfoQ Brasil e todo o seu conteúdo: todos os direitos reservados. © 2006-2013 C4Media Inc.
Política de privacidade
BT