myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Concini <>
Subject Re: [MyFaces 2.0] how to handle _SystemEventServletRequest and _SystemEventServletResponse classes (attn:Werner)
Date Wed, 02 Dec 2009 05:32:14 GMT
Thanks for the thorough analysis Bernhard.  Sounds like the 2nd option 
that I and others were leaning towards won't work out.  Based on this, 
and assuming there are no objections from the community, I'll work on a 
a fix using your recommendations below.

Bernhard Huemer wrote:
> Hello,
> regarding the 1st solution:
> According to the JavaDocs the ServletRequestWrapper throws an 
> IllegalArgumentException if you pass "null" as delegate, so this won't 
> work (I'll come back to that later though). However, given that you're 
> worried about NullPointerExceptions in case someone calls methods that 
> have been introduced in the Servlet 3.0 version release, I assume that 
> MyFaces isn't really concerned about those methods anyway. Otherwise 
> you'd probably override those methods? If I'm mistaken, please correct 
> me as some suggestions later on rely on this assumption.
> regarding the 2nd solution:
> Just ignoring the @Override annotation won't work as the respective 
> interfaces introduce dependencies to artifacts that are only available 
> in a Servlet 3.0 environment (for example, there's the startAsync() 
> method that returns an AsyncContext). If a class loader were to load 
> your request / response dummy class, he would now also have to load 
> the class AsyncContext as it's a dependency of your class itself, 
> which apparently the class loader cannot do in a Servlet 2.5 environment.
> Given that I'd say you'll have to create two different dummy 
> implementations, one that implements the Servlet 2.5 ServletRequest 
> interface and one that implements the Servlet 3.0 ServletRequest (i.e. 
> the only thing that changes is the set of methods you have to 
> implement). However, now another problem arises as you can't just use 
> two different versions of the same API in a single build, i.e. there's 
> no way to tell the compiler that one class just implements the methods 
> in the Servlet 2.5 version whereas another class has to implement the 
> methods of the Servlet 3.0 version. Both versions have to be 
> compilable using the same Servlet API version and as the Servlet 2.5 
> API is just a subset of the Servlet 3.0 API, both versions have to be 
> compilable using the Servlet 3.0 version.
> The big issue now is that we've got a contradiction now. If we want to 
> support a Servlet 3.0 environment, we'll have to use this version in 
> our build (again, Servlet 3.0 is if I'm not mistaken a superset of 
> Servlet 2.5, that's the reason for that). However, the 2.5 version of 
> the dummy class cannot compile if one uses the 3.0 version for the 
> actual build. Maybe that sounds a little bit strange up until now, but 
> hopefully now it will get clearer: A 2.5 compatible implementation of 
> the ServletRequest interface must not implement the method 
> "startAsync" as it introduces an unsatisfiable dependency, but a 3.0 
> compatible build environment requires any implementation to implement 
> the method "startAsync" (amongs others) as it is a part of the 
> interface after all.
> Hence I'm afraid but this solution just won't work either. Of course, 
> the third solution would probably work, but why bother about the 
> performance implications if there's another solution? :-)
> I think the preferable solution is actually the first one. It's easy 
> to  implement as we don't have to deal with the difference between the 
> Servlet 2.5 API and Servlet 3.0 API, but as I've already mentioned 
> there is the IllegalArgumentException issue that you just can't ignore 
> either. We just want to get rid of the null value somehow, so why not 
> use a dummy proxy instead? Note that there are no performance 
> implications if you override the wrapped methods anyway, i.e. in fact, 
> the proxy won't be called even once. It's sole purpose is to replace 
> the "null", that's it. It could look like the following:
> ///
> public class DummyServletRequest extends ServletRequestWrapper {
>   public DummyServletRequest() {
>     super(Proxy.newProxyInstance(
>       DummyServletRequest.class.getClassLoader(),
>       new Class[] { ServletRequest.class },
>       new InvocationHandler() {
>         public Object invoke(Object proxy, Method m, Object[] args) {
>           throw new UnsupportedOperationException(...);
>         }
>       }
>     );
>   }
>   // --------- "Implement" the interface ServletRequest now!
>   public Object getAttribute(String name) {
>     // ...
>   }
>   // ...
> }
> \\\
> Hope that helps. :-)
> regards,
> Bernhard Huemer
> On 12/01/2009 09:48PM GMT, Michael Concini wrote:
>> I need some help with the best way to handle updating the dummy 
>> request/response objects that we use for system event listeners 
>> kicked off when there isn't a request context.  Currently, we're 
>> implementing ServletRequest and ServletResponse directly.  This is 
>> broken when using a servlet 3.0 runtime though since we're not 
>> implementing the new methods added by the servlet 3.0 spec.
>> I tried already updating the classes to extend the request/response 
>> wrapper classes, but that turned out to be problematic since the 
>> constructor requires a request/response object to be passed.  Since 
>> we don't have access to that as we're outside of a request I hit an 
>> NPE try to use FacesContext that wasn't there.
>> I've come up with a couple of potential solutions on this and would 
>> like some input as to the best way to go.
>> 1) We could also extend the wrapper classes, but add a no-arg 
>> constructor to the dummy classes that would just call super(null).  
>> This would be fine in most cases, but if an application tried to call 
>> any of the new ServletContext methods from Servlet 3.0 we'd get an 
>> NPE instead of a runtime exception (not ideal)
>> 2) We can simply add the new methods from the Servlet 3.0 API to our 
>> dummy classes.  I think as long as we don't include the @Override 
>> annotation it should build and run in either a 2.5 or 3.0 environment.
>> 3) We could implement a dynamic proxy to handle the calls.  Would be 
>> a little more complex to implement, but might be the most elegant 
>> solution.  Not fully sure if there are performance implications here 
>> though.
>> Personally, I'd lean towards (2), I'd like to here from Werner as 
>> well since he was the one that initially implemented this.  Any 
>> additional feedback from others in the community is of course welcome.
>> Thanks,
>> Mike

View raw message