You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by James Dasher <jf...@thermopylae.com> on 2002/01/08 19:18:44 UTC

Possible bug: Present Struts 1.0 PropertyUtils introspection code bonks on the variety of Tomcat 4 ServletRequest facades that get handed to us as HttpServletRequest

Whoever thought of <bean:page>, I love it, but it exposes some weird
introspection inconsistencies in the Tomcat container, and I am out of
my depth.  Help.

I have seen two classes that get thrown up as HttpServletRequests to the
container.

org.apache.catalina.connector.HttpRequestFacade
org.apache.catalina.core.ApplicationHttpRequest

I assume that these objects should be interchangeable, handed to the
servlet as an HttpServletRequest, treated as an HttpServletRequest.
All I know is that they behave differently from an introspection point
of view--end result being that when you have an
org.apache.catalina.connector.HttpRequestFacade, you can introspect its
get() methods, when you have an
org.apache.catalina.core.ApplicationHttpRequest, you can't.

My environment is Tomcat 4.0.1 running embedded in Jboss.

1.  I get handed a org.apache.catalina.connector.HttpRequestFacade as my
ServletRequest Object.toString().
2.  I expose it as a bean, <bean:page> and attempt to get the
servletPath property (in other words force a call to
HttpServletRequest.getServletPath()).
3.  This works, as shown below by my ridiculous log-hacking of
PropertyUtils:

[INFO,Default] Matched propertydescriptor to property: servletPath
[INFO,Default] In getReadMethod with PropertyDescriptor servletPath
looking for ReadMethod getServletPath
[INFO,Default] In getAccessibleMethod with method getServletPath
[INFO,Default] org.apache.catalina.connector.HttpRequestFacade is
public.  Cool.

At this point, we got the method and called it, got the property, yadda
yadda.

Let's try that again when our request happens to be a
org.apache.catalina.core.ApplicationHttpRequest:

[INFO,Default] Matched propertydescriptor to property: servletPath
[INFO,Default] In getReadMethod with PropertyDescriptor servletPath
looking for ReadMethod getServletPath
[INFO,Default] In getAccessibleMethod with method getServletPath
[INFO,Default] Didn't succeed elsewhere with getServletPath so let's
check interfaces.
[INFO,Default] In getAccessibleMethodFromInterfaceNest with class
org.apache.catalina.core.ApplicationHttpRequest method getServletPath
parameterTypes: length=0
[INFO,Default] Found 0 interfaces of
org.apache.catalina.core.ApplicationHttpRequest

[ERROR,EmbeddedCatalinaServiceSX] ApplicationDispatcher[/evangeline]
Servlet.service() for servlet jsp threw exception
javax.servlet.ServletException: No getter method for property
servletPath of bean httpservletreq
        at
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContex
tImpl.java:457)
        at org.apache.jsp.navbar$jsp._jspService(navbar$jsp.java:626)
        at
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at
org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServle
t.java:202)
	  ...and fifteen more pages of stacktrace.

Basically what is happening is 
A) org.apache.catalina.core.ApplicationHttpRequest is not public, so we
can't use the method
B) For reasons not fully understood, the
getAccessibleMethodFromInterfaceNest can't find any interfaces for
org.apache.catalina.core.ApplicationHttpRequest.  

For a little background, org.apache.catalina.core.ApplicationHttpRequest
extends javax.servlet.http.HttpServletRequestWrapper, which implements
javax.servlet.http.HttpServletRequest, javax.servlet.ServletRequest.
I can't remember if when your superclass implements something, you do
too.

Anyway:  Is this a problem with the PropertyUtils?  Is this an issue
with the ApplicationHttpRequest implementation?  I don't know.  Please
advise.

For reference, my println'ed-up getAccessibleMethod and
getAccessibleMethodFromInterfaceNest are here:

