I don't know why you couldn't just pass the proxy, and just throw
IllegalOperationExceptions for unrecognized methods. But this one may
be a bit cleaner. Don't know.
Sent from my iPhone
On Dec 1, 2009, at 6:21 PM, Bernhard Huemer
<bernhard.hue...@gmail.com> 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