You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@activemq.apache.org by prgtrdr <pr...@gmail.com> on 2012/11/29 19:11:29 UTC

How can I retrieve a Stomp username when a new Connection is made?

I'm stuck on something that is probably obvious but I just can't figure out
how to do it.   

What I want to do is retrieve the userName from an incoming Stomp
connection.  I am creating the broker in my code and have also set up
monitoring Advisory messages.  The Advisory onMessage() function receives
the ConnectionInfo message but the userName and password are deleted from
the message, and the ConnectionInfo.getUserName() returns a null string. 

My guess is to get the userName I have to somehow lookup the Connection
object based on the ConnectionId contained in the Advisory ConnectionInfo
message, then I can get the userName from the Connection. 

Is that right?  Or is there an easier way?  If it's right, how do I lookup
the Connection object in the Advisory onMessage callback? 




--
View this message in context: http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by Christian Posta <ch...@gmail.com>.
Yah, I agree. The best way would be to have it properly exposed and used
that way. Which is what JMX does. Or, as Gary mentioned in another post(
http://activemq.2283324.n4.nabble.com/ActiveMQ-Advisory-Connection-messages-includes-username-and-password-td2365496.html),
maybe we should just change
http://issues.apache.org/activemq/browse/AMQ-2335 to not block out the
userName.

I've created https://issues.apache.org/jira/browse/AMQ-4198 for that. The
change is in trunk.


On Fri, Nov 30, 2012 at 4:10 AM, prgtrdr <pr...@gmail.com> wrote:

> Christian,
>
> Thanks for pointing me in the right direction.  Here's my code that seems
> to
> work so others can use it.  That said, I'm really nervous about using
> reflection to get at the brokerConnectionStates collection.  There must be
> a
> better way to do this...
>
>        @SuppressWarnings("unchecked")
>         public void onMessage(Message message){
>
>         if (message instanceof ActiveMQMessage) {
>             ActiveMQMessage activeMessage = (ActiveMQMessage) message;
>             Object command = activeMessage.getDataStructure();
>             if (command instanceof ConsumerInfo) {
>                 System.out.println("A consumer subscribed to a topic or
> queue: " + command);
>             } else if (command instanceof RemoveInfo) {
>                 RemoveInfo removeInfo = (RemoveInfo) command;
>                 if (removeInfo.isConsumerRemove()) {
>                     System.out.println("A consumer unsubscribed from a
> topic
> or queue");
>                 }
>                 else {
>                     System.out.println("RemoveInfo, a connection was
> closed:
> " + command);
>                 }
>             } else if (command instanceof ConnectionInfo) {
>                 //Retrieve this Connection so we can get the username and
> password
>                 TransportConnector connector =
> NeutroGate.broker.getConnectorByName("websocket");
>                 List<TransportConnection> connections =
> connector.getConnections();
>                 for (TransportConnection c : connections) {
>                         // use reflection to get at field
>                         Field f = null;
>                                         try {
>                                                 f =
> TransportConnection.class.getDeclaredField("brokerConnectionStates");
>                                         } catch (NoSuchFieldException |
> SecurityException e) {
>                                                 // TODO Auto-generated
> catch block
>                                                 e.printStackTrace();
>                                         }
>                         f.setAccessible(true);
>                         Map<ConnectionId, ConnectionState> context = null;
>                                         try {
>                                                 context =
> (Map<ConnectionId, ConnectionState>) f.get(c);
>                                         } catch (IllegalArgumentException
> | IllegalAccessException e) {
>                                                 // TODO Auto-generated
> catch block
>                                                 e.printStackTrace();
>                                         }
>                         ConnectionId commandCid = ((ConnectionInfo)
> command).getConnectionId();
>                         for (ConnectionId id : context.keySet()) {
>                         if (id.equals(commandCid)) {
>                                         String username =
> context.get(id).getInfo().getUserName();
>                                         String password =
> context.get(id).getInfo().getPassword();
>                                 System.out.println("ConnectionInfo, a new
> connection was made to " + username + ":" + password + ": " + command);
>
>                         }
>                         }
>                     }
>             } else {
>                 System.out.println("Unknown command: " + command);
>             }
>         }
>
>
>
>
> --
> View this message in context:
> http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4660019.html
> Sent from the ActiveMQ - User mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by prgtrdr <pr...@gmail.com>.
Christian,

Thanks for pointing me in the right direction.  Here's my code that seems to
work so others can use it.  That said, I'm really nervous about using
reflection to get at the brokerConnectionStates collection.  There must be a
better way to do this...

       @SuppressWarnings("unchecked")
	public void onMessage(Message message){
		
        if (message instanceof ActiveMQMessage) {
            ActiveMQMessage activeMessage = (ActiveMQMessage) message;
            Object command = activeMessage.getDataStructure();
            if (command instanceof ConsumerInfo) {
                System.out.println("A consumer subscribed to a topic or
queue: " + command);
            } else if (command instanceof RemoveInfo) {
                RemoveInfo removeInfo = (RemoveInfo) command;
                if (removeInfo.isConsumerRemove()) {
                    System.out.println("A consumer unsubscribed from a topic
or queue");
                }
                else {
                    System.out.println("RemoveInfo, a connection was closed:
" + command);
                }
            } else if (command instanceof ConnectionInfo) {
            	//Retrieve this Connection so we can get the username and
password
                TransportConnector connector =
NeutroGate.broker.getConnectorByName("websocket"); 
                List<TransportConnection> connections = 
connector.getConnections(); 
                for (TransportConnection c : connections) {
                	// use reflection to get at field 
                	Field f = null;
					try {
						f =
TransportConnection.class.getDeclaredField("brokerConnectionStates");
					} catch (NoSuchFieldException | SecurityException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} 
                	f.setAccessible(true); 
                	Map<ConnectionId, ConnectionState> context = null;
					try {
						context = (Map<ConnectionId, ConnectionState>) f.get(c);
					} catch (IllegalArgumentException | IllegalAccessException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
                	ConnectionId commandCid = ((ConnectionInfo)
command).getConnectionId();
                	for (ConnectionId id : context.keySet()) { 
                    	if (id.equals(commandCid)) {
	                		String username = 
context.get(id).getInfo().getUserName(); 
	                		String password = 
context.get(id).getInfo().getPassword(); 
	                        System.out.println("ConnectionInfo, a new
connection was made to " + username + ":" + password + ": " + command);

                    	}
                	}
 	            }
            } else {
            	System.out.println("Unknown command: " + command);
            }
        }




--
View this message in context: http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4660019.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by Christian Posta <ch...@gmail.com>.
Yah. You might be using nabble? I guess if you're sending it via email the
attachments don't show up.

I'll paste here:

package org.apache.activemq;

import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.TransportConnection;
import org.apache.activemq.broker.TransportConnector;
import org.apache.activemq.command.ConnectionId;
import org.apache.activemq.state.ConnectionState;
import org.apache.activemq.transport.stomp.Stomp;
import org.apache.activemq.transport.stomp.StompConnection;
import org.junit.Test;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author <a href="http://www.christianposta.com/blog">Christian Posta</a>
 */
public class GettingUserNameFromTransportConnectionTest {

    @Test
    public void testGetUserName() throws Exception {
        BrokerService service = new BrokerService();
        service.setUseJmx(true);
        service.addConnector("stomp://localhost:61613");
        service.setPopulateUserNameInMBeans(true);
        service.start();
        service.waitUntilStarted();

        // create a connection
        StompConnection connection = new StompConnection();
        connection.open("localhost", 61613);
        String connectFrame = "CONNECT\n" + "login:system\n" +
"passcode:manager\n" + "request-id:1\n" + "\n" + Stomp.NULL;
        connection.sendFrame(connectFrame);

        String response = connection.receiveFrame();
        System.out.println("STOMP response: " + response);
        TimeUnit.SECONDS.sleep(1);

        TransportConnector connector =
service.getConnectorByName("stomp://localhost:61613");
        List<TransportConnection> connections =  connector.getConnections();
        for (TransportConnection c : connections) {
//            if (c.getConnectionId().equals("some conn ID")) {
                // use reflection to get at field
            Field f =
TransportConnection.class.getDeclaredField("brokerConnectionStates");
            f.setAccessible(true);
            Map<ConnectionId, ConnectionState> context = (Map<ConnectionId,
ConnectionState>) f.get(c);
            for (ConnectionId id : context.keySet()) {
                String username =  context.get(id).getInfo().getUserName();
                System.out.println("User name: " + username);
            }
//            }
        }

    }
}



On Thu, Nov 29, 2012 at 2:07 PM, prgtrdr <pr...@gmail.com> wrote:

> Attachment??
>
>
>
> --
> View this message in context:
> http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4659964.html
> Sent from the ActiveMQ - User mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by prgtrdr <pr...@gmail.com>.
Attachment??



--
View this message in context: http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4659964.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by Christian Posta <ch...@gmail.com>.
Mmmm... good question.. it can be accessed through the BrokerService
object, but it was never intended to be made accessible... would have to
use some hacking to get at it. See attached unit test that has such hacking.

Otherwise, to get at it in JMX, make sure your broker is populating the
username:

        BrokerService service = new BrokerService();
        service.setUseJmx(true);
        service.setPopulateUserNameInMBeans(true);

Good luck!



On Thu, Nov 29, 2012 at 12:29 PM, prgtrdr <pr...@gmail.com> wrote:

> Thanks, Christian.
>
> To put it more succinctly, what I want to do is retrieve the userName for a
> given ConnectionId returned by the Advisory onMessage function.
>
> Do you think JMX is the easiest way to do this?  Can't I use the
> BrokerService or some other object I have created in the embedded ActiveMQ
> instance?
>
>
>
>
> --
> View this message in context:
> http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4659954.html
> Sent from the ActiveMQ - User mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by prgtrdr <pr...@gmail.com>.
Thanks, Christian.

To put it more succinctly, what I want to do is retrieve the userName for a
given ConnectionId returned by the Advisory onMessage function.

Do you think JMX is the easiest way to do this?  Can't I use the
BrokerService or some other object I have created in the embedded ActiveMQ
instance?




--
View this message in context: http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949p4659954.html
Sent from the ActiveMQ - User mailing list archive at Nabble.com.

Re: How can I retrieve a Stomp username when a new Connection is made?

Posted by Christian Posta <ch...@gmail.com>.
Yes, the advisory broker will delete the username/password from a
connectionInfo before dispatching to the advisories.

Since you're creating the broker in code, are you asking for how to
retrieve the username/password through the BrokerService object?

You can retrieve the username for a connection through jmx, btw...


On Thu, Nov 29, 2012 at 11:11 AM, prgtrdr <pr...@gmail.com> wrote:

> I'm stuck on something that is probably obvious but I just can't figure out
> how to do it.
>
> What I want to do is retrieve the userName from an incoming Stomp
> connection.  I am creating the broker in my code and have also set up
> monitoring Advisory messages.  The Advisory onMessage() function receives
> the ConnectionInfo message but the userName and password are deleted from
> the message, and the ConnectionInfo.getUserName() returns a null string.
>
> My guess is to get the userName I have to somehow lookup the Connection
> object based on the ConnectionId contained in the Advisory ConnectionInfo
> message, then I can get the userName from the Connection.
>
> Is that right?  Or is there an easier way?  If it's right, how do I lookup
> the Connection object in the Advisory onMessage callback?
>
>
>
>
> --
> View this message in context:
> http://activemq.2283324.n4.nabble.com/How-can-I-retrieve-a-Stomp-username-when-a-new-Connection-is-made-tp4659949.html
> Sent from the ActiveMQ - User mailing list archive at Nabble.com.
>



-- 
*Christian Posta*
http://www.christianposta.com/blog
twitter: @christianposta