Pular para o conteúdo principal

Do Browser para Impressora - Parte 3


Teoricamente, recuperar a saída de um Servlet (em geral um documento em texto como o HTML, mas pode ser qualquer arquivo incluso na resposta do servidor) mesmo que seja um JSP, deveria ser fácil. O JSP é convertido em uma classe Java que segue uma interface da especificação do Java Servlet com todas os métodos necessários para recuperar sua saída. Infelizmente, as classes geradas encontram-se em um contexto que o Classloader que executa os servlets não tem acesso. Então, para acessar as saídas dos JSPs é necessário uma abordagem mais indiretas. Na arquitetura J2EE, temos os seguintes recursos à nossa disposição:
  • Filtros: antes do envio da resposta ao cliente a cadeia de filtros intercepta a mensagem e pode enviar uma nova mensagem baseado na mensagem interceptada;
  • RequestDispatcher.include: esse (novo) método permite um servlet programaticamente adicionar o conteúdo de outro, o que é semelhante a tag jsp:include;
  • new URL(urlLocation).openStream: método que abre uma conexão com a localização urlLocation e retorna um stream de dados para leitura;
A solução utilizando url.openstream é simples, mas exige uma nova conexão para o servidor de aplicação proveniente dele mesmo. E é preciso tomar o cuidado utilizar a mesma sessão do usuário. Para isso, basta concatenar a url solicitada como jsessionId.
O uso de filtros ou do include method exige o uso de classes que sigam assinatura HttpServletResponse e do ServletOutputStream e que ao mesmo tempo, guarde as informações das chamadas em algum tipo de repositório. Essa é uma interessante aplicação do Adapter Pattern. O Adapter Pattern pode ser sumarizado da seguinte maneira.

Problema: (Múltipla herança) É desejado o comportamento de um objeto que infelizmente não segue uma assinatura específica.
Solução: Criar uma classe que implemente a interface e direcione as chamadas de forma apropriada ao objeto cujo comportamento é desejado.

Sendo o repositório escolhido para informações, um vetor de bytes. Escolhemos o ByteArrayOutputStream, que pode ser visto como um OutputStream e cujo resultado é guardado no vetor de bytes. Isso nos permite criar um objeto adaptado a interface ServletOutputStream e cuja implementação fica a cargo do ByteArrayOutputStream. Facilita também, utlizar o PrintWriter que já realiza as operações de Writer do ServletOutputStream. Esse PrintWriter deverá escrever diretamente no objeto ByteArrayOutputStream. Isso é feito ao passarmos esse objeto no construtor do PrintWriter.

Uma vez que temos essa classe, implementar a classe ServletResponse é muito simples:
public class FakeServletResponse extends HttpServletResponseWrapper{
  private ByteArrayOutputStream contentBuffer;
  private PrintWriter writer;
  private FakeServletOutputStream servletOutputStream;
  public FakeServletResponse(HttpServletResponse response) {
    super(response);
  }

  public PrintWriter getWriter() {
    if(writer == null){
      contentBuffer = new ByteArrayOutputStream();
      writer = new PrintWriter(contentBuffer);
      servletOutputStream = new FakeServletOutputStream(writer, contentBuffer);
    }
    return writer;
  }
  
  public ServletOutputStream getOutputStream() throws IOException {
    getWriter();
    return servletOutputStream;
  }

  public byte[] getData() {
    getWriter().flush();
    return contentBuffer.toByteArray();
  }
}
E então podemos utilizar o include method:
private FakeServletResponse includeJsp(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
  request.getSession().setAttribute("geraNota", Boolean.TRUE);
  FakeServletResponse fakeServletResponse = new FakeServletResponse(response);
  BuscaNotaAction buscaNotaAction = new BuscaNotaAction();
  buscaNotaAction.execute(mapping, form, request, fakeServletResponse);
  RequestDispatcher requestDispatcher = request.getRequestDispatcher("/jsp/operacoes/notaFiscal/imprimeNota.jsp");
  requestDispatcher.include(request, fakeServletResponse);
  return fakeServletResponse;
}

Comentários

Postagens mais visitadas deste blog

Um texto pós-moderno - better man

Espere olhando para as horas... são 4 horas. Tem que parar. Nesse tom melancólico, começa a modesta música "better man", uma balada pop composta por Eddie Vedder ainda na adolescência. A música é a ilustração perfeita da ironia. O próprio título é irônico, uma vez que em momento algum na música aparece um better man. She lies and says she's in love with him, can't find a better man... Irônico, não!? Para começar, com a personagem central da história, a mulher que aguarda tarde da noite seu esposo... Ela chega a treinar com o espelho o fim do relacionamento. E o que faz? Diz a negação do que queria dizer. Vedder escreve músicas sobre sentimentos fortes. Sua relação com a mãe foi bastante complicada pelo o que descreve em suas canções. Na trilogia Mommy, Vedder descreve um homem perturbado com o relacionamento materno; a mãe mente para o filho sobre a identidade do pai, revela a verdade para o garoto na puberdade dizendo a ele como se parece com o verdadeiro pai e o

Pequeno manual do ócio em terras alemãs

  Pequeno manual do ócio em terras alemãs Como Lei alemã favorece aproveitadoras (e alguns aproveitadores que nunca tive o desprazer de conhecer)   Há algumas vias pelas quais pessoas de países em desenvolvimento migram para países como a Alemanha.   Por exemplo, é sabido que países desenvolvidos sofrem de escassez de mão-de-obra qualificada. Por esse motivo, países como a Alemanha dispõe vistos "especiais" para profissionais em demanda. Esse é o conceito do Blaukart (Blue Card) que na Alemanha se destina a profissionais salário anual seja superior a 55 mil euros ou 43 mil no caso de profissionais de áreas em alta demanda. Não há como recrutar essa mão-de-obra sem que a família desses profissionais também possa ser relocada. Então esses profissionais e seus familiares são relocados.   Além de se qualificar para essas vagas em demanda, ou ser parte direta da família qualificada, outra via possível para a imigração para o território alemão é através do matrimôni

O argumento anti-álcool

A lógica contra a produção do álcool é mais ou menos a seguinte: Os produtores capitalistas, produtores do combustível de humanos e máquinas irão preferir vender combustível mais caro para os mais ricos do que comida barata para os mais pobres. Máquinas e homens irão competir por combustível... Mas enquanto os ricos terão dinheiro para comprar comida e combustível o que sobrará aos pobres!? Vale lembrar que não importa se a produção é de cana ou de milho, a competição é pela terra e não pelo grão. Ainda, mesmo que o país agrícola taxe o produtor de combustível de maneira diferenciada ao produtor de comida, o governo teria maiores dificuldades em repartir o "bolo", haja vista que os governos que temos não são as instituições mais eficientes e, além do que, a comida estará mais cara. Ora, esquecem os "amigos" comunistas que a venda de biocombustível dará aos países agrícolas uma oportunidade ímpar de participar da economia mundial como protagonistas, e não meros fi