I would like to respond in the public forum to an issue expressed in the following e-mail from Michael Voß . It concerns the configuration of a Client and callback Connector using the sslmultiplex transport.
> I have discovered another problem but I am not sure if it is about Linux/Windows differences or the cpu speed or sth. else:
> Regarding the client:
> On a Unix system I first build up the client object and run connect() and then build up and start the connector so that the program works fine.
> The other way round I get the exception: java.lang.InvocationTargetException ... caused by java.lang.RuntimeException: Address already in use when adding a callback listener to the client object
> + also getting Exception in thread "Timer-2" java.lang.NullPointerException
> Running the client application in Windows I need to build up and run the connector object first and then the client object to run properly
> The other way round I get the exception: java.lang.InvocationTargetException ... caused by java.lang.RuntimeException: Connection refused by Client client = new Client(locator, "subsys", configuration);
> I use sslmultiplex
> How already mentioned I do not know the cause for this but I can not imagine that it is about Windows or Unix
> What do you think about it?
The multiplex and sslmultiplex transports have been in flux recently (as has been much of Remoting), and the primary solution is to use the newest version. With CVS version JBossRemoting_2_0_0_beta_2 I was able to get Michael's example to work, in all of its variations, with only a single code modification (other than a change of ports), and I want to talk about that modification because it concerns the admittedly complicated invoker group rules.
Michael creates a Connector with InvokerLocator, say, sslmultiplex://localhost:2001, and then creates, in some order, a Client and a callback Connector. Simplifying somewhat, suppose the Client is set up so:
configuration.put(Multiplex.MULTIPLEX_BIND_HOST, "localhost"); configuration.put(Multiplex.MULTIPLEX_BIND_PORT, "3001"); client = new Client("sslmultiplex://localhost:2001", configuration); client.connect();
and then the Connector is set up so:
connector = new Connector("sslmultiplex://localhost:3001", configuration); connector.create(); SSLMultiplexServerInvoker invoker=(SSLMultiplexServerInvoker)connector.getServerInvoker(); invoker.setClientConnectAddress("localhost"); invoker.setClientConnectPort(2001); connector.start();
The result of starting the callback Connector will be: java.net.BindException: Address already in use.
The reason is that the InvokerLocator "sslmultiplex://localhost:3001" gives MultiplexServerInvoker no clue that it is meant to share a connection with a MultiplexClientInvoker. In the absence of any hint to the contrary, it will create, during the call to Connector.create(), a "real" server socket, i.e., MasterServerSocket, instead of a VirtualServerSocket, and try to bind it to port 3001. This behavior is determined by server rule 4.
One solution is to rewrite the callback Connector code as follows:
configuration.put(Multiplex.MULTIPLEX_CONNECT_HOST, "localhost"); configuration.put(Multiplex.MULTIPLEX_CONNECT_PORT, "2001"); connector = new Connector("sslmultiplex://localhost:3001", configuration); connector.create(); connector.start();
The presence of the "connect" information tells MultiplexServerInvoker to look for an existing invoker group to join, and it will create a VirtualServerSocket that uses the real socket bound to port 3001.
This example suggests that it might be reasonable to change the invoker group rules so that a MultiplexServerInvoker will try to create VirtualServerSocket bound to a given port if it finds that port in use. It's something to think about.