JBoss Remoting SVN: r5216 - remoting2/branches/2.x/src/main/org/jboss/remoting.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-14 21:58:55 -0400 (Thu, 14 May 2009)
New Revision: 5216
Modified:
remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionValidator.java
Log:
JBREM-1132: Introduced "stopping" and "useClientConnectionIdentity".
Modified: remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionValidator.java
===================================================================
--- remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionValidator.java 2009-05-15 01:40:05 UTC (rev 5215)
+++ remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionValidator.java 2009-05-15 01:58:55 UTC (rev 5216)
@@ -22,11 +22,11 @@
package org.jboss.remoting;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
@@ -117,7 +117,7 @@
}
catch (Throwable throwable)
{
- log.debug("ConnectionValidator to connect to server " +
+ log.debug("ConnectionValidator unable to connect to server " +
innerClientInvoker.getLocator().getProtocol() + "://" +
innerClientInvoker.getLocator().getHost() + ":" +
innerClientInvoker.getLocator().getPort(), throwable);
@@ -227,12 +227,13 @@
private Map metadata;
private InvokerLocator locator;
private Map configMap;
- private List listeners;
+ private Map listeners;
private ClientInvoker clientInvoker;
private Object lock = new Object();
private Object notificationLock = new Object();
private boolean started;
private volatile boolean stopped;
+ private volatile boolean stopping;
private String invokerSessionId;
private boolean tieToLease = true;
private boolean stopLeaseOnFailure = true;
@@ -240,6 +241,9 @@
private int failureDisconnectTimeout = -1;
private boolean isValid;
private Timer timer;
+ private MicroRemoteClientInvoker sharedInvoker;
+ private LeasePinger leasePinger;
+ private boolean useClientConnectionIdentity;
// Constructors ---------------------------------------------------------------------------------
@@ -251,9 +255,10 @@
public ConnectionValidator(Client client, long pingPeriod)
{
this.client = client;
+ this.locator = client.getInvoker().getLocator();
this.pingPeriod = pingPeriod;
pingTimeout = DEFAULT_PING_TIMEOUT_INT;
- listeners = new ArrayList();
+ listeners = new HashMap();
stopped = false;
getParameters(client, new HashMap());
log.debug(this + " created");
@@ -262,9 +267,10 @@
public ConnectionValidator(Client client, Map metadata)
{
this.client = client;
+ this.locator = client.getInvoker().getLocator();
pingPeriod = DEFAULT_PING_PERIOD;
pingTimeout = DEFAULT_PING_TIMEOUT_INT;
- listeners = new ArrayList();
+ listeners = new HashMap();
stopped = false;
this.metadata = new HashMap(metadata);
getParameters(client, metadata);
@@ -300,7 +306,7 @@
".addConnectionListener() instead.");
}
- if (stopped)
+ if (stopping)
{
return;
}
@@ -321,7 +327,7 @@
try
{
- if(!stopped)
+ if(!stopping)
{
isValid = false;
@@ -366,41 +372,84 @@
// Public ---------------------------------------------------------------------------------------
- public void addConnectionListener(ConnectionListener listener)
+ public boolean addConnectionListener(Client client, ConnectionListener listener)
{
+ boolean doStart = false;
if (listener != null)
{
synchronized (lock)
{
+ if (stopping)
+ {
+ if (trace) log.trace(this + " is stopped. Cannot add ConnectionListener: " + listener + " for " + client);
+ return false;
+ }
if (listeners.size() == 0)
{
- start();
+ doStart = true;
}
- listeners.add(listener);
+ Set s = (Set) listeners.get(listener);
+ if (s == null)
+ {
+ s = new HashSet();
+ }
+ s.add(client);
+ listeners.put(listener, s);
+ log.debug(this + " added ConnectionListener: " + listener + " for " + client);
}
+ if (doStart)
+ {
+ start();
+ }
}
+
+ return true;
}
- public boolean removeConnectionListener(ConnectionListener listener)
+ public boolean removeConnectionListener(Client client, ConnectionListener listener)
{
- boolean isRemoved = false;
- if (listener != null)
+ if (listener == null)
{
- synchronized (lock)
+ if (trace) log.trace(this + " ConnectionListener is null");
+ return false;
+ }
+ synchronized (lock)
+ {
+ if (stopping)
{
- isRemoved = listeners.remove(listener);
- if (listeners.size() == 0)
- {
- stop();
- }
+ if (trace) log.trace(this + " is stopped. It's too late to remove " + listener);
+ return false;
}
+ Set s = (Set) listeners.get(listener);
+ if (s == null)
+ {
+ log.debug(this + ": " + listener + " is not registered");
+ return false;
+ }
+ if (s.remove(client))
+ {
+ log.debug(this + " removed ConnectionListener: " + listener + " for " + client);
+ }
+ else
+ {
+ log.debug(this + ": " + listener + " is not registered for " + client);
+ return false;
+ }
+ if (s.size() == 0)
+ {
+ listeners.remove(listener);
+ }
+ if (listeners.size() == 0)
+ {
+ stop();
+ }
}
- return isRemoved;
+ return true;
}
public long getPingPeriod()
{
- if (stopped)
+ if (stopping)
{
return -1;
}
@@ -412,9 +461,52 @@
{
return "ConnectionValidator[" + Integer.toHexString(System.identityHashCode(this)) + ":" + clientInvoker + ", pingPeriod=" + pingPeriod + " ms]";
}
+
+ public boolean isStopped()
+ {
+ return stopped;
+ }
// Package protected ----------------------------------------------------------------------------
+ void notifyListeners(Throwable thr)
+ {
+ final Throwable t = thr;
+ synchronized (lock)
+ {
+ if (stopping)
+ {
+ return;
+ }
+ stopping = true;
+ if (trace) log.trace(this + " is stopped. No more listeners will be accepted.");
+
+ Iterator itr = listeners.keySet().iterator();
+ while (itr.hasNext())
+ {
+ final ConnectionListener listener = (ConnectionListener) itr.next();
+ Set clients = (Set) listeners.get(listener);
+ Iterator itr2 = clients.iterator();
+ while (itr2.hasNext())
+ {
+ final Client client = (Client) itr2.next();
+ new Thread()
+ {
+ public void run()
+ {
+ log.debug(ConnectionValidator.this + " calling " + listener + ".handleConnectionException() for " + client);
+ listener.handleConnectionException(t, client);
+ }
+ }.start();
+ }
+ }
+
+ listeners.clear();
+ }
+
+ stop();
+ }
+
// Protected ------------------------------------------------------------------------------------
// Private --------------------------------------------------------------------------------------
@@ -431,12 +523,21 @@
ClientInvoker clientInvoker = client.getInvoker();
if (clientInvoker instanceof MicroRemoteClientInvoker)
{
- invokerSessionId = ((MicroRemoteClientInvoker) clientInvoker).getSessionId();
+ sharedInvoker = (MicroRemoteClientInvoker) clientInvoker;
+ invokerSessionId = sharedInvoker.getSessionId();
}
else
{
throw new RuntimeException("creating a ConnectionValidator on a local connection");
}
+ if (stopLeaseOnFailure)
+ {
+ if (sharedInvoker != null)
+ {
+ leasePinger = sharedInvoker.getLeasePinger();
+ }
+ }
+ if (trace) log.trace(this + ": sharedInvoker = " + sharedInvoker + ", leasePinger = " + leasePinger);
}
private boolean checkUseParametersFromLocator(Client client, Map metadata)
@@ -580,6 +681,7 @@
}
o = config.get(FAILURE_DISCONNECT_TIMEOUT);
+ if (trace) log.trace(this + " \"failureDisconnectTimeout\" set to " + o);
if (o != null)
{
if (o instanceof String)
@@ -587,6 +689,7 @@
try
{
failureDisconnectTimeout = Integer.valueOf(((String) o)).intValue();
+ if (trace) log.trace(this + " setting failureDisconnectTimeout to " + failureDisconnectTimeout);
}
catch (Exception e)
{
@@ -600,6 +703,27 @@
" to an int: must be a String");
}
}
+ o = config.get(Remoting.USE_CLIENT_CONNECTION_IDENTITY);
+ if (o != null)
+ {
+ if (o instanceof String)
+ {
+ try
+ {
+ useClientConnectionIdentity = Boolean.valueOf(((String) o)).booleanValue();
+ }
+ catch (Exception e)
+ {
+ log.warn(this + " could not convert " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " value" +
+ " to a boolean: " + o);
+ }
+ }
+ else
+ {
+ log.warn(this + " could not convert " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " value" +
+ " to a boolean: must be a String");
+ }
+ }
}
}
@@ -610,7 +734,6 @@
log.debug(this + ": pingPeriod: " + this.pingPeriod);
log.debug(this + ": pingTimeout: " + this.pingTimeout);
log.debug(this + ": ping retries: " + configMap.get("NumberOfCallRetries"));
- locator = client.getInvoker().getLocator();
try
{
@@ -628,7 +751,14 @@
clientInvoker.connect();
}
- TimerUtil.schedule(this, pingPeriod);
+ try
+ {
+ TimerUtil.schedule(this, pingPeriod);
+ }
+ catch (Exception e)
+ {
+ log.error(this + " unable to schedule on TimerUtil", e);
+ }
started = true;
timer = new Timer(true);
log.debug(this + " started");
@@ -696,6 +826,7 @@
private boolean doStop()
{
+ if (trace) log.trace("entering doStop()");
synchronized(lock)
{
if (stopped)
@@ -707,6 +838,7 @@
{
listeners.clear();
}
+ stopping = true;
stopped = true;
timer = null;
}
@@ -722,34 +854,7 @@
log.debug(this + " stopped, returning " + result);
return result;
}
-
- private void notifyListeners(Throwable thr)
- {
- final Throwable t = thr;
- synchronized (lock)
- {
- if (stopped)
- {
- return;
- }
- ListIterator itr = listeners.listIterator();
- while (itr.hasNext())
- {
- final ConnectionListener listener = (ConnectionListener) itr.next();
- new Thread()
- {
- public void run()
- {
- log.debug(this + " calling " + listener + ".handleConnectionException()");
- listener.handleConnectionException(t, client);
- }
- }.start();
- }
- }
- stop();
- listeners.clear();
- }
-
+
// Inner classes --------------------------------------------------------------------------------
private class WaitOnConnectionCheckTimerTask extends TimerTask
@@ -783,27 +888,30 @@
if (!isValid)
{
log.debug(ConnectionValidator.this + "'s connection is invalid");
-
- notifyListeners(new Exception("Could not connect to server!"));
+ ConnectionValidator.super.cancel();
if (stopLeaseOnFailure)
{
- log.debug(this + " detected connection failure: stopping LeasePinger");
- MicroRemoteClientInvoker invoker = (MicroRemoteClientInvoker) client.getInvoker();
-
- if (invoker != null)
+ if (trace) log.trace(ConnectionValidator.this + " detected connection failure: stopping LeasePinger");
+ if (leasePinger != null)
{
+ log.debug(ConnectionValidator.this + " shutting down lease pinger: " + leasePinger);
int disconnectTimeout = (failureDisconnectTimeout == -1) ? client.getDisconnectTimeout() : failureDisconnectTimeout;
- invoker.terminateLease(null, disconnectTimeout);
- log.debug(ConnectionValidator.this + " shut down lease pinger");
+ if (trace) log.trace(ConnectionValidator.this + " disconnectTimeout: " + disconnectTimeout);
+ sharedInvoker.terminateLease(null, disconnectTimeout, leasePinger);
}
else
{
- log.debug(ConnectionValidator.this + " unable to shut down lease pinger: client must have shut down");
+ if (trace) log.trace(ConnectionValidator.this + ": lease pinger == null: perhaps leasing is not enabled for this connection");
+ notifyListeners(new Exception("Could not connect to server!"));
}
cancel();
}
+ if (!useClientConnectionIdentity)
+ {
+ notifyListeners(new Exception("Could not connect to server!"));
+ }
}
}
}
14 years, 10 months
JBoss Remoting SVN: r5215 - remoting2/branches/2.x/src/main/org/jboss/remoting.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-14 21:40:05 -0400 (Thu, 14 May 2009)
New Revision: 5215
Modified:
remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionNotifier.java
Log:
JBREM-1132: Improved logging.
Modified: remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionNotifier.java
===================================================================
--- remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionNotifier.java 2009-05-15 01:34:54 UTC (rev 5214)
+++ remoting2/branches/2.x/src/main/org/jboss/remoting/ConnectionNotifier.java 2009-05-15 01:40:05 UTC (rev 5215)
@@ -43,7 +43,7 @@
{
try
{
- log.debug("Server connection lost to client (session id = " + clientSessionId);
+ log.debug(this + " Server connection lost to client (session id = " + clientSessionId);
Client client = new Client(new InvokerLocator(locatorurl), requestPayload);
client.setSessionId(clientSessionId);
@@ -56,7 +56,9 @@
Iterator it = localListeners.iterator();
while (it.hasNext())
{
- ((ConnectionListener) it.next()).handleConnectionException(null, client);
+ ConnectionListener listener = (ConnectionListener) it.next();
+ listener.handleConnectionException(null, client);
+ log.debug(this + " notified " + listener + " of connection lost to: " + clientSessionId);
}
}
catch(Exception e)
@@ -71,7 +73,7 @@
{
if(log.isTraceEnabled())
{
- log.trace("Client disconnected (session id = " + clientSessionId);
+ log.trace(this + " Client disconnected (session id = " + clientSessionId);
}
Client client = new Client(new InvokerLocator(locatorURL), requestPayload);
client.setSessionId(clientSessionId);
14 years, 10 months
JBoss Remoting SVN: r5214 - remoting2/branches/2.x/src/main/org/jboss/remoting.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-14 21:34:54 -0400 (Thu, 14 May 2009)
New Revision: 5214
Modified:
remoting2/branches/2.x/src/main/org/jboss/remoting/Client.java
Log:
JBREM-1132: (1) Added new connect() and notifyListeners(); (2) Clients can share ConnectionValidators; (3) dialed down logging.
Modified: remoting2/branches/2.x/src/main/org/jboss/remoting/Client.java
===================================================================
--- remoting2/branches/2.x/src/main/org/jboss/remoting/Client.java 2009-05-13 08:01:07 UTC (rev 5213)
+++ remoting2/branches/2.x/src/main/org/jboss/remoting/Client.java 2009-05-15 01:34:54 UTC (rev 5214)
@@ -167,13 +167,20 @@
public static final String INVOKER_DESTRUCTION_DELAY = "invokerDestructionDelay";
public static final String THROW_CALLBACK_EXCEPTION = "throwCallbackException";
+
+ private static Map connectionValidators = new HashMap();
+ private static Object connectionValidatorLock = new Object();
+ static final String CLIENT = "client";
+ static final String CONNECTION_LISTENER = "connectionListener";
+
/** The key to use to specify that parameters for objects created by Client should be taken,
* in addition to the metadata map, from the InvokerLocator and from the Client's configuration map.
*/
public static final String USE_ALL_PARAMS = "useAllParams";
private static final Logger log = Logger.getLogger(Client.class);
+ private static boolean trace = log.isTraceEnabled();
private static final long serialVersionUID = 5679279425009837934L;
@@ -198,6 +205,7 @@
private InvokerLocator locator;
private ConnectionValidator connectionValidator = null;
+ private ConnectionValidatorKey connectionValidatorKey;
private Map configuration = new HashMap();
private Map callbackConnectors = new HashMap();
@@ -213,6 +221,10 @@
private int invokerDestructionDelay = 0;
+ private Set connectionListeners = new HashSet();
+
+ private boolean useClientConnectionIdentity;
+
// Constructors ---------------------------------------------------------------------------------
/**
@@ -420,7 +432,7 @@
if (invoker == null)
{
throw new RuntimeException("Can not add connection listener to remoting client " +
- "until client has been connected.");
+ "while client is not connected.");
}
else
{
@@ -431,11 +443,57 @@
}
}
- if (connectionValidator == null)
+ synchronized (connectionValidatorLock)
{
- connectionValidator = new ConnectionValidator(this, metadata);
+ if (trace) log.trace(this + " in addConnectionListener()");
+ if (connectionValidator == null)
+ {
+ Map map = new HashMap(configuration);
+ map.putAll(metadata);
+ connectionValidatorKey = new ConnectionValidatorKey(invoker, map);
+ WeakReference ref = (WeakReference) connectionValidators.get(connectionValidatorKey);
+ if (ref == null)
+ {
+ connectionValidator = new ConnectionValidator(this, metadata);
+ connectionValidators.put(connectionValidatorKey, new WeakReference(connectionValidator));
+ connectionValidator.addConnectionListener(this, listener);
+ if (trace) log.trace(this + ": created " + connectionValidator);
+ }
+ else
+ {
+ connectionValidator = (ConnectionValidator) ref.get();
+ if (connectionValidator.addConnectionListener(this, listener))
+ {
+ if (trace) log.trace(this + ": reusing from static table: " + connectionValidator);
+ }
+ else
+ {
+ if (trace) log.trace(this + ": unable to reuse existing ConnectionValidator in static map: " + connectionValidator);
+ connectionValidator = new ConnectionValidator(this, metadata);
+ connectionValidators.put(connectionValidatorKey, new WeakReference(connectionValidator));
+ connectionValidator.addConnectionListener(this, listener);
+ if (trace) log.trace(this + ": current ConnectionValidator is stopped: created " + connectionValidator);
+ }
+ }
+ }
+ else
+ {
+ if (connectionValidator.addConnectionListener(this, listener))
+ {
+ if (trace) log.trace(this + ": reusing from local reference: " + connectionValidator);
+ }
+ else
+ {
+ if (trace) log.trace(this + ": unable to reuse ConnectionValidator from local reference: " + connectionValidator);
+ connectionValidator = new ConnectionValidator(this, metadata);
+ connectionValidators.put(connectionValidatorKey, new WeakReference(connectionValidator));
+ connectionValidator.addConnectionListener(this, listener);
+ if (trace) log.trace(this + ": current ConnectionValidator is stopped: created " + connectionValidator);
+ }
+ }
+
+ connectionListeners.add(listener);
}
- connectionValidator.addConnectionListener(listener);
}
/**
@@ -444,11 +502,36 @@
*/
public boolean removeConnectionListener(ConnectionListener listener)
{
- if (connectionValidator == null)
+ if (trace) log.trace(this + ".removeConnectionListener(" + listener + ")");
+ boolean isRemoved = false;
+ synchronized (connectionValidatorLock)
{
- return false;
+ if (connectionValidator == null)
+ {
+ return false;
+ }
+ isRemoved = connectionValidator.removeConnectionListener(this, listener);
+ if (connectionValidator.isStopped())
+ {
+ if (connectionValidators.remove(connectionValidatorKey) != null)
+ {
+ log.debug(this + ".removeConnectionListener() removed from static map: " + connectionValidator);
+ }
+ connectionValidator = null;
+ connectionValidatorKey = null;
+ }
+ connectionListeners.remove(listener);
+ if (connectionListeners.isEmpty())
+ {
+ connectionValidator = null;
+ connectionValidatorKey = null;
+ }
+ if (connectionValidator == null)
+ {
+ if (trace) log.trace(this + " set connectionValidator to null");
+ }
}
- return connectionValidator.removeConnectionListener(listener);
+ return isRemoved;
}
/**
@@ -494,6 +577,41 @@
*/
public void connect() throws Exception
{
+ connect(null, null);
+ }
+
+ /**
+ * Will cause the underlying transport to make connection to the target server. This is
+ * important for any stateful transports, like socket or multiplex. This is also when a client
+ * lease with the server is started. If listener is not null, it will be registered to
+ * receive a callback if the connection fails.
+ */
+ public void connect(ConnectionListener listener) throws Exception
+ {
+ connect(listener, null);
+ }
+
+ /**
+ * Will cause the underlying transport to make connection to the target server. This is
+ * important for any stateful transports, like socket or multiplex. This is also when a client
+ * lease with the server is started. If listener is not null, it will be registered to
+ * receive a callback if the connection fails.
+ * <p>
+ *
+ * If this version of connect() is used, and leasing is enabled, the concept of "connection
+ * identity" is enforced. That is, the ConnectionValidator used by this Client will be
+ * tied to the LeasePinger currently used by the MicroRemoteClientInvoker created or reused
+ * in this method, and that LeasePinger will be tied to this Client and its ConnectionValidator.
+ * If the ConnectionValidator used by any of the Clients associated with the MicroRemoteClientInvoker
+ * used by this Client detects a broken connection, it will shut down that LeasePinger.
+ * Moreover, each ConnectionValidator associated with that LeasePinger will notify its
+ * ConnectionListeners of the broken connection. At that point, the LeasePinger will be
+ * destroyed, and all of the associated Clients will be disconnected.
+ */
+ public void connect(ConnectionListener listener, Map metadata) throws Exception
+ {
+ log.debug(this + ".connect(" + listener + ")");
+ if (trace) log.trace(this + ": metadata = " + metadata);
if (isConnected())
return;
@@ -512,9 +630,10 @@
invoker = InvokerRegistry.createClientInvoker(locator, configuration);
}
- connect(invoker);
+ connect(invoker, listener, metadata);
connected = true;
+ log.debug(this + " is connected");
}
/**
@@ -525,17 +644,15 @@
*/
public void disconnect()
{
+ if (trace) log.trace(this + " entering disconnect()");
+
+ connected = false;
+
if (invoker != null)
{
// this is a noop if no lease is active
invoker.terminateLease(sessionId, disconnectTimeout);
-
- if (connectionValidator != null)
- {
- connectionValidator.stop();
- connectionValidator = null;
- }
-
+
// Need to remove myself from registry so will not keep reference to me since I am of no
// use now. Will have to create a new one.
@@ -560,7 +677,7 @@
invokerDestructionTimer.schedule(task, invokerDestructionDelay);
}
- log.trace(this + " scheduled destruction of " + invoker);
+ if (trace) log.trace(this + " scheduled destruction of " + invoker);
}
}
else
@@ -570,8 +687,30 @@
invoker = null;
}
-
- connected = false;
+
+ synchronized (connectionValidatorLock)
+ {
+ if (connectionValidator != null)
+ {
+ Iterator it = connectionListeners.iterator();
+ while (it.hasNext())
+ {
+ ConnectionListener listener = (ConnectionListener) it.next();
+ connectionValidator.removeConnectionListener(this, listener);
+ }
+ if (connectionValidator.isStopped())
+ {
+ if (connectionValidators.remove(connectionValidatorKey) != null)
+ {
+ if (trace) log.trace(this + ".disconnect() removed from static map: " + connectionValidator);
+ }
+ }
+
+ connectionValidator = null;
+ connectionValidatorKey = null;
+ }
+ }
+ log.debug(this + " is disconnected");
}
/**
@@ -1252,7 +1391,7 @@
{
if (e.getCause() != null && e.getCause() instanceof SocketTimeoutException)
{
- if (log.isTraceEnabled()) log.trace(this + ": getCallbacks() timed out: returning empty list");
+ if (trace) log.trace(this + ": getCallbacks() timed out: returning empty list");
return new ArrayList();
}
throw e;
@@ -1596,23 +1735,61 @@
public String toString()
{
- return "Client[" + System.identityHashCode(this) + "]";
+ return "Client[" + System.identityHashCode(this) + ":" + sessionId + "]";
}
// Package protected ----------------------------------------------------------------------------
+ void notifyListeners()
+ {
+ synchronized (connectionValidatorLock)
+ {
+ log.debug(this + " entering notifyListeners(): " + connectionValidator);
+ if (connectionValidator != null)
+ {
+ synchronized (connectionValidator)
+ {
+ if (connectionValidator.isStopped())
+ {
+ if (trace) log.trace(this + ": " + connectionValidator + " is stopped");
+ }
+ else
+ {
+ if (trace) log.trace(this + ": " + connectionValidator + " is not stopped");
+ if (trace) log.trace(this + " calling connectionValidator.notifyListeners()");
+ connectionValidator.notifyListeners(new Exception("Could not connect to server!"));
+ Iterator it = connectionListeners.iterator();
+ while (it.hasNext())
+ {
+ ConnectionListener listener = (ConnectionListener) it.next();
+ connectionValidator.removeConnectionListener(this, listener);
+ }
+ if (connectionValidators.remove(connectionValidatorKey) != null)
+ {
+ if (trace) log.trace(this + ".notifyAndDisconnect() removed from static map: " + connectionValidator);
+ }
+ }
+ }
+ connectionValidator = null;
+ connectionValidatorKey = null;
+ }
+
+ log.debug(this + " leaving notifyListeners()");
+ }
+ }
+
// Protected ------------------------------------------------------------------------------------
// Private --------------------------------------------------------------------------------------
- private void connect(ClientInvoker invoker)
+ private void connect(ClientInvoker invoker, ConnectionListener listener, Map metadata)
{
if (invoker != null)
{
invoker.connect();
try
{
- setupClientLease(invoker);
+ setupClientLease(invoker, listener, metadata);
}
catch (Throwable throwable)
{
@@ -1621,6 +1798,7 @@
e.initCause(throwable);
throw e;
}
+ log.debug(this + " connected to " + locator);
}
else
{
@@ -1629,7 +1807,7 @@
}
}
- private void setupClientLease(ClientInvoker invoker) throws Throwable
+ private void setupClientLease(ClientInvoker invoker, ConnectionListener listener, Map metadata) throws Throwable
{
long leasePeriod = -1;
boolean enableLease = false;
@@ -1710,10 +1888,26 @@
}
}
+ if (trace) log.trace(this + " enableLease: " + enableLease);
if (enableLease)
{
- invoker.establishLease(sessionId, configuration, leasePeriod);
+ Map temp = new HashMap(configuration);
+ if (metadata != null)
+ {
+ temp.putAll(metadata);
+ }
+ if (useClientConnectionIdentity)
+ {
+ temp.put(CLIENT, this);
+ temp.put(CONNECTION_LISTENER, listener);
+ }
+ if (trace) log.trace(this + " calling MicroRemoteClientInvoker.establishLease()");
+ invoker.establishLease(sessionId, temp, leasePeriod);
}
+ else if (listener != null)
+ {
+ addConnectionListener(listener, metadata);
+ }
}
private Object invoke(Object param, Map metadata, InvokerLocator callbackServerLocator)
@@ -1833,6 +2027,28 @@
{
log.error("invokerDestructionDelay parameter must be a string in integer format: " + param);
}
+
+ param = configuration.get(Remoting.USE_CLIENT_CONNECTION_IDENTITY);
+ if (param instanceof String)
+ {
+ useClientConnectionIdentity = Boolean.valueOf((String) param).booleanValue();
+ }
+ else if (param != null)
+ {
+ log.warn("value of " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " must be a String: " + param);
+ }
+ else
+ {
+ if (locator.getParameters() != null)
+ {
+ param = locator.getParameters().get(Remoting.USE_CLIENT_CONNECTION_IDENTITY);
+ if (param != null)
+ {
+ useClientConnectionIdentity = Boolean.valueOf((String) param).booleanValue();
+ this.configuration.put(Remoting.USE_CLIENT_CONNECTION_IDENTITY, param);
+ }
+ }
+ }
}
private void configureCallbackServerSocketFactory(Map map) throws Exception
@@ -1864,6 +2080,34 @@
}
}
+ static class ConnectionValidatorKey
+ {
+ private ClientInvoker invoker;
+ private Map metadata;
+
+ ConnectionValidatorKey(ClientInvoker invoker, Map metadata)
+ {
+ this.invoker = invoker;
+ this.metadata = metadata;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == null)
+ return false;
+ if (! (o instanceof ConnectionValidatorKey))
+ return false;
+ ConnectionValidatorKey holder = (ConnectionValidatorKey) o;
+ boolean metadataEquals = (metadata == null && holder.metadata == null) || metadata.equals(holder.metadata);
+ return invoker == holder.invoker && metadataEquals;
+ }
+
+ public int hashCode()
+ {
+ return invoker.hashCode() * metadata.hashCode();
+ }
+ }
+
static private InetAddress getLocalHost() throws UnknownHostException
{
if (SecurityUtility.skipAccessControl())
14 years, 10 months
JBoss Remoting SVN: r5213 - remoting2/branches/2.2/docs/guide/en.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 04:01:07 -0400 (Wed, 13 May 2009)
New Revision: 5213
Modified:
remoting2/branches/2.2/docs/guide/en/chap5.xml
Log:
JBREM-1079: Various additions.
Modified: remoting2/branches/2.2/docs/guide/en/chap5.xml
===================================================================
--- remoting2/branches/2.2/docs/guide/en/chap5.xml 2009-05-13 06:27:53 UTC (rev 5212)
+++ remoting2/branches/2.2/docs/guide/en/chap5.xml 2009-05-13 08:01:07 UTC (rev 5213)
@@ -1371,6 +1371,40 @@
<para>These request headers are set automatically when using a remoting
client, but if using another client to send request to the HTTP server
invoker, may want to add these headers.</para>
+
+ <bridgehead>Response headers</bridgehead>
+
+ <para>If a request on the HTTP transport is made with the
+ <classname>org.jboss.remoting.Client</classname> method</para>
+
+ <programlisting>public Object invoke(Object param, Map metadata) throws Throwable</programlisting>
+
+ <para>then
+ <classname>org.jboss.remoting.transport.http.HTTPClientInvoker</classname>
+ returns the HTTP response headers in a map in metadata, associated with
+ the key
+ <code>org.jboss.remoting.transport.http.HTTPMetadataConstants.RESPONSE_HEADERS</code>
+ (actual value "ResponseHeaders"). For example, the response header "Date"
+ can be retrieved as follows:</para>
+
+ <programlisting>Object payload = ... ;
+HashMap metadata = new HashMap();
+client.invoke(payload, metadata);
+Map responseHeaders = (Map) metadata.get(HTTPMetadataConstants.RESPONSE_HEADERS);
+String date = (String) responseHeaders.get("Date");</programlisting>
+
+ <bridgehead>CR/LF in HTTP transport</bridgehead>
+
+ <para>By default, the HTTP transport uses
+ <classname>org.jboss.remoting.marshal.http.HTTPMarshaller</classname> and
+ <classname>org.jboss.remoting.marshal.http.HTTPUnMarshaller</classname> to
+ marshal and unmarshal invocations and responses. Prior to Remoting version
+ 2.2.3, <classname>HTTPUnMarshaller</classname> stripped CR/LF characters. As
+ of version 2.2.3, the default behavior remains the same, but it is possible
+ to change the behavior, on the client and the server, by setting the
+ parameter <code>HTTPUnMarshaller.PRESERVE_LINES</code> (actual value
+ "preserveLines") to "true". </para>
+
</section>
<section>
@@ -1617,6 +1651,29 @@
to is changed, will need to change the value for the InvokerLocator in
the Connector configuration mentioned above.</para>
+ <para><emphasis role="bold">Note.</emphasis> Prior to Remoting version 2.2.3,
+ <classname>org.jboss.remoting.transport.servlet.ServletServerInvoker</classname>
+ generated a single MBean ObjectName for representing
+ <classname>ServletServerInvoker</classname>s as MBeans, which meant that
+ an MBeanServer could be aware of only a single
+ <classname>ServletServerInvoker</classname> MBean. As of version 2.2.3, that
+ restriction can be eliminated by setting the parameter
+ <code>org.jboss.remoting.transport.servlet.ServletServerInvoker.CREATE_UNIQUE_OBJECT_NAME</code>
+ (actual value "createUniqueObjectName") to "true".</para>
+
+ <section>
+ <title>Configuration</title>
+
+ <para><emphasis role="bold">unwrapSingletonArrays</emphasis> - If the map
+ returned by <methodname>javax.servlet.http.HttpServletRequest.getParameterMap()</methodname>
+ maps a String key to an array of length one, the value in the array will be extracted
+ and associated with the key.</para>
+
+ <para><emphasis role="bold">createUniqueObjectName</emphasis> - If set to "true",
+ each <classname>InvokerLocator</classname> will be transformed into a unique
+ ObjectName.</para>
+ </section>
+
<bridgehead>Issues</bridgehead>
<para>One of the issues of using Servlet invoker is that the invocation
@@ -6509,6 +6566,17 @@
responseHeaders.put(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, "Custom response code and message from remoting server");
</programlisting>
+ <para><emphasis role="bold">RESPONSE_HEADERS</emphasis> (actual value is
+ 'ResponseHeaders') - key for returning the value of
+ <methodname>java.net.URLConnection.getHeaderFields()</methodname>. In other
+ words, a map containing all of the response headers is stored in the
+ metadata map. For example,</para>
+
+ <programlisting>Object payload = ... ;
+HashMap metadata = new HashMap();
+client.invoke(payload, metadata);
+Map responseHeaders = (Map) metadata.get(HTTPMetadataConstants.RESPONSE_HEADERS);</programlisting>
+
<para><emphasis role="bold">NO_THROW_ON_ERROR</emphasis> (actual value is
'NoThrowOnError') - key indicating if http client invoker (for transports
http, https, servlet, and sslservlet) should throw an exception if the
14 years, 10 months
JBoss Remoting SVN: r5212 - remoting2/branches/2.2/src/tests/org/jboss/test/remoting/transport/web.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 02:27:53 -0400 (Wed, 13 May 2009)
New Revision: 5212
Modified:
remoting2/branches/2.2/src/tests/org/jboss/test/remoting/transport/web/WebInvokerTestClient.java
Log:
JBREM-1130: Allows server to use either "localhost" or "127.0.0.1" to accommodate InvokerLocator in Remoting 1.x, for versioning tests.
Modified: remoting2/branches/2.2/src/tests/org/jboss/test/remoting/transport/web/WebInvokerTestClient.java
===================================================================
--- remoting2/branches/2.2/src/tests/org/jboss/test/remoting/transport/web/WebInvokerTestClient.java 2009-05-13 05:47:42 UTC (rev 5211)
+++ remoting2/branches/2.2/src/tests/org/jboss/test/remoting/transport/web/WebInvokerTestClient.java 2009-05-13 06:27:53 UTC (rev 5212)
@@ -101,8 +101,18 @@
String transport = locatorURI.substring(0, index);
String params = (isServlet(transport) ? ",createUniqueObjectName=true" : "");
String port = "servlet".equals(transport) ? "8080" : ("sslservlet".equals(transport) ? "8443" : "8888");
- assertEquals("jboss.remoting:service=invoker,transport= " + transport + ",host=localhost,port=" + port + params, response);
-
+ System.out.println("ObjectName: " + response);
+ String host = null;
+ if (((String) response).indexOf("127.0.0.1") >= 0)
+ {
+ host = "127.0.0.1";
+ }
+ else
+ {
+ host = "localhost";
+ }
+ assertEquals("jboss.remoting:service=invoker,transport= " + transport + ",host=" + host + ",port=" + port + params, response);
+
checkUserAgent(remotingClient, metadata);
makeExceptionInvocation(remotingClient, metadata);
14 years, 10 months
JBoss Remoting SVN: r5211 - remoting2/branches/2.x/docs/guide/en.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 01:47:42 -0400 (Wed, 13 May 2009)
New Revision: 5211
Modified:
remoting2/branches/2.x/docs/guide/en/chap5.xml
Log:
JBREM-1121: Added section about configuring socket factories by the InvokerLocator.
Modified: remoting2/branches/2.x/docs/guide/en/chap5.xml
===================================================================
--- remoting2/branches/2.x/docs/guide/en/chap5.xml 2009-05-13 05:29:47 UTC (rev 5210)
+++ remoting2/branches/2.x/docs/guide/en/chap5.xml 2009-05-13 05:47:42 UTC (rev 5211)
@@ -220,7 +220,7 @@
</section>
- <section>
+ <section id="section-declarative-configuration-mbeans" xreflabel="Declarative configuration: MBeans">
<title>Declarative configuration: MBeans</title>
<para>One configuration option discussed in Section <xref
@@ -341,7 +341,7 @@
with a / (slash).</para>
</section>
- <section>
+ <section id="section-declarative-configuration-pojos" xreflabel="Declarative configuration: POJOs">
<title>Declarative configuration: POJOs</title>
<para>The last configuration option discussed in Section <xref
@@ -4485,6 +4485,32 @@
of JBoss MBeans.)</para>
</section>
+ <section >
+ <title>Client side configuration from the JBoss Application Server</title>
+
+ <para>As described in sections <xref linkend="section-declarative-configuration-mbeans"/>
+ and <xref linkend="section-declarative-configuration-pojos"/>,
+ the declarative xml files used by the Application Server can be used to configure the
+ client by way of the parameters included in the <classname>InvokerLocator</classname>.
+ However, a peculiarity in the way socket factories are created on the client
+ restricts the parameters taken into consideration to those passed in the
+ configuration map passed to the <classname>org.jboss.remoting.Client</classname>
+ constructor. The following two parameters, introduced in releases 2.4.0.SP1 and
+ 2.5.2, respectively, eliminate that restriction.</para>
+
+ <para><emphasis role="bold">org.jboss.remoting.Remoting.SOCKET_FACTORY_NAME</emphasis> (actual value
+ is 'socketFactory') - key for giving the name of the socket factory class to be used
+ by clients.</para>
+
+ <para><emphasis role="bold">org.jboss.remoting.Remoting.USE_ALL_SOCKET_FACTORY_PARAMS</emphasis> (actual value
+ is 'useAllSocketFactoryParams') - key for indicating that all socket factory parameters
+ in the <classname>InvokerLocator</classname> should be used by clients.</para>
+
+ <para>Note that the parameter <code>org.jboss.remoting.Remoting.CONFIG_OVERRIDES_LOCATOR</code>
+ (actual value "configOverridesLocator"), described in section
+ <xref linkend="section-org-jboss-remoting-Remoting"/>, is also relevant.</para>
+ </section>
+
<section>
<title>Socket creation listeners</title>
@@ -5967,7 +5993,7 @@
</section>
- <section>
+ <section id="section-org-jboss-remoting-Remoting" xreflabel="org.jboss.remoting.Remoting">
<title>org.jboss.remoting.Remoting</title>
<para><emphasis role="bold">CUSTOM_SERVER_SOCKET_FACTORY</emphasis>
14 years, 10 months
JBoss Remoting SVN: r5210 - remoting2/branches/2.2/docs/guide/en.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 01:29:47 -0400 (Wed, 13 May 2009)
New Revision: 5210
Modified:
remoting2/branches/2.2/docs/guide/en/chap5.xml
Log:
JBREM-1121: Added section about configuring socket factories by the InvokerLocator.
Modified: remoting2/branches/2.2/docs/guide/en/chap5.xml
===================================================================
--- remoting2/branches/2.2/docs/guide/en/chap5.xml 2009-05-13 04:23:39 UTC (rev 5209)
+++ remoting2/branches/2.2/docs/guide/en/chap5.xml 2009-05-13 05:29:47 UTC (rev 5210)
@@ -186,7 +186,7 @@
<classname>org.jboss.test.remoting.configuration.SocketClientConfigurationTestCase</classname>.</para>
</section>
- <section>
+ <section id="section-declarative-configuration" xreflabel="Declarative configuration">
<title>Declarative configuration</title>
<para>The configuration option discussed at the end of the previous
@@ -4842,6 +4842,28 @@
</section>
<section>
+ <title>Client side configuration from the JBoss Application Server</title>
+
+ <para>As described in section <xref linkend="section-declarative-configuration"/>
+ the declarative xml files used by the Application Server can be used to configure the
+ client by way of the parameters included in the <classname>InvokerLocator</classname>.
+ However, a peculiarity in the way socket factories are created on the client
+ restricts the parameters taken into consideration to those passed in the
+ configuration map passed to the <classname>org.jboss.remoting.Client</classname>
+ constructor. The following two parameters, introduced in releases 2.2.2.SP9 and
+ 2.2.3, respectively, eliminate that restriction.</para>
+
+ <para><emphasis role="bold">org.jboss.remoting.Remoting.SOCKET_FACTORY_NAME</emphasis> (actual value
+ is 'socketFactory') - key for giving the name of the socket factory class to be used
+ by clients.</para>
+
+ <para><emphasis role="bold">org.jboss.remoting.Remoting.USE_ALL_SOCKET_FACTORY_PARAMS</emphasis> (actual value
+ is 'useAllSocketFactoryParams') - key for indicating that all socket factory parameters
+ in the <classname>InvokerLocator</classname> should be used by clients.</para>
+
+ </section>
+
+ <section>
<title>Socket creation listeners</title>
<para>
14 years, 10 months
JBoss Remoting SVN: r5209 - remoting2/branches/2.2.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 00:23:39 -0400 (Wed, 13 May 2009)
New Revision: 5209
Modified:
remoting2/branches/2.2/build.xml
Log:
JBREM-1131: Updated version to 2.2.3.
Modified: remoting2/branches/2.2/build.xml
===================================================================
--- remoting2/branches/2.2/build.xml 2009-05-13 04:14:59 UTC (rev 5208)
+++ remoting2/branches/2.2/build.xml 2009-05-13 04:23:39 UTC (rev 5209)
@@ -38,9 +38,9 @@
<!-- Module name(s) & version -->
<property name="module.name" value="remoting"/>
<property name="module.Name" value="JBoss Remoting"/>
- <property name="module.version" value="2.2.2.SP12"/>
+ <property name="module.version" value="2.2.3"/>
<!-- extension is for the file suffix to use for distribution build -->
- <property name="module.version.extension" value="2_2_2_SP12"/>
+ <property name="module.version.extension" value="2_2_3"/>
<property name="implementation.url" value="http://www.jboss.org/products/remoting"/>
<property name="root.dir" value="${basedir}"/>
14 years, 10 months
JBoss Remoting SVN: r5208 - remoting2/branches/2.2/docs/guide/en.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 00:14:59 -0400 (Wed, 13 May 2009)
New Revision: 5208
Modified:
remoting2/branches/2.2/docs/guide/en/master.xml
Log:
JBREM-1131: Updated version and date.
Modified: remoting2/branches/2.2/docs/guide/en/master.xml
===================================================================
--- remoting2/branches/2.2/docs/guide/en/master.xml 2009-05-13 04:13:00 UTC (rev 5207)
+++ remoting2/branches/2.2/docs/guide/en/master.xml 2009-05-13 04:14:59 UTC (rev 5208)
@@ -23,9 +23,9 @@
<bookinfo>
<title>JBoss Remoting Guide</title>
- <subtitle>JBoss Remoting version 2.2.2.SP11</subtitle>
+ <subtitle>JBoss Remoting version 2.2.3</subtitle>
- <releaseinfo>December 31, 2008</releaseinfo>
+ <releaseinfo>May 13, 2009</releaseinfo>
<mediaobject>
<imageobject>
14 years, 10 months
JBoss Remoting SVN: r5207 - remoting2/branches/2.2/docs/guide/en.
by jboss-remoting-commits@lists.jboss.org
Author: ron.sigal(a)jboss.com
Date: 2009-05-13 00:13:00 -0400 (Wed, 13 May 2009)
New Revision: 5207
Modified:
remoting2/branches/2.2/docs/guide/en/chap8.xml
Log:
JBREM-1128: Added discussion of "connection identity".
Modified: remoting2/branches/2.2/docs/guide/en/chap8.xml
===================================================================
--- remoting2/branches/2.2/docs/guide/en/chap8.xml 2009-05-13 04:05:31 UTC (rev 5206)
+++ remoting2/branches/2.2/docs/guide/en/chap8.xml 2009-05-13 04:13:00 UTC (rev 5207)
@@ -295,6 +295,51 @@
</orderedlist>
+ <para><emphasis role="bold">Note.</emphasis> As of release 2.2.3, an important
+ concept related to connection monitoring, <emphasis>connection identity</emphasis>,
+ is available. Suppose that leasing is enabled and that a client invoker
+ stops and is replaced by a new client invoker. If the
+ replacement occurs quickly, the server side <classname>Lease</classname> may never
+ miss a ping, in which there is no evidence that anything changed on the client side.
+ That is, the connection is still alive, as far as the server is concerned. That
+ semantics might be perfectly acceptable for some applications, but other
+ applications might interpret the same events as a connection failure followed by
+ a new connection. Remoting can be configured to treat a connection as being
+ defined by a client/server pair, which supports the second category of applications.
+ </para>
+
+ <para>More specifically, when configured to do so by setting the parameter
+ <code>org.jboss.remoting.Remoting.USE_CLIENT_CONNECTION_IDENTITY</code> (actual value
+ "useClientConnectionIdentity") to "true", Remoting identifies a connection with a
+ <classname>LeasePinger</classname>/<classname>Lease</classname> pair. A
+ <classname>Client</classname> participates in a connection when it is connected
+ by way of the new method</para>
+
+ <programlisting>public void connect(ConnectionListener listener, Map metadata) throws Exception;</programlisting>
+
+ <para>This method serves to connect the <classname>Client</classname> to the server
+ by way of a new or existing client invoker, and it also (1) registers the
+ <classname>ConnectionListener</classname> with the <classname>Client</classname>'s
+ new or exiting <classname>ConnectionValidator</classname> and (2) registers
+ the <classname>ConnectionValidator</classname> with the client invoker's
+ <classname>LeasePinger</classname>. Subsequently, if any
+ <classname>ConnectionValidator</classname> registered with that
+ <classname>LeasePinger</classname> detects a connection failure, it will
+ (if "stopLeaseOnFailure" is "true") stop the <classname>LeasePinger</classname>,
+ and the <classname>LeasePinger</classname> will cause each registered
+ <classname>ConnectionValidator</classname>s to notify each of its
+ registered <classname>ConnectionListener</classname>s of the connection failure.
+ Once the <classname>LeasePinger</classname> has been shut down and all of the
+ notifications have been made, the connection anchored by the
+ <classname>LeasePinger</classname> is defunct, and the
+ associated <classname>Client</classname>'s should be disconnected by a call
+ to <methodname>Client.disconnect()</methodname>. If such a <classname>Client</classname>
+ is reconnected by a call to <methodname>Client.connect()</methodname>, it
+ will be associated with a new <classname>LeasePinger</classname> and, therefore,
+ a new connection.</para>
+
+ <para>Relevant parameters:</para>
+
<para><emphasis role="bold">TIE_TO_LEASE</emphasis> (actual value
"tieToLease") - specifies whether <classname>ConnectionValidator</classname>
should treat the failure of a related lease on the server side as a
@@ -307,5 +352,9 @@
<classname>org.jboss.remoting.LeasePinger</classname>, if any. The default
value is "true".</para>
+ <para><emphasis role="bold">org.jboss.remoting.Remoting.USE_CLIENT_CONNECTION_IDENTITY</emphasis>
+ (actual value "useClientConnectionIdentity") - tells Remoting to adhere to the
+ new "connection identity" semantics.</para>
+
</section>
</chapter>
\ No newline at end of file
14 years, 10 months