private static Method getAccessibleMethod(Method method) {
        System.out.println("In getAccessibleMethod with method " +
method.getName());
        // Make sure we have a method to check
        if (method == null) {
            return (null);
        }

        // If the requested method is not public we cannot call it
        if (!Modifier.isPublic(method.getModifiers())) {
            System.out.println(method.getName() + " not public.
Bonking.");
            return (null);
        }

        // If the declaring class is public, we are done
        Class clazz = method.getDeclaringClass();
        if (Modifier.isPublic(clazz.getModifiers())) {
            System.out.println(method.getDeclaringClass().getName() + 
            " is public.  Cool.");
            return (method);
        }
        System.out.println("Didn't succeed elsewhere with " +
method.getName() + 
                           " so let's check interfaces.");
            
        // Check the implemented interfaces and subinterfaces
        String methodName = method.getName();
        Class[] parameterTypes = method.getParameterTypes();
        method =
            getAccessibleMethodFromInterfaceNest(clazz,
                                                 method.getName(),
 
method.getParameterTypes());
        return (method);
}

private static Method getAccessibleMethodFromInterfaceNest
        (Class clazz, String methodName, Class parameterTypes[]) {
        System.out.println("In getAccessibleMethodFromInterfaceNest with
class " +
                               clazz.getName() + "method " + methodName
+ 
                               " parameterTypes: length=" +
parameterTypes.length);
        for (int i = 0; i < parameterTypes.length;i++) {
            System.out.println(": " + parameterTypes[i].getName());
        }
            
        Method method = null;

        // Check the implemented interfaces of the parent class
        Class interfaces[] = clazz.getInterfaces();
        System.out.println("Found " + interfaces.length + " interfaces
of " +
                           clazz.getName());
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println("Found interface: " +
interfaces[i].getName());
            // Is this interface public?
            if (!Modifier.isPublic(interfaces[i].getModifiers()))
                continue;

            // Does the method exist on this interface?
            try {
                method = interfaces[i].getDeclaredMethod(methodName,
 
parameterTypes);
            } catch (NoSuchMethodException e) {
                ;
            }
            if (method != null)
                break;

            // Recursively check our parent interfaces
            method =
                getAccessibleMethodFromInterfaceNest(interfaces[i],
                                                     methodName,
                                                     parameterTypes);
            if (method != null)
                break;

        }

        // Return whatever we have found
        if (method != null) System.out.println("Found method!");
        return (method);

    }






--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: Possible bug: Present Struts 1.0 PropertyUtils introspection code bonks on the variety of Tomcat 4 ServletRequest facades that get handed to us as HttpServletRequest

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Tue, 8 Jan 2002, James Dasher wrote:

> Date: Tue, 8 Jan 2002 13:18:44 -0500
> From: James Dasher <jf...@thermopylae.com>
> Reply-To: Struts Developers List <st...@jakarta.apache.org>
> To: struts-dev@jakarta.apache.org
> Subject: Possible bug: Present Struts 1.0 PropertyUtils introspection
>     code bonks on the variety of Tomcat 4 ServletRequest facades that get
>     handed to us as HttpServletRequest
>
> Whoever thought of <bean:page>, I love it, but it exposes some weird
> introspection inconsistencies in the Tomcat container, and I am out of
> my depth.  Help.
>

Are you using the 1.0 release of Struts?  If so, you will indeed have
introspection issues.

> I have seen two classes that get thrown up as HttpServletRequests to the
> container.
>
> org.apache.catalina.connector.HttpRequestFacade
> org.apache.catalina.core.ApplicationHttpRequest
>

The difference comes from whether your page is accessed directly (you'll
see the first of these) or via a request dispatcher (the second case).

In either case, you should be able to introspect to all public properties.
However, the BeanUtils code that was included in the 1.0 release did have
problems introspecting the public methods that are declared in an
interface (HttpServletRequest) rather than the class itself.  This has
been corrected in the nightly builds (which use the Commons version of
BeanUtils).  Could you give that a try to see if it sovles your problem?

Craig


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>