diff --git a/common/source/java/ch/systemsx/cisd/common/api/retry/RetryCaller.java b/common/source/java/ch/systemsx/cisd/common/api/retry/RetryCaller.java index d99b3bb5df4b9fb09c881f9556077ffec03fcdd9..307693f5ce62ebd3c7fe83d11bdc29da53a262bb 100644 --- a/common/source/java/ch/systemsx/cisd/common/api/retry/RetryCaller.java +++ b/common/source/java/ch/systemsx/cisd/common/api/retry/RetryCaller.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.common.api.retry; import java.net.SocketException; import java.net.SocketTimeoutException; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.remoting.RemoteAccessException; import org.springframework.remoting.RemoteConnectFailureException; @@ -115,12 +116,19 @@ public abstract class RetryCaller<T, E extends Throwable> } if (e instanceof RemoteAccessException) { - return e.getCause() instanceof SocketTimeoutException - || e.getCause() instanceof SocketException; + Throwable cause = e.getCause(); + Throwable rootCause = ExceptionUtils.getRootCause(e); + + return isRetryableRemoteAccessCause(cause) || isRetryableRemoteAccessCause(rootCause); } return false; } + private boolean isRetryableRemoteAccessCause(Throwable cause) + { + return cause instanceof SocketTimeoutException || cause instanceof SocketException; + } + private boolean shouldRetry() { return retryCounter < configuration.getMaximumNumberOfRetries(); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/openbisauth/OpenBISAuthenticationInterceptor.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/openbisauth/OpenBISAuthenticationInterceptor.java index 63371f70ecb3957f68614ec0b41ab7be5e7535b3..babde6bc4a0de3115c21c77b8e54f80ce84f55be 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/openbisauth/OpenBISAuthenticationInterceptor.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/openbisauth/OpenBISAuthenticationInterceptor.java @@ -127,38 +127,48 @@ public class OpenBISAuthenticationInterceptor implements MethodInterceptor, ICre private final void authenticate() { - if (operationLog.isDebugEnabled()) - { - operationLog.debug("Authenticating to openBIS server as user '" + username + "'."); - } - SessionContextDTO sessionContextDTO = service.tryAuthenticate(username, password); - String sessionToken = - sessionContextDTO == null ? null : sessionContextDTO.getSessionToken(); - if (sessionToken == null) + try { - final String msg = - "Authentication failure to openBIS server. Most probable cause: user or password are invalid."; - throw new ConfigurationFailureException(msg); - } - sessionHolder.setSessionToken(sessionToken); - DataStoreServerInfo dataStoreServerInfo = new DataStoreServerInfo(); - dataStoreServerInfo.setPort(port); - dataStoreServerInfo.setUseSSL(useSSL); - dataStoreServerInfo.setDataStoreCode(sessionHolder.getDataStoreCode()); - if (downloadUrl == null) + if (operationLog.isDebugEnabled()) + { + operationLog.debug("Authenticating to openBIS server as user '" + username + "'."); + } + SessionContextDTO sessionContextDTO = service.tryAuthenticate(username, password); + String sessionToken = + sessionContextDTO == null ? null : sessionContextDTO.getSessionToken(); + if (sessionToken == null) + { + final String msg = + "Authentication failure to openBIS server. Most probable cause: user or password are invalid."; + throw new ConfigurationFailureException(msg); + } + sessionHolder.setSessionToken(sessionToken); + DataStoreServerInfo dataStoreServerInfo = new DataStoreServerInfo(); + dataStoreServerInfo.setPort(port); + dataStoreServerInfo.setUseSSL(useSSL); + dataStoreServerInfo.setDataStoreCode(sessionHolder.getDataStoreCode()); + if (downloadUrl == null) + { + final String msg = + "'" + DssPropertyParametersUtil.DOWNLOAD_URL_KEY + "' can't be null."; + throw new ConfigurationFailureException(msg); + } + dataStoreServerInfo.setDownloadUrl(downloadUrl); + dataStoreServerInfo.setSessionToken(sessionTokenManager.drawSessionToken()); + dataStoreServerInfo.setServicesDescriptions(pluginTaskDescriptions); + dataStoreServerInfo.setArchiverConfigured(archiverConfigured); + dataStoreServerInfo.setTimeoutInMinutes(timeoutInMinutes); + dataStoreServerInfo.setDataSourceDefinitions(dataSourceProvider.getAllDataSourceDefinitions()); + + service.registerDataStoreServer(sessionToken, dataStoreServerInfo); + } catch (Exception e) { - final String msg = - "'" + DssPropertyParametersUtil.DOWNLOAD_URL_KEY + "' can't be null."; - throw new ConfigurationFailureException(msg); + // Clear the session token to repeat the authentication on the next intercepted call. + // If we don't do this the communication between AS and DSS may work incorrectly. For instance, + // AS may keep on using an old entry from data_stores database table and send a stale session token to DSS. + sessionHolder.setSessionToken(null); + throw e; } - dataStoreServerInfo.setDownloadUrl(downloadUrl); - dataStoreServerInfo.setSessionToken(sessionTokenManager.drawSessionToken()); - dataStoreServerInfo.setServicesDescriptions(pluginTaskDescriptions); - dataStoreServerInfo.setArchiverConfigured(archiverConfigured); - dataStoreServerInfo.setTimeoutInMinutes(timeoutInMinutes); - dataStoreServerInfo.setDataSourceDefinitions(dataSourceProvider.getAllDataSourceDefinitions()); - - service.registerDataStoreServer(sessionToken, dataStoreServerInfo); } /** diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java index 9fe666277646303cca5e872d181a15bea0d9041e..c7123e471057dd9dd638d65eca7e4a72eb28541d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ServiceForDataStoreServer.java @@ -68,8 +68,12 @@ import ch.systemsx.cisd.authentication.DefaultSessionManager; import ch.systemsx.cisd.authentication.DummyAuthenticationService; import ch.systemsx.cisd.authentication.IAuthenticationService; import ch.systemsx.cisd.authentication.ISessionManager; +import ch.systemsx.cisd.common.api.retry.RetryCaller; +import ch.systemsx.cisd.common.api.retry.config.DefaultRetryConfiguration; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; +import ch.systemsx.cisd.common.exceptions.InvalidAuthenticationException; import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.common.logging.Log4jSimpleLogger; import ch.systemsx.cisd.common.properties.PropertyUtils; import ch.systemsx.cisd.common.servlet.IRequestContextProvider; import ch.systemsx.cisd.common.servlet.RequestContextProviderAdapter; @@ -488,7 +492,16 @@ public class ServiceForDataStoreServer extends AbstractCommonServer<IServiceForD { operationLog.info("Obtain version of Data Store Server at " + dssURL); } - int dssVersion = service.getVersion(dssSessionToken); + + int dssVersion = + new RetryCaller<Integer, InvalidAuthenticationException>(DefaultRetryConfiguration.getInstance(), new Log4jSimpleLogger(operationLog)) + { + @Override protected Integer call() throws InvalidAuthenticationException + { + return service.getVersion(dssSessionToken); + } + }.callWithRetry(); + if (IDataStoreService.VERSION != dssVersion) { String msg =