[J2EE] RequestDispatcher.include problem

J

John English

I have an application where the servlets generate XML and their output
goes through an XSLT filter. This all works fine, except when I try to
use RequestDispatcher's include() method to paste in some external
content. Whenever I try to do this, the XS:T filter bombs out with
an IllegalStateException at the point where it calls getWriter() to
get the output stream. The code looks something like this:

In the servlet, inside doGet(), I have:

println("<html>");
try {
RequestDispatcher disp =
context.getRequestDispatcher("/foo.html");
disp.include(request,response);
}
catch (Exception e) {
System.out.println("Include failed: " + e.getMessage());
// this never happens... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
e.printStackTrace();
}
println("</html>");

(using <html> to delimit HTML content in the enclosing XML).

In the XSLT filter I have:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
try {
CharResponseWrapper wrapper =
new CharResponseWrapper((HttpServletResponse)response);
chain.doFilter(request,wrapper);
String s = wrapper.toString();
if (s.length() > 0) {
InputSource input = new InputSource(new StringReader(s));
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
SAXParser parser = spf.newSAXParser();
reader = parser.getXMLReader();
stf = (SAXTransformerFactory) TransformerFactory.newInstance();
filter = stf.newXMLFilter(new StreamSource(stylesheet));
filter.setParent(reader);
StreamResult result = new StreamResult(response.getWriter());
// fails here... ^^^^^^^^^^^^^^^^^^^^
// but only when I've used include() in the servelt being filtered!
Transformer transformer = stf.newTransformer();
SAXSource transformSource = new SAXSource(filter, input);
transformer.transform(transformSource, result);
(... and so on...)

Does anyone have any idea why the response writer might end up in
an illegal state because of using include()?
 
A

Andrea Desole

John said:
Does anyone have any idea why the response writer might end up in
an illegal state because of using include()?


the documentation is clear:

IllegalStateException - if the getOutputStream method has already been
called for this response object

maybe the included page uses getOutputStream? Try to call
response.getOutputStream instead of getWriter
 
R

Raymond DeCampo

John said:
I have an application where the servlets generate XML and their output
goes through an XSLT filter. This all works fine, except when I try to
use RequestDispatcher's include() method to paste in some external
content. Whenever I try to do this, the XS:T filter bombs out with
an IllegalStateException at the point where it calls getWriter() to
get the output stream. The code looks something like this:

In the servlet, inside doGet(), I have:

println("<html>");
try {
RequestDispatcher disp =
context.getRequestDispatcher("/foo.html");
disp.include(request,response);
}
catch (Exception e) {
System.out.println("Include failed: " + e.getMessage());
// this never happens... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
e.printStackTrace();
}
println("</html>");

(using <html> to delimit HTML content in the enclosing XML).

In the XSLT filter I have:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws ServletException, IOException {
try { [snip]
StreamResult result = new StreamResult(response.getWriter());
// fails here... ^^^^^^^^^^^^^^^^^^^^
// but only when I've used include() in the servelt being filtered! [snip]
(... and so on...)

Does anyone have any idea why the response writer might end up in
an illegal state because of using include()?

Here's a thought. The servlet API allows you to get a writer to write
the response or a stream to write the response, but not both. It is
possible that the RequestDispatcher.include() used the stream, not the
writer, thereby hosing your future attempt to use the writer.

HTH,
Ray
 
J

John English

Andrea said:
the documentation is clear:

IllegalStateException - if the getOutputStream method has already been
called for this response object

maybe the included page uses getOutputStream? Try to call
response.getOutputStream instead of getWriter

The included page is just vanilla HTML. (Well, XHTML, suitable for shoving
through an XSLT filter.)

So, maybe include() uses getOutputStream() rather than getWriter(), which is
what I use everywhere else. In which case, it's a waste of space AFAICS.

Anyway, in the meantime I'm just creating a FileInputStream and reading from
that instead... Most of the J2EE API just seems to be designed to prevent you
doing anything useful in a finite amount of time!

However, when I get some free time to ponder this without worrying about
hitting targets, I might well investigate further... Suggestions welcome
in the meantime from anyone with more experience and/or free time.

Thanks...
 
J

John English

Andrea said:
the documentation is clear:

IllegalStateException - if the getOutputStream method has already been
called for this response object

maybe the included page uses getOutputStream? Try to call
response.getOutputStream instead of getWriter

The included page is plain old HTML, not a servlet, so any streams needed
to include it must be opened by the server when it serves up the page...

Could try getOutputStream, but the examples I've seen show the base servlet
using getWriter and including another resource as well. What puzzles me is
that the error occurs in the filter, not in the original servlet. From examples
on Sun's website, I would expect what I've done to be perfectly legit.
 
J

junaid

have you tried to add following in web.xml

<filter-mapping>
<filter-name>VJFilterTest</filter-name>
<!--<servlet-name>VJServlet</servlet-name>-->
<url-pattern>/servlet/MyTest</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
 
A

Andrea Desole

John said:
The included page is plain old HTML, not a servlet, so any streams needed
to include it must be opened by the server when it serves up the page...

that's probably what happens
Could try getOutputStream, but the examples I've seen show the base servlet
using getWriter and including another resource as well. What puzzles me is
that the error occurs in the filter, not in the original servlet. From
examples
on Sun's website, I would expect what I've done to be perfectly legit.

why should you have it in the servlet? You are not calling
response.getWriter there, are you?
I don't know the examples you are talking about (do you have a url?),
but looking better at the documentation I saw that getWriter should be
used for non binary streams, while for binary and mixed streams you
should use getOutputStream. So I was guessing that maybe setting the
content type to "text/html" (and maybe the character encoding) at the
beginning of the filter, before anything is written to the response,
might help.

Anyway, if you really need a writer you can use:

new PrintWriter( response.getOutputStream() );
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top