Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] WAR overlays in Jetty 9.1?

Hi Klaus,

I've made some more mods to Jetty - this time to make sure that
ServletContainerInitializers are definitely going to be called before
any injection happens on any listeners.

I've also implemented a ServletContainerInitializer that does the same
thing as the org.jboss.weld.environment.servlet.Listener to set up the
weld framework. Using it, I can definitely get your test context
listener injected just fine:

2013-12-13 16:07:03.785:INFO:oejs.Server:main: jetty-9.1.1-SNAPSHOT
Dec 13, 2013 4:07:03 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 2.2.0 (2013-12-13 12:20)
Dec 13, 2013 4:07:04 PM
org.jboss.weld.environment.servlet.WeldServletContainerInitializer
onStartup
INFO: WeldServletContainerInitializer onStartup called
Dec 13, 2013 4:07:04 PM org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of
@Inject UserTransaction not available. Transactional observers will be
invoked synchronously.
Dec 13, 2013 4:07:04 PM
org.jboss.weld.environment.jetty.JettyContainer initialize
INFO: Jetty 7.2+ detected, CDI injection will be available in
Listeners, Servlets and Filters.
Dec 13, 2013 4:07:04 PM
org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate
not found, interception based on it is not enabled
Dec 13, 2013 4:07:04 PM
org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate
not found, interception based on it is not enabled
1st POST CONSTRUCT ON LISTENER CALLED test.ContextListener@6b66187b
Dec 13, 2013 4:07:05 PM
org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener
contextInitialized
INFO: BeanManager reference bound to java:comp/env/BeanManager
2013-12-13 16:07:05.147:INFO:oejsh.ContextHandler:main: Started
o.e.j.m.p.JettyWebAppContext@63fd1f47{/,file:/home/janb/src/tmp/bug-423361/cditest/src/main/webapp/,AVAILABLE}{file:/home/janb/src/tmp/bug-423361/cditest/src/main/webapp/}
2013-12-13 16:07:05.148:WARN:oejsh.RequestLogHandler:main: !RequestLog
2013-12-13 16:07:05.168:INFO:oejs.ServerConnector:main: Started
ServerConnector@5eb7c06f{HTTP/1.1}{0.0.0.0:8080}
[INFO] Started Jetty Server

Here's the link to the repo I did the Weld changes in:
https://github.com/jetty-project/weld-core
I have opened a pull request on the Weld project for it:
https://github.com/weld/core/pull/435

If you want to test this, then clone my weld repo, build it. Then
update and build your jetty repo. In your cditest application, take
out the org.jboss.weld.environment.servlet.Listener from your web.xml,
as jetty will find the weld ServletContainerInitializer automatically.

cheers
Jan

