You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@activemq.apache.org by "Timothy Bish (JIRA)" <ji...@apache.org> on 2011/08/26 01:24:30 UTC
[jira] [Closed] (AMQ-1233) Bug when setting transportConnector URI
options in activemq.xml
[ https://issues.apache.org/jira/browse/AMQ-1233?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Timothy Bish closed AMQ-1233.
-----------------------------
Resolution: Fixed
Appears to be fixed, reopen with test case if its still an issue.
> Bug when setting transportConnector URI options in activemq.xml
> ---------------------------------------------------------------
>
> Key: AMQ-1233
> URL: https://issues.apache.org/jira/browse/AMQ-1233
> Project: ActiveMQ
> Issue Type: Bug
> Components: Broker
> Affects Versions: 5.2.0
> Reporter: David MartÃn Clavo
> Fix For: NEEDS_REVIEWED
>
>
> As you may know, there are some problems when setting options in the URI for a TransportConnector in the broker configuration file activemq.xml (at least for me when launching the console with the Main class and the start command).
> For example, the option 'socket.tcpNoDelay=true' works fine in a producer or consumer URI, but doesn't make the broker have TCP_NODELAY sockets when it is set in the activemq.xml file.
> I think I have this more or less nailed down, I will try to explain.
> During all my explanation, I'm using the last source from SVN at the time of writing.
> Let's imagine you have the following piece of xml in your activemq.xml file:
> <transportConnectors>
> <transportConnector uri="tcp://localhost:61616?trace=true&foo=bar"/>
> </transportConnectors>
> (side note: i have not found in the documentation the need to use ' & a m p ;' in this file, instead of just '&' like in Java code, would be a nice addition for clueless people like myself)
> (side note 2: in the forum the & a m p ; appears as just &, but you have to write '& a m p ;' without the spaces of course).
> How do these options get processed? Well at some point the method 'org.apache.activemq.transport.tcp.TcpTransportFactory.doBind' gets executed.
> public TransportServer doBind(String brokerId, final URI location) throws IOException {
> try {
> Map options = new HashMap(URISupport.parseParamters(location));
> We now have a nice HashMap with our options: {trace=true, foo=bar}
> ServerSocketFactory serverSocketFactory = createServerSocketFactory();
> TcpTransportServer server = createTcpTransportServer(location, serverSocketFactory);
> server.setWireFormatFactory(createWireFormatFactory(options));
> IntrospectionSupport.setProperties(server, options);
> 'IntrospectionSupport.setProperties' is a method who uses reflexion to find the setter methods of a class, and if there is a setter method with the same name as a key of our HashMap, sets the value.
> The 'doBind' method finishes wish
> Map transportOptions = IntrospectionSupport.extractProperties(options, "transport.");
> server.setTransportOption(transportOptions);
> server.bind();
>
> return server;
> }
> catch (URISyntaxException e) {
> throw IOExceptionSupport.create(e);
> }
> }
> This is what happens when you start the broker.
> Now, what happens when a client connects and the broker has to create a Transport object for the connection?
> The method org.apache.activemq.transport.tcp.TcpTransportServer.run() gets executed:
> [some stuff]
> HashMap options = new HashMap();
> options.put("maxInactivityDuration", new Long(maxInactivityDuration));
> options.put("minmumWireFormatVersion", new Integer(minmumWireFormatVersion));
> options.put("trace", new Boolean(trace));
> options.putAll(transportOptions);
> WireFormat format = wireFormatFactory.createWireFormat();
> Transport transport = createTransport(socket, format);
> Transport configuredTransport = transportFactory.serverConfigure(transport, format, options);
> getAcceptListener().onAccept(configuredTransport);
> [more stuff]
> As you see this method constructs a new HashMap options object, which is used to configure the Transport with the line:
> Transport configuredTransport = transportFactory.serverConfigure(transport, format, options);
> If you have a look at this method, you will see that after a call to another method, the properties of the Transport are set again with 'IntrospectionSupport.setProperties'.
> So what's the problem? The problem is that for the properties to be recognized, they have to be declared as setters in 2 classes. In this case, TcpTransport and TcpTransportServer.
> When a property is set in the connection URI of a client, the ActiveMQ classes don't use TcpTransportServer. They directly set the options on the TcpTransport.
> However in a broker, the execution path goes through the TcpTransportServer class. If the options don't have setters declared, and are not later put into the 'options' object in the The method 'org.apache.activemq.transport.tcp.TcpTransportServer.run()' method, the Transport created by the broker does not have these options set.
> In our example, trace=true will be recognized but not foo=bar.
> If you have a look at the TcpTransportServer class, you will see that the only options accepted are:
> -maxInactivityDuration
> -minmumWireFormatVersion (small mispelling btw)
> -trace
> -transport.* options
> Furthermore, the way things work, if you put another option on the URI, it will be silently ignored. You can put 'foo=bar' or 'socket.tcpNoDelay=true' and no error message appears. So people may have been using options and thinking they had no effect, where in fact they were ignored without warning, like in the TCP_NODELAY case.
> I don't know how the ActiveMQ devs want to design this class, but I see 2 solutions:
> -manually add the missing options to TcpTransportServer, and update the docs so that they are synchronized with the actual options that have to be used (like socket.tcpNoDelay=true instead of wireFormat.tcpNoDelayEnabled=true).
> -somehow eliminate the double IntrospectionSupport.setProperties usage, and pass the options directly to the TcpTransport class. This will save the need to remember to put options in 2 classes every time one is added. And of course, there is still the need to keep the docs synchronized... :)
> If you want to reproduce my analysis, I used Eclipse, executing ActiveMQ source using the console Main class, in debug mode, and using breakpoints in the methods above mentioned.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira