Daniel Bleisteiner
Daniel Bleisteiner

Reputation: 3320

Is it possible to use Seam in a JBoss timed service?

I've started to write some new JBoss timed service that was meant to use some existing seam components. But it seems that I can't access these components because of non-existing contexts. Is it possible to use them other than in the typical situation with JSF?

A little snippet to demonstrate what I want to do...

@Service
public class MyService extends DefaultTimedService implements TimedObject, DefaultServiceInterface {
    @Timeout
    public void ejbTimeout(Timer timer) {
        MyInterface loader = (MyInterface) Component.getInstance(MyInterface.SEAM_NAME, true);
        // throws no context!
    }
}

That throws the following exception for example:

java.lang.IllegalStateException: No application context active
    at org.jboss.seam.Component.forName(Component.java:1945)
    at org.jboss.seam.Component.getInstance(Component.java:2005)

Upvotes: 4

Views: 2602

Answers (3)

Bobby
Bobby

Reputation: 1611

There is one way that is a little dirty and there are many developers that would not use such a hack ever but it will solve your problem:

import org.jboss.seam.contexts.Lifecycle;

@Service
public class MyService extends DefaultTimedService implements TimedObject, DefaultServiceInterface {
    @Timeout
    public void ejbTimeout(Timer timer) {
        Lifecycle.beginCall();

        MyInterface loader = (MyInterface) Component.getInstance(MyInterface.SEAM_NAME, true);
        // will not throw no context!
        // also the Component.getInstance(MyInterface.SEAM_NAME, true,true); call
        // is another way you could inject that component. 

        Lifecycle.endCall();
    }
}

I have used it in one project where I couldn't find anything else that worked. If anybody has another solution I am looking forward to seeing it here :).

Upvotes: 7

Bozho
Bozho

Reputation: 597224

Can't you inject the loader instance, instead of of locating it with that static call? I'm not quite familiar with Seam, but perhaps (in the class body):

@In private MyInterface loader;

and then, in your method, just use the loader.

As it seems, Seam has the application /statelesss scopes, which seems the appropriate one in your case:

@Scope(ScopeType.APPLICATION)

or

@Scope(ScopeType.STATELESS)

Try one of those - since your class doesn't seem to need any information from the session/request, it's more appropriate not to use a web-related scope.

So define MyService and MyInterface in one of the above scopes, and try both injection and your lookup method.

Check the Seam tutorial on contexts and concurrency

This thread seems helpful.

And from this thread it seems there is an @Asynchronous annotation, that you might use.

Upvotes: 1

Aleksi Yrttiaho
Aleksi Yrttiaho

Reputation: 8446

What scope have you defined for the component? Probably application context as it says so in the error.

...

So I poked around the source and found out that contexts are stored in a class named Contexts. All contexts seems to be thread specific, because they are encapsulated in ThreadLocal-instances. That means that has to specified for thread of the timed service...

The question remains though: how do create a context for a specific thread.

Upvotes: 1

Related Questions