How to ensure that only one XMPPConnection will be created? Use singletons?
I'm dealing with creating a web service which will receive requests to send messages via XMPP. However, all messages will be sent from one account (the server logs in and sends notifications to users).
Here comes the problem - how to implement it? I was trying to implement the XMPPConnection class as a singleton, but I got stuck at passing arguments to constructors containing the hostname, port, JID etc
As I've read here, a singleton with parameters is not a singleton... Hence, I thought about solving it as follows (is it some kind of factory?):
public class XMPPConnectionSingleton
{
private volatile static XMPPConnectionSingleton anInstance;
private volatile static XMPPConnection connection;
public static XMPPConnectionSingleton getInstance() {
if(anInstance == null) {
synchronized (XMPPConnectionSingleton.class) {
if(anInstance == null)
anInstance = new XMPPConnectionSingleton();
}
}
return anInstance;
}
public void init(String se开发者_如何学JAVArver, int port, String jid, String password, String resource)
{
ConnectionConfiguration conf = new ConnectionConfiguration(server, port);
connection = new XMPPConnection(conf);
// logging in, etc.
}
}
Is it a good way to go? Or maybe it is better to make a wrapping class for XMPPConnection, accepting a constructor with no parameters?
You can use a ~singleton, read this question and the related pages here and here. The cleanest is to initialize in a static block, but that is obiously not always possible.
The obious, simple, approach is to synchronize on a single instance and all WS calls wait. This will work great for low capacity. Using ReentrantLock might enhance that logic somewhat - for example sending a timeout WS reponse rather than having the whole HTTP call out.
If you need many concurrent sessions, consider checking out whether the server can log in with multiple clients and then initialize as many clients as you want - then use the ReentrantLock in some way to determine which is currently free.
Depending on the logic in your WS calls (does it need confirmation that message is sent to XMPP?) you might consider queueing up the calls and serving them from another thread, returning the WS call before the actual message is sent (http hold time is normally 30 second, but can be changed).
Might even be possible to let each WS session connect and have its own session for the duration of the call.
Edit:I suggest you go with
// Correct lazy initialization in Java
@ThreadSafe
class Foo {
private static class HelperHolder {
public static Helper helper = new Helper();
}
public static Helper getHelper() {
return HelperHolder.helper;
}
}
where Helper is
- a helper class which pull the login info from somewhere, wraps the XMPP client class, or
- the XMPP client class itself with hardcoded login info.
Then simply use synchronized operator on the returned object.
It sounds to me like the wrong approach altogether. Why not simply have the WS requests put in a queue and have a single thread read the requests and write the messages via xmpp. There would only be a single connection, but there is no need to create any custom code to create a singleton connection at all.
精彩评论