tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 35472] New: - RequestDispatcher forward doesn't work with custom HttpServletRequest implementation
Date Wed, 22 Jun 2005 17:54:49 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=35472>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=35472

           Summary: RequestDispatcher forward doesn't work with custom
                    HttpServletRequest implementation
           Product: Tomcat 5
           Version: 5.5.9
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Catalina
        AssignedTo: tomcat-dev@jakarta.apache.org
        ReportedBy: christian@iks-jena.de


Hello there,

we're using an application that uses a custom implementation of
HttpServletRequest to trigger the RequestDispatcher. With an
include call everything works fine but forward doesn't work.
Basically there are two problems:

a) Catalina uses the internal DISPATCHER_TYPE (see Globals.java)
   attribute to remember the request state (REQUEST, FORWARD,
   INCLUDE, ERROR). This attribute is hardcoded in Catalinas
   request.getAttribute implementation and not listed during a
   request.getAttributeNames call. A standard Servlet 2.4
   application does not know the attribute and therefore can't
   copy it to it's own HttpServletRequest. A workaround is
   calling the container requests getAttribute as a fallback.
   But that's somewhat ugly. As the request implementation just
   returns a hardcoded REQUEST if the attribute is null this
   would be sufficient for the forward call, too.
   See my suggestions and code snippets from
   org.apache.catalina.core.ApplicationDispatcher CVS version 1.44 below.
   
b) unwrapRequest is called once during doInclude inside the
   invoke Method. Thats sufficient. doForward calls unwrapRequest
   again at the end of the method. Because unwrapRequest only
   breaks on instanceof Request and RequestFacade the code
   runs through and a ClassCastException occurs at the end.

DISPATCHER_TYPE attribute:
   
449 : remm 1.19     private void processRequest(ServletRequest request,  
450 :                                     ServletResponse response) 
451 :             throws IOException, ServletException { 
452 : jfarcand 1.15                  
453 : remm 1.19         Integer disInt = (Integer) request.getAttribute 
454 :                 (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR); 
455 :             if (disInt != null) { 
456 : jfarcand 1.15             if (disInt.intValue() != 
ApplicationFilterFactory.ERROR) { 
457 : remm 1.19                 outerRequest.setAttribute 
458 :                         
(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, 
459 :                          origServletPath); 
460 :                     outerRequest.setAttribute 
461 :                         (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR, 
462 :                          new Integer(ApplicationFilterFactory.FORWARD)); 
463 : jfarcand 1.15                 invoke(outerRequest, response); 
464 :                 } else { 
465 : remm 1.19                 invoke(outerRequest, response); 
466 : jfarcand 1.15             } 
467 : remm 1.19         } 
468 :      
469 : jfarcand 1.15     } 

processRequest is called by doForward only.
invoke() is only called if the attribute is not null.
The easiest fix for that would be to set the attribute to FORWARD
and call invoke when the attribute is null also. (same for the
DISPATCHER_REQUEST_PATH_ATTR) The check above is for the ERROR
case, if the attribute does not exist it can't be an error - its
a REQUEST by hardcoded default in org.apache.catalina.connector.Request.


unwrapRequest:

787 :         private void unwrapRequest() { 
788 :      
789 :             if (wrapRequest == null) 
790 :                 return; 
791 :      
792 :             ServletRequest previous = null; 
793 :             ServletRequest current = outerRequest; 
794 :             while (current != null) { 
795 :      
796 :                 // If we run into the container request we are done 
797 :                 if ((current instanceof Request) 
798 :                     || (current instanceof RequestFacade)) 
799 :                     break; 
800 :      
801 :                 // Remove the current request if it is our wrapper 
802 :                 if (current == wrapRequest) { 
803 :                     ServletRequest next = 
804 :                       ((ServletRequestWrapper) current).getRequest(); 
805 :                     if (previous == null) 
806 :                         outerRequest = next; 
807 :                     else 
808 :                         ((ServletRequestWrapper) previous).setRequest
(next); 
809 :                     break; 
810 :                 } 
811 :      
812 :                 // Advance to the next request in the chain 
813 :                 previous = current; 
814 :                 current = ((ServletRequestWrapper) current).getRequest
(); 
815 :      
816 :             } 
817 :      
818 :         } 

See line 797 - 799. If 'current' is an instance of HttpServletRequest
the request is fully unwrapped. Remember according to Servlet 2.4
SRV 6.2.2 the request attribute can be any descendant of HttpServletRequest.
As you can see the code runs through in this case up to line 814 where
the variable is casted to ServletRequestWrapper which causes the
ClassCastException. The fix is easy by adding HttpServletRequest to
the statement at line 797.
The only workaround is catching the ClassCastException around a
forward call and ignore it. But thats pretty ugly again ;-)

I hope I supplied enough information to fix it.
If there any questions I'll try to clarify.

Thanks.

Best regards,
Christian

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org


Mime
View raw message