10 Replies Latest reply on Apr 14, 2008 1:49 PM by Daniel Roth

    Injection and threads

    Nicklas Karlsson Master

      There is a gap in my understanding of Threads and injection so there is probably a natural explanation for this but:


      Is there any way around the case where I have a managed bean with injections. In the same class I would like to kick off a thread (private class) doing some work but when the run method is executed, all injections are null?

        • 1. Re: Injection and threads
          Daniel Roth Apprentice

          I have noticed that too... so I use @Async and Event+Observer to achieve the same behavior, but I guess it depend quite a lot on your use case.

          • 2. Re: Injection and threads
            Nicklas Karlsson Master

            Yes, but you won't have injections or contexts in asynchronous methods(?)

            • 3. Re: Injection and threads
              Nicklas Karlsson Master

              Is it somehow possible to set up the seam contexts yourself manually in the separate thread so you can then call Component.getInstance?

              • 4. Re: Injection and threads
                Daniel Roth Apprentice

                You will have injections. Context I don't know, but the relevant data can be sent with the async call. If you have the cid, maybe you could (I'm guessing) send it with the async call and get the context from there...


                If async methods do database stuff, thay need to be @Transactional/@TransactionAttribute I have noticed, the hard way :)

                • 5. Re: Injection and threads
                  Nicklas Karlsson Master

                  The manual speaketh, saying


                  "
                  The asynchronous method is processed in a completely new event context and does not have access to the session or conversation context state of the caller
                  "


                  so I will have to see what I end up with. The actual usage scenario is for an ICEFaces progress bar. I have to activate the progress bar and kick off the work in another thread (disabling the progress bar when it's done) to have it re-render correctly.


                  I'll see if the trick can be accomplished with asynchronous events or something...

                  • 6. Re: Injection and threads
                    Pete Muir Master

                    As Daniel says, you should use an asynchronous event/method for this as it causes the call to be executed inside Seam's contexts.


                    Why are you not thinking of doing this?

                    • 7. Re: Injection and threads
                      Nicklas Karlsson Master

                      I am now ;-)


                      I was thrown off by the last statement in section 18.1.3 that stated


                      "
                      Component-driven events may also be asynchronous. To raise an event for asynchronous processing, simply call the raiseAsynchronousEvent() method of the Events class. To schedule a timed event, call the raiseTimedEvent() method, passing a schedule object (for the default dispatcher or timer service dispatcher, use TimerSchedule). Components may observe asynchronous events in the usual way, but remember that only the business process context is propagated to the asynchronous thread.
                      "


                      and lead me to believe that there would be no injections

                      • 8. Re: Injection and threads
                        Nicklas Karlsson Master

                        But actually trying it reveals no injections for observer to asynchronous methods so back to square one :-/

                        • 9. Re: Injection and threads
                          Nicklas Karlsson Master

                          "This new learning amazes me, Sir Roth. Explain again how sheep's bladders may be employed to prevent earthquakes."


                          In your action, do you raise an asynchronous event and @Observe and see the injected stuff there, do you have the asynchronous event raise a normal event or how did your setup look like?

                          • 10. Re: Injection and threads
                            Daniel Roth Apprentice

                            Since I had a sample project up (yeah, I'll guess you'll recognize it), I modified it for a nice sample:


                            @Name("startup")
                            @Scope(ScopeType.APPLICATION)
                            @org.jboss.seam.annotations.Startup
                            public class Startup {
                            
                                @In
                                private StartupTest startupTest;
                            
                                @Create
                                public void create() {
                                    startupTest.run(new Date(new Date().getTime() + 5000)); // 5 sec.
                                }
                                
                                @Observer("lojtest")
                                public void lojtest() {
                                    if(startupTest==null)
                                        System.out.println("startupTest is null");
                                    else
                                        System.out.println("startupTest is NOT null");
                                        
                                }
                            
                            }
                            



                            @Name("startupTest")
                            @Scope(ScopeType.APPLICATION)
                            @AutoCreate
                            public class StartupTest {
                            
                                @In
                                private Startup startup;
                            
                                public StartupTest() {
                                    System.out.println();
                                }
                            
                                @Asynchronous
                                public void run(@Expiration
                                Date date) {
                                    System.out.println("I'm here");
                                    Events.instance().raiseAsynchronousEvent("lojtest", new Object[0]);
                            
                                }
                            
                            }
                            



                            This works as one really would like, with all fields correctly injected...