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

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

The escape of blue eyed vampires (answer)

The island of blue eyed vampires (answer) An initial idea Each one needs to figure out if him/herself is blue eyed. They assume having blue eyes and see how the others react. A technical details There are some variations to formalize this problem using different type of logic: modal logic, temporal logic, Public Announcement Logic and so on. I believe that those kind of prove are tedious to write and read. For now, I will write a sketch to a prove but I belive the best way to prove is using an algorimthm what basically, it would be an adaptation of DPLL algorithm (Davis–Putnam–Logemann–Loveland) that uses dedutive reasoning and prove by contraction. Legend \[\begin{matrix} BlueEyed(X) :X \text{ is blue eyed.} \\ Leave(X) :X \text{ leaves.} \\ O(y) :y \text{ holds at the next (temporal) state.} \end{matrix}\] In this temporal simplified logic, we have a set of state that holds the in- formation of days, \(W = \{d_0, d_1, d_2, d3 \ldots , d_n\}\) and transition \(S : W \rightarrow

Answering: top reasons I hate living in Brazil

Yes, some guys shared a teasing topic about “Top reasons why I hate living in Brazil”: http://www.gringoes.com/forum/forum_posts.asp?TID=17615&PN=1&title=top-reasons-i-hate-living-in-brazil What is the point here? The whole text is loaded of cliclés, people that you will hardly find, etc most of time just pissing people off.   I don’t think Brazil is the best country in the world. Also, I don’t think Brazilians don’t make mistakes. Actually we do all the time but most of us really care about our mistakes specially those were pointed out. Some feel like an expatriate, alien in own country. Others reflect about how we could improve. Others  simply don’t accept teases from John Does. So, I’m actually truly bothered with people believing in a bunch of false statements (specially Brazilians) or supporting some cynical arguments disguised “sincere” criticisms . Yes, I make mistakes all the time, and as most of Brazilians, I don’t speak English. However, I will