6 Replies Latest reply: Feb 8, 2012 12:21 PM by fvitorc RSS

SessionContext and LocalContext within RPC

fvitorc Newbie

Hi,

 

I've seen in the reference guide that one can get the SessionContext or the LocalContext using the Message object.

But in a RPC there is no Message object. How can we get access to those contexts within a RPC?

 

Regards,

Vitor.

  • 1. Re: SessionContext and LocalContext within RPC
    Christian Sadilek Master

    I assume your use case for this is to get access to the HTTP session? I have created a JIRA for this a while back: https://issues.jboss.org/browse/ERRAI-157

     

    If it's for the session object, you could add a servlet filter and store the object in a ThreadLocal, given you use the SimpleDispatcher.

  • 2. Re: SessionContext and LocalContext within RPC
    fvitorc Newbie

    Not actually. I wanted acess to the queue id of the client invoking the RPC. I guess that information is in LocalContext right?

    I just put SessionContext in this discussion because those are the contexts provided by errai, so that would be a helpful information.

     

    Anyway, does errai have acess to the Message object just before invoking the RPC?

    I assume it does, and so, it would be possible to store the Message object in a ThreadLocal.

    Then from the RPC we can grab it, and access LocalContext and SessionContext.

     

    Regards,

    Vitor.

  • 3. Re: SessionContext and LocalContext within RPC
    Christian Sadilek Master

    There's currently no API you could use to get access to the message from within an RPC endpoint. Can you elaborate on the feature you want to implement? Maybe we can come up with an alternative.

  • 4. Re: SessionContext and LocalContext within RPC
    fvitorc Newbie

    Ok, so the first thing that comes into my mind in this situation is to use a ThreadLocal. Let me try to show a simple and ugly way to do this.

    As I've seen from the source code, RPCs are initiated from class ConversationalEndpointCallback, correct?

     

    Let's add ThreadLocal to it:

     

    private static ThreadLocal<Message> currentMessage = new ThreadLocal<Message>();

     

    public static Message getCurrentMessage() {

        return currentMessage.get();

    }

     

    and right before the createConversation(message) statement, in the beginning of the try block, place this statement:

    try {

        currentMessage.set(message);

        createConversation(message)

         ....

     

    and create a finally block to the above try block like this:

    ...

    finally {

        currentMessage.remove();

    }

     

    Now, in our RPC service, we access the current message object using ConversationEndpointCallback.getCurrentMessage();

    It's ugly but it works. So let's make it look nice. We can use resource injection for that.

     

    First, let's make getCurrentMessage() protected, so that only classes in the same package can access it.

    protected static Message getCurrentMessage() {

        return currentMessage.get();

    }

     

    Now, create an extension component in the same package as ConversationalEndpointCallback that will add bindings to a resource provider:

     

    @ExtensionComponent

    public class MessageAccessorExtension implements ErraiConfigExtension {

        @Override

        public void configure(ErraiConfig config) {

            config.addBinding(Message.class, new ResourceProvider<Message>() {

                @Override

                public Message get() {

                    return ConversationalEndpointCallback.getCurrentMessage();

                }

            });

        }

    }

     

    That's it. Now we add a provider to our RPC service and access the Message object through this provider:

     

    @Service

    public class MyServiceImpl implements MyService {

     

        @Inject

        private Provider<Message> message;

     

        @Override

         public void doYourWork() {

             Message m = message.get();

        }

     

    }

     

    It would also be possible to add more bindings to simplify access of commonly used objects in RPC services, like:

     

    @Override

    public LocalContext get() {

        Message m = ConversationalEndpointCallback.getCurrentMessage();

        return LocalContext.get(m);

    }

    @Override

    public SessionContext get() {

        Message m = ConversationalEndpointCallback.getCurrentMessage();

        return SessionContext.get(m);

    }

     

     

    What do you think of this solution?

     

    Regards,

    Vitor.

  • 5. Re: SessionContext and LocalContext within RPC
    Christian Sadilek Master

    Nice! I think your solution would work. However, it seems there's an opportunity for us to provide a higher level abstraction for what you are trying to do. What is your exact use case for this? To identify the client? I am thinking we could make a provider for the context itself which could then be injected.

  • 6. Re: SessionContext and LocalContext within RPC
    fvitorc Newbie

    Yes, I need to identify the client. What I need is a list of all users currently logged in, along with their respective queue id. There's no specific need for the Message object. But I know that with it I can get the LocalContext of the currently running RPC.

     

    Think of it as chat application (it's a little more complex than a chat application, but it serves as an example). When a user logs in, I register that user as logged in along with his queue id in a application scoped variable. So, if user A wants to send a private message to user B, I get the user B from the application scoped variable along with his queue id. With his queue id, it's now possible to send a message directly to user B.

     

    I can use my hack for the moment, but I am looking forward to see this feature in future releases.

     

    I've recently opened up another discussion about detecting user presence, because I need to know when a queue has been started or finished. But I still have no response for that.

     

    Regards,

    Vitor.