On 13 December 2013 10:36, Jan Bartel <janb@xxxxxxxxxxx> wrote:
> Hi Klaus,
>
> There's something pretty funky going on in your environment ;)  The
> @WebListener handler has code in there to check to see if the class
> that it is on has already been defined somewhere else (eg web.xml) and
> it does not create another instance if so (see
> https://github.com/eclipse/jetty.project/blob/master/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java#L89).
>  In my own testing by modifying your cditest webapp, I have kept the
> @WebListener annotation on test.ContextListener and also the
> definition in web.xml and I only see 1 output of the @PostConstruct (I
> added a debug line in the @WebListener handler that shows the check
> for the duplicate class name, which in this case is found in web.xml):
>
> janb@smidge: ~/src/jetty-eclipse/jetty-9/jetty-distribution/target/distribution/demo-base
> (master)
> [2139] java -jar ../start.jar
> 2013-12-13 09:24:26.203:WARN::main: demo test-realm is deployed. DO
> NOT USE IN PRODUCTION!
> 2013-12-13 09:24:26.207:INFO:oejs.Server:main: jetty-9.1.1-SNAPSHOT
> 2013-12-13 09:24:26.227:INFO:oejdp.ScanningAppProvider:main:
> Deployment monitor
> [file:/home/janb/src/jetty-eclipse/jetty-9/jetty-distribution/target/distribution/demo-base/webapps/]
> at interval 1
> Dec 13, 2013 9:24:26 AM org.jboss.weld.bootstrap.WeldStartup <clinit>
> INFO: WELD-000900: 2.1.0 (Final)
> @WebListener checking for existing definition for test.ContextListener:WebXml
> POST CONSTRUCT ON LISTENER CALLED test.ContextListener@42538425
> Dec 13, 2013 9:24:27 AM
> org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener
> contextInitialized
> INFO: BeanManager reference bound to java:comp/env/BeanManager
> Dec 13, 2013 9:24:27 AM org.jboss.weld.bootstrap.WeldStartup startContainer
> INFO: WELD-000101: Transactional services not available. Injection of
> @Inject UserTransaction not available. Transactional observers will be
> invoked synchronously.
> Dec 13, 2013 9:24:27 AM
> org.jboss.weld.environment.jetty.JettyContainer initialize
> INFO: Jetty 7.2+ detected, CDI injection will be available in
> Listeners, Servlets and Filters.
> Dec 13, 2013 9:24:27 AM
> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
> WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate
> not found, interception based on it is not enabled
> Dec 13, 2013 9:24:27 AM
> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
> WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate
> not found, interception based on it is not enabled
> ugh! injection into test.ContextListener failed!
> 2013-12-13 09:24:27.738:WARN:oejuc.AbstractLifeCycle:main: FAILED
> o.e.j.w.WebAppContext@11de0733{/cditest,file:/tmp/jetty-0.0.0.0-8080-cditest.war-_cditest-any-5944617847214306307.dir/webapp/,STARTING}{/cditest.war}:
> java.lang.AbstractMethodError:
> org.jboss.weld.environment.jetty.WeldDecorator.decorate(Ljava/lang/Object;)Ljava/lang/Object;
>
>
> So I don't know how there could be 2 instances of the same listener,
> one from the @WebListener and one from web.xml. Maybe add a new
> Throwable().printStackTrace() in a constructor for the
> test.ContextListener class and see who is calling it?
>
> Similarly, I couldn't immediately see how there could be 2
> PostConstruct callbacks for the same instance - then I added 2 methods
> annotated with @PostConstruct to see if that made a difference. I
> confirmed that Jetty will only call one of them if there are 2 methods
> in the same class annotated with @PostConstruct. Then I noticed this:
>
> org.jboss.weld.exceptions.DefinitionException: WELD-000805: Cannot
> have more than one post construct method annotated with @PostConstruct
> for [EnhancedAnnotatedTypeImpl] public @WebListener class
> test.ContextListener
>
> So it looks like Weld might be responsible for the 2nd calling of the
> @PostConstruct callback you are experiencing - again, could you add a
> new Throwable().printStackTrace() into that method call so we can see
> who is calling it? If you can confirm that for me, then the Jetty/Weld
> integration will need to be more fine-grained that it is at the
> moment.
>
> In any case, the Jetty/Weld integration needs work. The changes that I
> made to Jetty ensure that
> org.eclipse.jetty.servlet.ServletContextHandler.Decorator instances
> are called on all Listeners just before any methods on any listeners
> are called. Before, the Decorators were called immediately the
> Listener was discovered, so my changes have had the effect of delaying
> the application of the Decorators, allowing a lot more scope for extra
> Decorators to be added etc. I must admit I got so focussed on getting
> this delayed call to the Decorators working that I forgot the
> observation I made 6 days ago about Weld's integration with Jetty:
>
>>However, I have to say that weld's current jetty integration isn't
>>going to be able to inject a Listener because they are hooking into
>>the deployment lifecycle too late. Their implementation sets up a
>>ServletContextListener that decides which container it has been
>>deployed into on the call to contextInitialized(), and then goes on to
>>do some container-specific setup. That's too late to be able to inject
>>a listener, as the listeners are clearly already being called back
>>during their startup sequence!  Jetty injects listeners just after
>>they are created.
>
> So, even though I've delayed the injection of listeners until just
> before they will be called back,  the basic problem still stands: once
> the ServletContextListeners have started to be called back, it is way
> too late to try to execute code that should affect listeners (ie
> inject them).
>
> The approach that will work is to make the Weld/jetty integration a
> ServletContainerInitializer. They are guaranteed to be called back
> before any application code, and can thus do whatever setup is
> necessary. Even better, with Jetty we can guarantee the order that
> ServletContainerInitializers are called - which is not something the
> spec addresses - so we can ensure that the Weld SCI is the first to be
> called. I will look into the existing
> org.jboss.weld.environment.servlet.Listener and see if I can come up
> with some code as a SCI instead.
>
> So to sum up, can you do a fresh git pull on the jetty repo and full
> build to make sure you've got the latest code, and then put in those
> new Throwable().printStackTrace() calls where I suggested and report
> back your findings? Meanwhile, I'll investigate turning the Weld
> Listener in to a Weld ServletContainerInitializer.
>
> cheers
> Jan
>
> On 13 December 2013 00:59, Klaus Brunner <klaus.brunner@xxxxxxxxx> wrote:
>> 2013/12/12 Jan Bartel <janb@xxxxxxxxxxx>:
>>> The method annotated with @PostConstruct will be called back by the
>>> org.eclipse.jetty.plus.webapp.PlusDecorator.  If you see the output,
>>> then jetty's Decorator mechanism is working fine for  listeners. As I
>>> understand it, Weld adds in another Decorator to do its magic, so this
>>> test will at least confirm that Decorators are being called. If you
>>> see the output, then there must be something else in Weld that is not
>>> working for listeners.
>>
>> The postConstruct is duly called, but that's before the whole
>> Jetty/Weld integration code is ever run (which is bootstrapped using
>> their own listeners):
>>
>> klaus@klaus-dellnb:/opt/jetty-distribution-9.1.1-SNAPSHOT$ java -jar start.jar
>> 2013-12-12 14:38:43.418:INFO:oejs.Server:main: jetty-9.1.1-SNAPSHOT
>> 2013-12-12 14:38:43.446:INFO:oejdp.ScanningAppProvider:main:
>> Deployment monitor
>> [file:/opt/jetty-distribution-9.1.1-SNAPSHOT/webapps/] at interval 1
>> Dec 12, 2013 2:38:43 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
>> INFO: WELD-000900: 2.2.0 (2013-12-05 14:19)
>> POST CONSTRUCT ON LISTENER CALLED test.ContextListener@744f45c
>> Dec 12, 2013 2:38:44 PM
>> org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener
>> contextInitialized
>> INFO: BeanManager reference bound to java:comp/env/BeanManager
>> Dec 12, 2013 2:38:44 PM org.jboss.weld.bootstrap.WeldStartup startContainer
>> INFO: WELD-000101: Transactional services not available. Injection of
>> @Inject UserTransaction not available. Transactional observers will be
>> invoked synchronously.
>> Dec 12, 2013 2:38:44 PM
>> org.jboss.weld.environment.jetty.JettyContainer initialize
>> INFO: Jetty 7.2+ detected, CDI injection will be available in
>> Listeners, Servlets and Filters.
>> Dec 12, 2013 2:38:45 PM
>> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
>> WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate
>> not found, interception based on it is not enabled
>> Dec 12, 2013 2:38:45 PM
>> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
>> WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate
>> not found, interception based on it is not enabled
>> ugh! injection into test.ContextListener failed!
>>
>> My understanding is that the Weld bootstrapping code should be
>> executed before my own Listener is even instantiated (or at least
>> immediately after that) so that injection can take place, but I have
>> no idea how such ordering could be ensured in Jetty.
>>
>> BTW, I noticed that if I have my ContextListener both annotated as a
>> WebListener *and* referenced in the web.xml, postConstruct is called
>> several times (twice on the same instance apparently, and once on
>> another instance). This seems to be a bug, or at least it's not what
>> I'd expect:
>>
>> 2013-12-12 13:12:43.300:INFO:oejdp.ScanningAppProvider:main:
>> Deployment monitor
>> [file:/opt/jetty-distribution-9.1.1-SNAPSHOT/webapps/] at interval 1
>> Dec 12, 2013 1:12:43 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
>> INFO: WELD-000900: 2.2.0 (2013-12-05 14:19)
>> POST CONSTRUCT ON LISTENER CALLED test.ContextListener@4bd38cb3
>> POST CONSTRUCT ON LISTENER CALLED test.ContextListener@744f45c
>> POST CONSTRUCT ON LISTENER CALLED test.ContextListener@744f45c
>> Dec 12, 2013 1:12:44 PM
>> org.jboss.weld.environment.servlet.BeanManagerResourceBindingListener
>> contextInitialized
>> INFO: BeanManager reference bound to java:comp/env/BeanManager
>> Dec 12, 2013 1:12:44 PM org.jboss.weld.bootstrap.WeldStartup startContainer
>> INFO: WELD-000101: Transactional services not available. Injection of
>> @Inject UserTransaction not available. Transactional observers will be
>> invoked synchronously.
>> Dec 12, 2013 1:12:44 PM
>> org.jboss.weld.environment.jetty.JettyContainer initialize
>> INFO: Jetty 7.2+ detected, CDI injection will be available in
>> Listeners, Servlets and Filters.
>> Dec 12, 2013 1:12:44 PM
>> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
>> WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate
>> not found, interception based on it is not enabled
>> Dec 12, 2013 1:12:44 PM
>> org.jboss.weld.interceptor.util.InterceptionTypeRegistry <clinit>
>> WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate
>> not found, interception based on it is not enabled
>> ugh! injection into test.ContextListener failed!
>>
>>
>> Klaus
>> _______________________________________________
>> jetty-users mailing list
>> jetty-users@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/jetty-users
>
>
>
> --
> Jan Bartel <janb@xxxxxxxxxxx>
> www.webtide.com
> 'Expert Jetty/CometD developer,production,operations advice'



-- 
Jan Bartel <janb@xxxxxxxxxxx>
www.webtide.com
'Expert Jetty/CometD developer,production,operations advice'


Back to the top