I have a small application containing a number of classes. The application is designed to connect to a server and send / recv binary protocol msgs.
I have this part working using a connection manager class and a message processor class. The connection manager gets instantiated and creates 2 threads one to send and one to recv msgs. On receipt of a message a new message processor object is instantiated to handle the parsing of the message.
I have now created a GUI that has connect, logon etc... buttons.
The gui creates an instance of connection manager and when the connect button is presses it calls connection manager.connect.
When the logon button is pressed it calls connection manager.logon.
the connection manager object has a Boolean called connected.
so the gui can read connection manager.connected and see true/false. now what I need to be able to do is access connection manager.connected from my message processor object which gets created inside connection manager each time a message is received. So if message processor sees a logon ack message it can set connection manager.connected = true and the GUI which created the connection manager object can read the value.
However I cant see how I can access connection manager.connected from the message processor object. I think this is possibly a flaw in my design?
code examples.
GUI creates connection manager object reading in GUI text fields
cm = new ConnectionManager(jTextField1.getText(), jTextField2.getText())
Connection Manager has a Boolean connected. It also creates a read and write from network thread
public boolean connected;
executor.execute(new MessageProcessor(header, message, msgType));
Inside MessageProcessor I want to update cm.connected - is this possible?
Thanks
Did you create the MessageProcessor yourself? If so you could add a parameter in constructor and send a reference to the ConnectionManager:
executor.execute(new MessageProcessor(header, message, msgType, this));
Then the MessageProcessor will be able to access connected through ConnectionManager.
MessageProcessor should hold a reference to its calling ConnectionManager. You can pass the reference in the constructor of MessageProcessor and store it in an instance variable:
public class MessageProcessor {
private ConnectionManager cm;
public MessageProcessor(ConnectionManager cm) {
this.cm = cm;
}
public void process() {
cm.setConnected(false);
}
}
instantiating a MessageProcessor:
public class ConnectionManager {
public void connect() {
MessageProcessor pm = new MessageProcessor(this);
}
public void setConnected(boolean connected) {
this.connected = connected;
}
}
of course you have coupled MessageProcessor and ConnectionManager. There are (rather) complex solutions that allow you to "decide" at run time between implementations of MessageProcessor and ConnectionManager. These include the factory patter and dependency injection.
how are you planning to access cm from your MessageProcessor object? it's also about the communication between objects. If you have only one ConnectionManager for your send/receive threads and if you always have one pair of threads (send/receive), you can simply use public static boolean connected and upon establishing a connection you can set it to true. This is not a good solution of you have multiple thead-couples (for send/receive activities). I almost forgot until someone pointed it out, you can pass on a parameter this - reference to who is calling MessageProcessor constructor. However, this is still not very good as any change in class definition will hurt the implementation in MessageProcessor.
In simple word, yes it is possible to access/mutate connected from your MessageProcessor - you should also consider using synchronized methods to access/mutate connected. But if you need to make the solution better, you need to consider using individual connectionManager objects. #sharonbn has already shown you some examples of how to go about doing this.
Related
I came across some JMS calling code that initializes the JMS session inside of its constructor. The calling code implements the ExceptionListener interface and passes a reference to this to the connection factory object, as shown below:
public class JmsCode implements ExceptionListener {
private static final Logger logger = LoggerFactory.getLogger(JmsCode.class);
public JmsCode(String url, String username, String password, String trustStorePath, char[] trustStorePassword) throws JMSException {
ActiveMQSslConnectionFactory connectionFactory = new ActiveMQSslConnectionFactory(url);
connectionFactory.setUserName(username);
connectionFactory.setPassword(password);
connectionFactory.setTrustStore(trustStorePath);
connectionFactory.setTrustStorePassword(new String(trustStorePassword));
connectionFactory.setExceptionListener(this);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
#Override
public void onException(JMSException e) {
logger.error("Unexpected JMS exception caught", e);
}
}
I am wondering if it is safe to pass a reference to this from the JmsCode constructor given that the object hasn't been fully constructed yet. I came across a similar question which had me reading up on IBM's article on not publishing this during construction. While I agree with their reasoning, I am not sure if it applies in this case since the only thing the exception listener is doing is logging via a static and final member. Is the code above safe (ignoring someone else being tempted to change the exception listener method to use some instance state of the object)?
This is in fact unsafe publishing, and it's theoretically possible for another object to see this one in an inconsistent state.
That said, while this isn't a good pattern (and it's just shown here to demonstrate ExceptionListener), the logic of the constructor shows that the class is in fact fully constructed by the time that the this reference escapes (because it has nothing to construct), and so in this exact case there's nothing that can go wrong.
Whether it is safe or not depends on where that reference to this can escape to. If, as a consequence of this call, this could be read by another thread, then it is not safe.
If you want to ensure an instance is completely initialized for safe publication and you want to publish it, a constructor isn't the right place to publish it. Instead, you'll need to create a Factory object or a static factory method which can construct the object safely and then publish it before returning it to the caller.
It is completely safe. You are just passing the this reference, not using anything in the this scope.
Something will go wrong on that iff the .setExceptionListener(this) method performs something else than being a setter.
I am new in Java and JavaRMI so a have some doubts about how its works, see below:
public interface Something implements Remote {...}
public SomeStub extends UnicastRemoteObject implements Something {...}
Every time when I create and bind (registry.rebind(...)) one object of SomeStub I am creating a new ServerSocket to listen calls only for this object?
Example:
registry.rebind("...", new obj1);
registry.rebind("...", new obj2);
registry.rebind("...", new obj3).
2) So if the question 1 is true, is better use just only one stub of this object and threads to avoid create lots of serversockets?
PS: I am using the default serversocket and socket factories provided by the JavaRMI.
Every time when I create and bind (registry.rebind(...)) one object of SomeStub I am creating a new ServerSocket to listen calls only for this object?
No. Every time you export a new remote object RMI attempts to do port sharing, and creates a new ServerSocket only if it doesn't already have one it can share with the new object.
Binding has nothing to do with it.
NB This is not a stub. It is a remote object, and it has its own stub created by RMI. Don't misuse standard naming. Call it something else.
So if the question 1 is true
It isn't.
is better use just only one stub of this object and threads to avoid create lots of serversockets
No.
I have a server and a client communicating through RMI. Their goal is to share a simple object, work on it together, and then simulate a server disconnect.
The sever has its name bound to the rmiregistry. The client uses the rmiregistry to get a remote reference to the server. Then it uses this reference to call a method that returns a reference to the object they will share. Further communication is to be done through this shared object.
The shared object is a UnicastRemoteObject, the server owns its implementation and has a method the returns a reference to the client.
The client knows the interface of the shared object, gets a remote reference from the server and then acts on it. Please note the server should return a remote reference, not a serialized copy.
This is the shared object interface
public interface CInterface extends Remote {
boolean testMethod() throws RemoteException;
}
And this is its implementation
public class CImpl implements CInterface {
#Override
public boolean testMethod() throws RemoteException {
return false;
}
}
This is the method of the server that should return a remote reference when the client calls it
public CInterface exportRefToC() throws RemoteException {
return new CImpl();
}
If I call it from the client, it gives me this exception
java.rmi.UnmarshalException: error unmarshalling return; nested
exception is: java.io.WriteAbortedException: writing aborted;
java.io.NotSerializableException: sandbox.CImpl
I can get the method to work and return a remote reference if I write it this way
public CInterface exportRefToC() throws RemoteException {
refToC = new CImpl();
return (CInterface) UnicastRemoteObject.exportObject(refToC, 1099);
}
What I don't get is why I need to go through the registry again, though not explicitly binding a the name, just to return a remote reference. The client got a reference to the server before, using the rmiregistry, so the bootstrap is done. Now, why can't the server just return a reference to the client without knowing the port of the rmiregistry (1099)?
Bonus question, if the server wants to make the object it shared with the client unavailable (to simulate a disconnection), is there a better way than doing this
UnicastRemoteObject.unexportObject(refToC, true);
EDIT: if I extend the UnicastRemoteObject in the implementation of the shared object, the first version of the method works, however, the unexport does not work and return this exception
java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is: java.rmi.NoSuchObjectException: object not
exported
EDIT2: checked again, it does work, just need to save the reference before returning it
public CInterface exportRefToC() throws RemoteException {
refToC = new CImpl();
return refToC;
}
The shared object is a UnicastRemoteObject
No it isn't. Look again:
public class CImpl implements CInterface
Add extends UnicastRemoteObject to that, and provide an appropriate constructor, and your problem will disappear.
You don't need to call exportObject(), and you don't need a second binding to the Registry.
Your last question embodies a mistake. It should be unexportObject(), and that is the correct way of making the object unavailable.
I'm constructing an AsyncHttpClient like this:
public AsyncHttpClient getAsyncHttpClient() {
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()
.setProxyServer(makeProxyServer())
.setRequestTimeoutInMs((int) Duration.create(ASYNC_HTTP_REQUEST_TIMEOUT_MIN, TimeUnit.MINUTES).toMillis())
.build();
return new AsyncHttpClient(new NettyAsyncHttpProvider(config), config);
}
This gets called once at startup, and then the return value is passed around and used in various places. makeProxyServer() is my own function to take my proxy settings an return a ProxyServer object. What I need to do is be able to change the proxy server settings and then recreate the AsyncHttpClient object. But, I don't know how to shut it down cleanly. A bit of searching on leads me to believe that close() isn't gracefull. I'm worried about spinning up a whole new executor and set of threads every time the proxy settings change. This won't be often, but my application is very long-running.
I know I can use RequestBuilder.setProxyServer() for each request, but I'd like to have it set in one spot so that all callers of my asyncHttpClient instance obey the system-wide proxy settings without each developer having to remember to do it.
What's the right way to re-configure or teardown and rebuild a Netty-based AsyncHttpClient?
The problem with using AsyncHttpClient.close() is that it shuts down the thread pool executor used by the provider, then there is no way to re-use the client without re-building it, because as per documentation, the executor instance cannot be reused once ts is shutdown. So, there is no way but re-build the client if you go that way (unless you implement your own ExecutorService that would have another shutdown logic, but it is a long way to go, IMHO).
However, from looking into the implementation of NettyAsyncHttpProvider, I can see that it stores the reference to the given AsyncHttpClientConfiginstance and calls its getProxyServerSelector() to get the proxy settings for every new NettyAsyncHttpProvider.execute(Request...) invocation (i.e. for every request executed by AsyncHttpClient).
Then, if we could make the getProxyServerSelector() return the configurable instance of ProxyServerSelector, that would do the thing.
Unfortunately, AsyncHttpClientConfig is designed to be a read-only container, instantiated by AsyncHttpClientConfig.Builder.
To overcome this limitation, we would have to hack it, using, say, "wrap/delegate" approach:
Create a new class, derived from AsyncHttpClientConfig. The class should wrap the given separate AsyncHttpClientConfig instance and implement the delegation of the AsyncHttpClientConfig getters to that instance.
To be able to return the proxy selector we want at any given point of time, we make this setting mutable in a this wrapper class and expose the setter for it.
Example:
public class MyAsyncHttpClientConfig extends AsyncHttpClientConfig
{
private final AsyncHttpClientConfig config;
private ProxyServerSelector proxyServerSelector;
public MyAsyncHttpClientConfig(AsyncHttpClientConfig config)
{
this.config = config;
}
#Override
public int getMaxTotalConnections() { return config.maxTotalConnections; }
#Override
public int getMaxConnectionPerHost() { return config.maxConnectionPerHost; }
// delegate the others but getProxyServerSelector()
...
#Override
public ProxyServerSelector getProxyServerSelector()
{
return proxyServerSelector == null
? config.getProxyServerSelector()
: proxyServerSelector;
}
public void setProxyServerSelector(ProxyServerSelector proxyServerSelector)
{
this.proxyServerSelector = proxyServerSelector;
}
}
Now, in your example, wrap your AsyncHttpClient config instance with our new wrapper and use it to configure the AsyncHttpClient:
Example:
MyAsyncHttpClientConfig myConfig = new MyAsyncHttpClientConfig(config);
return new AsyncHttpClient(new NettyAsyncHttpProvider(myConfig), myConfig);
Whenever you invoke myConfig.setProxyServerSelector(newSelector), the new request executed by NettyAsyncHttpProvider instance in your client will use the new proxy server settings.
A few hints/warnings:
This approach relies on the internal implementation of NettyAsyncHttpProvider; therefore make your own judgement on maintainability, future Netty libraries versions upgrade strategy etc. You could always look at the Netty source code before upgrading to the new version. At the current point, I personally think it is unlikely to change too much to invalidate this implementation.
You could get ProxyServerSelector for ProxyServer by using com.ning.http.util.ProxyUtils.createProxyServerSelector(proxyServer) - that's exactly what AsyncHttpClientConfig.Builder does.
The given example has no synchronization logic for accessing proxyServerSelector; you may want to add some as your application logic needs.
Maybe it is a good idea to submit a feature request for AsyncHttpClient to be able to setup a "configuration factory" for the AsyncHttpProvider so all these complications would vanish :-)
You should be holding a RequestHandle instance for all your unfinished requests. When you want to shut down, you can loop through and call isFinished() on all of them until they are all done. Then you know you can safely close it and no pending requests will be killed.
Once it's closed, just build a new one. Don't try to reuse the existing one. If you have references to it around, change those to reference a Factory that will return the current one.
Scenario:
Client C connects to Server S via RMI
C asks S to create a handler H, S returns H to C
C then talks to H
Now I could do this in two ways:
Make the handler a Remote and let S return the stub to it, so C can directly talk to that (h.say(String msg);)
Give the handler an ID and return that to C. C will talk to H via S (s.sayToHandler(int id, String msg);)
The first is nicer OO, but what about the performance? Will an extra TCP connection be opened, or is the existing connection between S and H used?
I don't know about the implementation. I don't think a new connection is made. But what I know is the more objects you share remotely the more objects that depends on remote dereference to get garbage collected (so there will be more objects living longer, not good).
Alternative approach
I'll recommend a mixed approach. Use the nice approach for the client but implement it the not-so-nice-way internally:
interface Server {
public Handler getHandler(...);
}
interface Handler extends Serializable {
// it gets copied!
public X doThis(...);
public Y doThat(...);
}
class HandlerImpl implements Handler {
public X doThis(...) {
backDoor.doThis(this, ...);
}
public Y doThat(...) {
backDoor.doThat(this, ...);
}
private BackDoor backDoor;
}
interface BackDoor {
public X doThis(Handler h, ...);
public Y doThat(Handler h, ...);
}
class ServerImpl imlpements Server, BackDoor {
public Handler getHandler(...) {
return /*a handler with a self reference as backdoor, only ONE remote obj shared via TWO interfaces */
}
...
// it does everything
// it receives the handler
}
BackDoor and Handler are sync'ed interfaces. The first has the methods with Handler as argument, the later has the pure methods. I don't think it's a big deal. And the two different interfaces let you work cleanly without the client know nothing and allowing the thin serializable Handler's do the dirty work.
Hope you like it!
The RMI specification does not really say whether there should be a new connection or the existing one reused. The wire protocol allows both, using either multiplexing or one TCP connection per call (which might be reused for following calls to the same sever object, I'm not sure). If you need tunneling through HTTP, than only one message per connection is allowed.
I did not find anything on how to configure which type of protocol to use (other than disabling HTTP tunneling).
If you want to make sure that only one TCP connection is used, use custom client and server socket factories doing the tunneling of multiple connections though one themselves. This will probably be less efficient than what the RMI runtime system would be doing there.