tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Jencks <david_jen...@yahoo.com>
Subject Re: AsyncListeners and resource injection
Date Thu, 16 Sep 2010 20:26:29 GMT

On Sep 15, 2010, at 10:51 PM, David Jencks wrote:

> 
> On Sep 15, 2010, at 9:58 PM, David Jencks wrote:
> 
>> I think this is how AsyncContextImpl creates async listeners (lines 228ff)
>> 
>>   @Override
>>   public <T extends AsyncListener> T createListener(Class<T> clazz)
>>           throws ServletException {
>>       T listener = null;
>>       try {
>>            listener = clazz.newInstance();
>>       } catch (InstantiationException e) {
>>           ServletException se = new ServletException(e);
>>           throw se;
>>       } catch (IllegalAccessException e) {
>>           ServletException se = new ServletException(e);
>>           throw se;
>>       }
>>       return listener;
>>   }
>> 
>> 
>> 
>> but the 3.0 spec section 15.5 page 179 says
>> 
>> Annotations must be supported on the following container managed classes that implement
the following interfaces and are declared in the web application deployment descriptor or
using the annotations defined in Section 8.1, “Annotations and pluggability” on page 8-61
or added programmatically.
>> 
>> and includes AsyncListener in the table following.  
>> 
>> So shouldn't this be using the instance manager to create the instance so the resource
injection machinery can do its stuff?
>> 
>> 
>> Secondly, if you do try to register an AsyncListener with  the ServletContext so
it can be scanned for annotations, aside from not actually scanning it, it quickly gets to
this code (ApplicationContext lines 1262 ff)
>> 
>>   @Override
>>   public <T extends EventListener> void addListener(T t) {
>>       if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
>>           throw new IllegalStateException(
>>                   sm.getString("applicationContext.addListener.ise",
>>                           getContextPath()));
>>       }
>> 
>>       // TODO SERVLET3
>>       // throw UnsupportedOperationException - if this context was passed to the
>>       // {@link ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)}
>>       // method of a {@link ServletContextListener} that was not declared
>>       // in web.xml, a web-fragment or annotated with {@link WebListener}.
>> 
>>       boolean match = false;
>>       if (t instanceof ServletContextAttributeListener ||
>>               t instanceof ServletRequestListener ||
>>               t instanceof ServletRequestAttributeListener ||
>>               t instanceof HttpSessionAttributeListener) {
>>           context.addApplicationEventListener(t);
>>           match = true;
>>       }
>> 
>>       if (t instanceof HttpSessionListener
>>               || (t instanceof ServletContextListener &&
>>                       newServletContextListenerAllowed)) {
>>           context.addApplicationLifecycleListener(t);
>>           match = true;
>>       }
>> 
>>       if (match) return;
>> 
>>       throw new IllegalArgumentException(sm.getString(
>>               "applicationContext.addListener.iae.wrongType",
>>               t.getClass().getName()));
>> 
>>   }
>> 
>> 
>> which doesn't accept AsyncListeners.  (of course it shouldn't do anything with then).
>> 
>> Thoughts?
>> 
>> thanks
>> david jencks
>> 
> 
> BTW I opened bug 49937 with  fixes that work for me for these problems.
> 
> david jencks
> 

The situation seems to be more complicated than I thought at first.

As noted above, section 15.5 clearly indicates annotation based resource injection is supported
for all servlet related listeners including AsyncListener, and that these can be specified
in the xml deployment descriptor, via annotation, or by adding programatically.

However.... 

4.4.3 indicates that an AsyncListener cannot be added programatically

4.4.3.5 indicates that resource injection is not supported for listeners added programatically
unless the listener is a managed bean.  I think this directly contradicts 15.5.

8.1.4 indicates that an AsyncListener cannot be annotated with @WebListener

11.3.2 says

Listener classes are declared in the Web application deployment descriptor using the listener
element. They are listed by class name in the order in which they are to be invoked. Unlike
other listeners, listeners of type AsyncListener may only be registered (with a ServletRequest)
programmatically.

I can't figure out what this is supposed to mean.  It might mean that you aren't allowed to
list an AsyncListener in your web.xml, or it might mean that you can, but to use it you have
to explicitly add it to an AsyncContext.

Despite the contradictions in the spec, it seems pretty clear that an asyncListener can be
a managed bean and thus be subject to resource injection.  It might also be possible for it
to be listed in web.xml, have a @WebListener annotation, and be "added" programatically so
it can be scanned for normal ee resource injection annotations (depending on how much weight
you put on 15.5 compared with the other sections).  So, I think that the AsyncContext.createListener
method should use the instance manager in any case.  I think it makes sense to relax the restrictions
on @WebListener and programatically adding AsyncListeners as well (i.e. giving priority to
15.5 rather than all the other sections) since it doesn't break anything and is more powerful.

thanks
david jencks


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


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


Mime
View raw message