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

Expressões, preconceito e racismo

Expressões preconceituosas e racistas Antes de alguma outra frase, primeiro peço licença para falar de mais um assunto do qual não domino. Falo por acreditar que um leigo presta serviço maior ao debater assunto com base em fontes (ainda que seja uma Wikipedia) e no pensamento lógico do que simplesmente se manter mudo a questões do cotidiano. Em voga agora está em falar quais são ou eram as expressões preconceituosas e racistas que até a pouco eram toleradas em muitos meios.
Como é covarde dizer que em boca fechada não entra racismo. O racismo não é perpetrado apenas por quem profere mas por quem se cala à agressão perpetrada a outrem. Mas veremos que a questão é muito mais complexa que os cães raivosos do politicamente correto querem dizer.
Tomo aqui a palavra racista, como sendo algo usado para impor a dominação de uma “raça” sobre outra. Portanto, a acusação de racismo vai muito além da mera acusação de preconceito. Não tenho o menor apreso por vitimismo barato, onde expressões que…

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 leva …

Filme: Obrigado Por Fumar

Obrigado Por Fumar (Thank you for Smoking) - 2006Filme escrito e dirigido por Jason Reitman, produzido por David Sacks e baseado na novela de Christopher Buckley. Duração de 92 minutos.
"Obrigado Por Fumar" é um aclamado filme, vencedor do globo de ouro 2006 e sucesso em bilheterias (com faturamento superior a 39 milhões de dólares). O filme conta a história de Nick Naylor (Aaron Eckhart), vice-presidente da empresa Academia do Estudo do Tabaco, um lobby da indústria tabagista, e como ele usa suas habilidades de persuação para defender os interesses de seus superiores.
Direção muito interessante: ao contrário do que se pode esperar, o filme não mostra um quadro contaminado por fumaça em que o próprio telespectador tenha dificuldades em respirar. Aliás, o filme não mostra nehuma pessoa fumando. Também não faz uma crítica raivosa à indústria do cigarro. Seus argumentos são sutis, inteligentes e bem-humorados. Mas, a mensagem não passa despercebida pelo público, apenas não o agri…