jakarta-cactus-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Vincent Massol" <vmas...@octo.com>
Subject RE: Dispatch problem
Date Sun, 10 Feb 2002 11:14:24 GMT
Kim,

As Nicholas said, these are interesting issues ! ...

Let me try to answer below.

> -----Original Message-----
> From: kim [mailto:kim] On Behalf Of Kim Madsen
> Sent: 08 February 2002 14:47
> To: cactus-user@jakarta.apache.org
> Subject: Dispatch problem
> 
> I have a few problems with Cactus, which I have been unable to find
any
> information about. I got several Cactus test cases which works fine,
but
> the below cases does not work for me.
> 
> I am using JBoss with Tomcat 3.2.3.
> 
> 
> 1) Problem with dispatching from Servlet to JSP.
> 
> In my Servlet I redirect/dispatch to a JSP template. This works fine,
> when running the Servlet without Cactus. But when running my Cactus
test
> case I get below error every time. This is the code that fails.
> 
> 
>         ServletContext servletContext  = getServletContext();
> 
> 	javax.servlet.RequestDispatcher requestDispatcher  =
> 	    servletContext.getNamedDispatcher( template );
> 	requestDispatcher.forward( req, res );  <------- This goes
wrong.
> 
> I have initialized the servlet context first in the Cactus test case:
> 	servlet.init(config);
> 
> This is the error I get:
> 
> java.lang.NullPointerException
> at
>
org.apache.cactus.server.RequestDispatcherWrapper.forward(RequestDispatc
he
> rWrapper.java:98)
> at com.inceptor.rt.Servlet.dispatchError(Servlet.java:164)

[snip]

I'm currently looking into this. There is indeed a bug in Cactus, in
that the Cactus-wrapped getNamedDispatcher() does not return null if the
servlet (named "template" in your example) is not found. Instead Cactus
returns a request dispatcher wrapper. I have corrected this. It means
that now your test will still return a NullPointerException but in
_your_ code rather than in Cactus code. The null pointer will happen on
the line :

requestDispatcher.forward( req, res );

This is normal, it is part of the spec. The spec says to return null if
the named servlet cannot be found. Make sure your "template" is in the
same context and has an entry in web.xml.

Note 1 : I've added a test case in Cactus so that this problem does not
happen again. Here it is :

    public void testGetRequestDispatcherFromNamedDispatcher()
        throws ServletException, IOException
    {
        RequestDispatcher rd =
            config.getServletContext().getNamedDispatcher("TestJsp");
        rd.forward(request, response);
    }

    public void endGetRequestDispatcherFromNamedDispatcher(WebResponse
theResponse)
        throws IOException
    {
        String result = theResponse.getText();
        assertTrue("Page not found, got [" + result + "]",
            result.indexOf("Hello !") > 0);
    }

"TestJsp" is defined in web.xml as :

    <servlet>
        <servlet-name>TestJsp</servlet-name>
        <jsp-file>/test/test.jsp</jsp-file>
    </servlet>

Note 2 : I've tried it with Tomcat 4.x and Tomcat 3.2.4 and it works
fine. However, it fails on Tomcat 3.3.x ... I'll submit a bug report to
them as it looks like a bug.

> 
> 
> 2) Response 404 least to file not found exception:
> 
> For some request my Servlet correct behaviour is to respond with a 404
> Page Not Found.
> This works fine when running the servlet without Cactus, however, when
> running my Cactus test case I get the below error:
> 
> So the servlet code is:
> 	res.sendError(HttpServletResponse.SC_NOT_FOUND);
> 	res.flushBuffer();
> 
> The exception I get is:
> 
> java.io.FileNotFoundException:
> http://localhost:8080/cactus/ServletRedirector/

[snip]

Yes, I know about this issue. Do you know if there is any way to tell
HttpURLConnection not to interpret returned codes ? My plan is to move
to Commons HttpClient (i.e. replace HttpURLConnection by HttpClient).

I already have this issue when testing for a redirect ... I have it
commented out in the cactus test case ... It seems this issue is getting
more urgent every day ... 

> 
> 
> 3) Synchronization problem.
> 
> In some cases my Servlet sends a redirect flushes the buffer... and
then
> continues to do some processing for logging.
> 
> 	    response.sendRedirect(redirectURL);
>
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
> 	    response.flushBuffer();
> 	    ... more stuff for logging.
> 
> This works fine, as long as the test is run in isolation. However, if
I
> do 2 of these test after each other I get into trouble because the
setUp
> method of the second test is run before the tearDown method of the
first
> test. I have avoided this by inserting a statement in the endXXX
method
> that makes the first test sleep for 10 seconds - such that the start
of
> the next test is delayed.
> 
> However, it seems to me that fact that I am flushing the http-response
> tricks Cactus into thinking that the test has completed, when in fact
> the Servlet is still processing.
> 

This is a complex issue ! In fact, the Client side of Cactus is waiting
for the HTTP response. When you do a flush, the server starts sending
the response. On the client side, Cactus reads all the data that are on
the wire, using :

        if (this.delegate.getContentLength() != 0) {

            byte[] buf = new byte[DEFAULT_CHUNK_SIZE];
            int count;

            while (-1 != (count = theInputStream.read(buf))) {

                theOutputStream.write(buf, 0, count);
            }

        }

where this.delegate is the InputStream (i.e. response from the Server).
The read() method blocks until input data is available, end of file is
detected, or an exception is thrown. If you don't close the socket on
the server side (by issuing a close()) then I would imagine the read
will block and the test will not be finished.

If you're doing a close you're actually unsynchronising the response
from other work that you still need to perform on the server side. This
is fine and even nice in term of response time ! 

.. argh .... I know remember something I had done in the past and
removed ... 

Ok, here's the story : Previously, I had introduced a semaphore on the
test result that is stored in the servlet context ... But I removed some
time ago as it was a kludge and couldn't remember why I had put it ...
:-(

Hum ... Here's what I'll try to do to fix this issue :

1/ At the beginning of each test, reset the context variable holding the
result
2/ When the Cactus client asks to get the result, the server side will
check if the variable is null or not. If null then it will sleep for a
few milliseconds and try again, etc, until it gets a non-null value,
signaling that the test is actually finished

Thus the second test will not start before the first one is finished.

I'll try to add a test case for this first and will keep you informed of
the progress.

Thanks for these 3 challenging issues ;-)

-Vincent

> 
> Any help on any of these 3 issues would greatly be appreciated.
> 
> --
> To unsubscribe, e-mail:   <mailto:cactus-user-
> unsubscribe@jakarta.apache.org>
> For additional commands, e-mail: <mailto:cactus-user-
> help@jakarta.apache.org>
> 



--
To unsubscribe, e-mail:   <mailto:cactus-user-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:cactus-user-help@jakarta.apache.org>


Mime
View raw message