From 7dbe1728e608992bcdffa564e3ad471104b4a3dc Mon Sep 17 00:00:00 2001
From: pkupczyk <piotr.kupczyk@id.ethz.ch>
Date: Sun, 12 Jun 2022 23:42:19 +0200
Subject: [PATCH] SSDM-11550 : Personal Access Tokens (PAT) - change the PAT
 decorator to an AOP interceptor to make it play nicely with other existing
 interceptors (e.g. logging)

---
 openbis-common/build.gradle                   |  31 +-
 openbis-common/settings.gradle                |   2 +-
 .../common/pat/IPersonalAccessTokenAware.java |   8 +
 .../pat/IPersonalAccessTokenInvocation.java   |  10 +
 .../pat/PersonalAccessTokenAdvisor.java       |  66 ++
 .../pat/PersonalAccessTokenInterceptor.java   | 100 +++
 .../PersonalAccessTokenInvocationHandler.java |  53 ++
 .../openbis/common/spring/LogAdvisor.java     |   4 +-
 .../server/asapi/v3/ApplicationServerApi.java |   9 +-
 ...PersonalAccessTokenInvocationHandler.java} | 795 ++++++++----------
 ...GetServerInformationOperationExecutor.java |   8 +-
 ...erApiPersonalAccessTokenPostProcessor.java |  26 -
 .../source/java/genericApplicationContext.xml |  23 +-
 13 files changed, 629 insertions(+), 506 deletions(-)
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenAware.java
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenInvocation.java
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenAdvisor.java
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInterceptor.java
 create mode 100644 openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInvocationHandler.java
 rename openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/{pat/ApplicationServerApiPersonalAccessTokenDecorator.java => ApplicationServerApiPersonalAccessTokenInvocationHandler.java} (53%)
 delete mode 100644 openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenPostProcessor.java

diff --git a/openbis-common/build.gradle b/openbis-common/build.gradle
index d58a27cb4d9..4249adffca7 100644
--- a/openbis-common/build.gradle
+++ b/openbis-common/build.gradle
@@ -1,25 +1,28 @@
 evaluationDependsOn(':commonbase')
 evaluationDependsOn(':common')
 evaluationDependsOn(':dbmigration')
+evaluationDependsOn(':authentication')
 
 apply from: '../gradle/javaproject.gradle'
 
 dependencies {
 	api project(':common'),
-		project(':dbmigration'),
-		'googlecode:jsonrpc4j:1.5.3',
-        'fasterxml:jackson-databind:2.9.10.8',
-		'reflections:reflections:0.9.10',
-		'sis:sis-jhdf5:19.04.0',
-		'lemnik:eodsql:2.2-CISD',
-		'springframework:spring-jdbc:5.0.1.RELEASE',
-		'apache:commons-collections4:4.1',
-		'truezip:truezip:6.8.1'
+			project(':dbmigration'),
+			project(':authentication'),
+			'googlecode:jsonrpc4j:1.5.3',
+			'fasterxml:jackson-databind:2.9.10.8',
+			'reflections:reflections:0.9.10',
+			'sis:sis-jhdf5:19.04.0',
+			'lemnik:eodsql:2.2-CISD',
+			'springframework:spring-jdbc:5.0.1.RELEASE',
+			'apache:commons-collections4:4.1',
+			'truezip:truezip:6.8.1'
 
     testImplementation project(path: ':commonbase', configuration: 'tests'),
-                       project(path: ':common', configuration: 'tests'),
-                       project(path: ':dbmigration', configuration: 'tests'),
-                       'fjelmer:classycle:1.4.2',
-                       'testng:testng:6.8-CISD',
-                       'eclipse:jetty-servlet:9.4.44.v20210927'
+			project(path: ':common', configuration: 'tests'),
+			project(path: ':dbmigration', configuration: 'tests'),
+			project(path: ':authentication', configuration: 'tests'),
+			'fjelmer:classycle:1.4.2',
+			'testng:testng:6.8-CISD',
+			'eclipse:jetty-servlet:9.4.44.v20210927'
 }
diff --git a/openbis-common/settings.gradle b/openbis-common/settings.gradle
index f274122a6b8..eb8d818f954 100644
--- a/openbis-common/settings.gradle
+++ b/openbis-common/settings.gradle
@@ -1 +1 @@
-includeFlat 'commonbase', 'common', 'dbmigration'
+includeFlat 'commonbase', 'common', 'dbmigration', 'authentication'
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenAware.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenAware.java
new file mode 100644
index 00000000000..66c18d3c976
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenAware.java
@@ -0,0 +1,8 @@
+package ch.systemsx.cisd.openbis.common.pat;
+
+public interface IPersonalAccessTokenAware
+{
+
+    Object createPersonalAccessTokenInvocationHandler(IPersonalAccessTokenInvocation context);
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenInvocation.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenInvocation.java
new file mode 100644
index 00000000000..677a6ba55bd
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/IPersonalAccessTokenInvocation.java
@@ -0,0 +1,10 @@
+package ch.systemsx.cisd.openbis.common.pat;
+
+public interface IPersonalAccessTokenInvocation
+{
+
+    <T> T proceedWithOriginalArguments();
+
+    <T> T proceedWithNewFirstArgument(Object argument);
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenAdvisor.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenAdvisor.java
new file mode 100644
index 00000000000..8eda113eec1
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenAdvisor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.common.pat;
+
+import org.aopalliance.aop.Advice;
+import org.springframework.aop.ClassFilter;
+import org.springframework.aop.MethodMatcher;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.aop.support.RootClassFilter;
+import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
+import org.springframework.core.Ordered;
+
+public class PersonalAccessTokenAdvisor extends DefaultPointcutAdvisor
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public static final int ORDER = Ordered.HIGHEST_PRECEDENCE;
+
+    PersonalAccessTokenAdvisor()
+    {
+        super(createPointcut(), createAdvice());
+        setOrder(ORDER);
+    }
+
+    private static Advice createAdvice()
+    {
+        return new PersonalAccessTokenInterceptor();
+    }
+
+    private static Pointcut createPointcut()
+    {
+        return new PersonalAccessTokenAwarePointcut();
+    }
+
+    private static class PersonalAccessTokenAwarePointcut implements Pointcut
+    {
+        @Override
+        public MethodMatcher getMethodMatcher()
+        {
+            return MethodMatcher.TRUE;
+        }
+
+        @Override
+        public ClassFilter getClassFilter()
+        {
+            return new RootClassFilter(IPersonalAccessTokenAware.class);
+        }
+    }
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInterceptor.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInterceptor.java
new file mode 100644
index 00000000000..124da9b9002
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInterceptor.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.common.pat;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.aop.ProxyMethodInvocation;
+
+public final class PersonalAccessTokenInterceptor implements MethodInterceptor, Serializable
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public Object invoke(final MethodInvocation invocation) throws Throwable
+    {
+        final IPersonalAccessTokenAware aware = (IPersonalAccessTokenAware) invocation.getThis();
+
+        final Object handler =
+                aware.createPersonalAccessTokenInvocationHandler(new PersonalAccessTokenInvocation((ProxyMethodInvocation) invocation));
+
+        try
+        {
+            return invocation.getMethod().invoke(handler, invocation.getArguments());
+        } catch (InvocationTargetException e)
+        {
+            if (e.getCause() instanceof PersonalAccessTokenInvocationException)
+            {
+                throw e.getCause().getCause();
+            } else
+            {
+                throw e.getCause();
+            }
+        }
+    }
+
+    private static final class PersonalAccessTokenInvocation implements IPersonalAccessTokenInvocation
+    {
+
+        private final ProxyMethodInvocation originalInvocation;
+
+        private PersonalAccessTokenInvocation(ProxyMethodInvocation originalInvocation)
+        {
+            this.originalInvocation = originalInvocation;
+        }
+
+        @Override public <T> T proceedWithOriginalArguments()
+        {
+            try
+            {
+                return (T) originalInvocation.proceed();
+            } catch (Throwable e)
+            {
+                throw new PersonalAccessTokenInvocationException(e);
+            }
+        }
+
+        @Override public <T> T proceedWithNewFirstArgument(final Object argument)
+        {
+            try
+            {
+                Object[] arguments = originalInvocation.getArguments();
+                arguments[0] = argument;
+                originalInvocation.setArguments(arguments);
+                return (T) originalInvocation.proceed();
+            } catch (Throwable e)
+            {
+                throw new PersonalAccessTokenInvocationException(e);
+            }
+        }
+    }
+
+    private static final class PersonalAccessTokenInvocationException extends RuntimeException
+    {
+
+        PersonalAccessTokenInvocationException(Throwable cause)
+        {
+            super(cause);
+        }
+
+    }
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInvocationHandler.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInvocationHandler.java
new file mode 100644
index 00000000000..265685b891d
--- /dev/null
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/pat/PersonalAccessTokenInvocationHandler.java
@@ -0,0 +1,53 @@
+package ch.systemsx.cisd.openbis.common.pat;
+
+import java.util.Date;
+
+import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.authentication.pat.IPersonalAccessTokenDAO;
+import ch.systemsx.cisd.authentication.pat.PersonalAccessToken;
+import ch.systemsx.cisd.authentication.pat.PersonalAccessTokenSession;
+
+public abstract class PersonalAccessTokenInvocationHandler
+{
+
+    protected abstract IPersonalAccessTokenDAO getPersonalAccessTokenDAO();
+
+    protected String toSessionToken(String sessionTokenOrPAT)
+    {
+        IPersonalAccessTokenDAO patDAO = getPersonalAccessTokenDAO();
+        PersonalAccessToken patToken = patDAO.getTokenByHash(sessionTokenOrPAT);
+
+        if (patToken == null)
+        {
+            return sessionTokenOrPAT;
+        } else
+        {
+            Date now = new Date();
+
+            if (now.before(patToken.getValidFrom()))
+            {
+                throw new InvalidSessionException("Personal access token is not yet valid.");
+            }
+
+            if (now.after(patToken.getValidUntil()))
+            {
+                throw new InvalidSessionException("Personal access token is no longer valid.");
+            }
+
+            patToken.setLastAccessedAt(now);
+            patDAO.updateToken(patToken);
+
+            final PersonalAccessTokenSession patSession =
+                    patDAO.getSessionByUserIdAndSessionName(patToken.getUserId(), patToken.getSessionName());
+
+            if (patSession == null)
+            {
+                throw new InvalidSessionException("Personal access token session does not exist.");
+            } else
+            {
+                return patSession.getHash();
+            }
+        }
+    }
+
+}
diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/spring/LogAdvisor.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/spring/LogAdvisor.java
index 34938bb6b01..a9fa04b2d78 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/spring/LogAdvisor.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/spring/LogAdvisor.java
@@ -22,6 +22,8 @@ import org.springframework.aop.support.DefaultPointcutAdvisor;
 import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
 import org.springframework.core.Ordered;
 
+import ch.systemsx.cisd.openbis.common.pat.PersonalAccessTokenAdvisor;
+
 /**
  * A pointcut advisor which applies the {@link LogInterceptor} advice to classes with the {@link Logging} annotation.
  * 
@@ -32,7 +34,7 @@ public class LogAdvisor extends DefaultPointcutAdvisor
 
     private static final long serialVersionUID = 1L;
 
-    public static final int ORDER = Ordered.HIGHEST_PRECEDENCE;
+    public static final int ORDER = PersonalAccessTokenAdvisor.ORDER + 1;
 
     LogAdvisor()
     {
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
index 40781f3ff32..757655ec9d5 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApi.java
@@ -497,6 +497,8 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update.UpdateVocabula
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update.VocabularyTermUpdate;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update.VocabularyUpdate;
 import ch.ethz.sis.openbis.generic.server.asapi.v3.executor.operation.IExecuteOperationExecutor;
+import ch.systemsx.cisd.openbis.common.pat.IPersonalAccessTokenAware;
+import ch.systemsx.cisd.openbis.common.pat.IPersonalAccessTokenInvocation;
 import ch.systemsx.cisd.openbis.common.spring.IInvocationLoggerContext;
 import ch.systemsx.cisd.openbis.generic.server.AbstractServer;
 import ch.systemsx.cisd.openbis.generic.server.ComponentNames;
@@ -514,7 +516,7 @@ import ch.systemsx.cisd.openbis.generic.shared.managed_property.IManagedProperty
  */
 @Component(ApplicationServerApi.INTERNAL_SERVICE_NAME)
 public class ApplicationServerApi extends AbstractServer<IApplicationServerApi> implements
-        IApplicationServerInternalApi
+        IApplicationServerInternalApi, IPersonalAccessTokenAware
 {
     /**
      * Name of this service for which it is registered as Spring bean
@@ -1737,6 +1739,11 @@ public class ApplicationServerApi extends AbstractServer<IApplicationServerApi>
         return result.getCodes();
     }
 
+    @Override public IApplicationServerApi createPersonalAccessTokenInvocationHandler(final IPersonalAccessTokenInvocation context)
+    {
+        return new ApplicationServerApiPersonalAccessTokenInvocationHandler(context);
+    }
+
     @Override
     public IApplicationServerApi createLogger(IInvocationLoggerContext context)
     {
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenDecorator.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiPersonalAccessTokenInvocationHandler.java
similarity index 53%
rename from openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenDecorator.java
rename to openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiPersonalAccessTokenInvocationHandler.java
index 0db34aacd44..b4c7114aa00 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenDecorator.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/ApplicationServerApiPersonalAccessTokenInvocationHandler.java
@@ -1,6 +1,5 @@
-package ch.ethz.sis.openbis.generic.server.asapi.v3.pat;
+package ch.ethz.sis.openbis.generic.server.asapi.v3;
 
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -235,980 +234,880 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.search.VocabularySear
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.search.VocabularyTermSearchCriteria;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update.VocabularyTermUpdate;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update.VocabularyUpdate;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.IApplicationServerInternalApi;
 import ch.systemsx.cisd.authentication.pat.IPersonalAccessTokenDAO;
-import ch.systemsx.cisd.authentication.pat.PersonalAccessToken;
-import ch.systemsx.cisd.authentication.pat.PersonalAccessTokenSession;
-import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.openbis.common.pat.IPersonalAccessTokenInvocation;
+import ch.systemsx.cisd.openbis.common.pat.PersonalAccessTokenInvocationHandler;
 import ch.systemsx.cisd.openbis.generic.server.CommonServiceProvider;
 
-public class ApplicationServerApiPersonalAccessTokenDecorator implements IApplicationServerInternalApi
+public class ApplicationServerApiPersonalAccessTokenInvocationHandler extends PersonalAccessTokenInvocationHandler
+        implements IApplicationServerInternalApi
 {
 
-    private final IApplicationServerInternalApi applicationServerApi;
+    private final IPersonalAccessTokenInvocation invocation;
 
-    public ApplicationServerApiPersonalAccessTokenDecorator(IApplicationServerInternalApi applicationServerApi)
+    public ApplicationServerApiPersonalAccessTokenInvocationHandler(final IPersonalAccessTokenInvocation invocation)
     {
-        this.applicationServerApi = applicationServerApi;
+        this.invocation = invocation;
     }
 
     @Override public int getMajorVersion()
     {
-        return applicationServerApi.getMajorVersion();
+        return invocation.proceedWithOriginalArguments();
     }
 
     @Override public int getMinorVersion()
     {
-        return applicationServerApi.getMinorVersion();
+        return invocation.proceedWithOriginalArguments();
     }
 
-    @Override public String login(final String userId, final String password)
+    @Override public String loginAsSystem()
     {
-        return applicationServerApi.login(userId, password);
+        return invocation.proceedWithOriginalArguments();
     }
 
-    @Override public String loginAs(final String userId, final String password, final String asUserId)
+    @Override public void registerUser(final String sessionToken)
     {
-        return applicationServerApi.loginAs(userId, password, asUserId);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public String loginAsSystem()
+    @Override public String login(final String userId, final String password)
     {
-        return applicationServerApi.loginAsSystem();
+        return invocation.proceedWithOriginalArguments();
     }
 
-    @Override public void registerUser(final String sessionTokenOrPAT)
+    @Override public String loginAs(final String userId, final String password, final String asUserId)
     {
-        // do not convert pat token
-        applicationServerApi.registerUser(sessionTokenOrPAT);
+        return invocation.proceedWithOriginalArguments();
     }
 
     @Override public String loginAsAnonymousUser()
     {
-        return applicationServerApi.loginAsAnonymousUser();
+        return invocation.proceedWithOriginalArguments();
     }
 
-    @Override public void logout(final String sessionTokenOrPAT)
+    @Override public void logout(final String sessionToken)
     {
-        // do not convert pat token
-        applicationServerApi.logout(sessionTokenOrPAT);
+        invocation.proceedWithOriginalArguments();
     }
 
-    @Override public SessionInformation getSessionInformation(final String sessionTokenOrPAT)
+    @Override public SessionInformation getSessionInformation(final String sessionToken)
     {
-        return applicationServerApi.getSessionInformation(toSessionToken(sessionTokenOrPAT));
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public boolean isSessionActive(final String sessionTokenOrPAT)
+    @Override public boolean isSessionActive(final String sessionToken)
     {
-        return applicationServerApi.isSessionActive(toSessionToken(sessionTokenOrPAT));
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<SpacePermId> createSpaces(final String sessionTokenOrPAT, final List<SpaceCreation> newSpaces)
+    @Override public List<SpacePermId> createSpaces(final String sessionToken, final List<SpaceCreation> newSpaces)
     {
-        return createSpaces(toSessionToken(sessionTokenOrPAT), newSpaces);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<ProjectPermId> createProjects(final String sessionTokenOrPAT, final List<ProjectCreation> newProjects)
+    @Override public List<ProjectPermId> createProjects(final String sessionToken, final List<ProjectCreation> newProjects)
     {
-        return createProjects(toSessionToken(sessionTokenOrPAT), newProjects);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<ExperimentPermId> createExperiments(final String sessionTokenOrPAT, final List<ExperimentCreation> newExperiments)
+    @Override public List<ExperimentPermId> createExperiments(final String sessionToken, final List<ExperimentCreation> newExperiments)
     {
-        return createExperiments(toSessionToken(sessionTokenOrPAT), newExperiments);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<EntityTypePermId> createExperimentTypes(final String sessionTokenOrPAT,
-            final List<ExperimentTypeCreation> newExperimentTypes)
+    @Override public List<EntityTypePermId> createExperimentTypes(final String sessionToken, final List<ExperimentTypeCreation> newExperimentTypes)
     {
-        return createExperimentTypes(toSessionToken(sessionTokenOrPAT), newExperimentTypes);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<SamplePermId> createSamples(final String sessionTokenOrPAT,
-            final List<SampleCreation> newSamples)
+    @Override public List<SamplePermId> createSamples(final String sessionToken, final List<SampleCreation> newSamples)
     {
-        return applicationServerApi.createSamples(toSessionToken(sessionTokenOrPAT), newSamples);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<EntityTypePermId> createSampleTypes(final String sessionTokenOrPAT,
-            final List<SampleTypeCreation> newSampleTypes)
+    @Override public List<EntityTypePermId> createSampleTypes(final String sessionToken, final List<SampleTypeCreation> newSampleTypes)
     {
-        return applicationServerApi.createSampleTypes(toSessionToken(sessionTokenOrPAT), newSampleTypes);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<DataSetPermId> createDataSets(final String sessionTokenOrPAT,
-            final List<DataSetCreation> newDataSets)
+    @Override public List<DataSetPermId> createDataSets(final String sessionToken, final List<DataSetCreation> newDataSets)
     {
-        return applicationServerApi.createDataSets(toSessionToken(sessionTokenOrPAT), newDataSets);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<EntityTypePermId> createDataSetTypes(final String sessionTokenOrPAT,
-            final List<DataSetTypeCreation> newDataSetTypes)
+    @Override public List<EntityTypePermId> createDataSetTypes(final String sessionToken, final List<DataSetTypeCreation> newDataSetTypes)
     {
-        return applicationServerApi.createDataSetTypes(toSessionToken(sessionTokenOrPAT), newDataSetTypes);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<MaterialPermId> createMaterials(final String sessionTokenOrPAT,
-            final List<MaterialCreation> newMaterials)
+    @Override public List<MaterialPermId> createMaterials(final String sessionToken, final List<MaterialCreation> newMaterials)
     {
-        return applicationServerApi.createMaterials(toSessionToken(sessionTokenOrPAT), newMaterials);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<EntityTypePermId> createMaterialTypes(final String sessionTokenOrPAT,
-            final List<MaterialTypeCreation> newMaterialTypes)
+    @Override public List<EntityTypePermId> createMaterialTypes(final String sessionToken, final List<MaterialTypeCreation> newMaterialTypes)
     {
-        return applicationServerApi.createMaterialTypes(toSessionToken(sessionTokenOrPAT), newMaterialTypes);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<PropertyTypePermId> createPropertyTypes(final String sessionTokenOrPAT,
-            final List<PropertyTypeCreation> newPropertyTypes)
+    @Override public List<PropertyTypePermId> createPropertyTypes(final String sessionToken, final List<PropertyTypeCreation> newPropertyTypes)
     {
-        return applicationServerApi.createPropertyTypes(toSessionToken(sessionTokenOrPAT), newPropertyTypes);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<PluginPermId> createPlugins(final String sessionTokenOrPAT,
-            final List<PluginCreation> newPlugins)
+    @Override public List<PluginPermId> createPlugins(final String sessionToken, final List<PluginCreation> newPlugins)
     {
-        return applicationServerApi.createPlugins(toSessionToken(sessionTokenOrPAT), newPlugins);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<VocabularyPermId> createVocabularies(final String sessionTokenOrPAT,
-            final List<VocabularyCreation> newVocabularies)
+    @Override public List<VocabularyPermId> createVocabularies(final String sessionToken, final List<VocabularyCreation> newVocabularies)
     {
-        return applicationServerApi.createVocabularies(toSessionToken(sessionTokenOrPAT), newVocabularies);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<VocabularyTermPermId> createVocabularyTerms(final String sessionTokenOrPAT,
+    @Override public List<VocabularyTermPermId> createVocabularyTerms(final String sessionToken,
             final List<VocabularyTermCreation> newVocabularyTerms)
     {
-        return applicationServerApi.createVocabularyTerms(toSessionToken(sessionTokenOrPAT), newVocabularyTerms);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<TagPermId> createTags(final String sessionTokenOrPAT, final List<TagCreation> newTags)
+    @Override public List<TagPermId> createTags(final String sessionToken, final List<TagCreation> newTags)
     {
-        return applicationServerApi.createTags(toSessionToken(sessionTokenOrPAT), newTags);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<AuthorizationGroupPermId> createAuthorizationGroups(final String sessionTokenOrPAT,
+    @Override public List<AuthorizationGroupPermId> createAuthorizationGroups(final String sessionToken,
             final List<AuthorizationGroupCreation> newAuthorizationGroups)
     {
-        return applicationServerApi.createAuthorizationGroups(toSessionToken(sessionTokenOrPAT), newAuthorizationGroups);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<RoleAssignmentTechId> createRoleAssignments(final String sessionTokenOrPAT,
+    @Override public List<RoleAssignmentTechId> createRoleAssignments(final String sessionToken,
             final List<RoleAssignmentCreation> newRoleAssignments)
     {
-        return applicationServerApi.createRoleAssignments(toSessionToken(sessionTokenOrPAT), newRoleAssignments);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<PersonPermId> createPersons(final String sessionTokenOrPAT,
-            final List<PersonCreation> newPersons)
+    @Override public List<PersonPermId> createPersons(final String sessionToken, final List<PersonCreation> newPersons)
     {
-        return applicationServerApi.createPersons(toSessionToken(sessionTokenOrPAT), newPersons);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<ExternalDmsPermId> createExternalDataManagementSystems(final String sessionTokenOrPAT,
+    @Override public List<ExternalDmsPermId> createExternalDataManagementSystems(final String sessionToken,
             final List<ExternalDmsCreation> newExternalDataManagementSystems)
     {
-        return applicationServerApi.createExternalDataManagementSystems(toSessionToken(sessionTokenOrPAT), newExternalDataManagementSystems);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<QueryTechId> createQueries(final String sessionTokenOrPAT,
-            final List<QueryCreation> newQueries)
+    @Override public List<QueryTechId> createQueries(final String sessionToken, final List<QueryCreation> newQueries)
     {
-        return applicationServerApi.createQueries(toSessionToken(sessionTokenOrPAT), newQueries);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<SemanticAnnotationPermId> createSemanticAnnotations(final String sessionTokenOrPAT,
+    @Override public List<SemanticAnnotationPermId> createSemanticAnnotations(final String sessionToken,
             final List<SemanticAnnotationCreation> newAnnotations)
     {
-        return applicationServerApi.createSemanticAnnotations(toSessionToken(sessionTokenOrPAT), newAnnotations);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateSpaces(final String sessionTokenOrPAT, final List<SpaceUpdate> spaceUpdates)
+    @Override public void updateSpaces(final String sessionToken, final List<SpaceUpdate> spaceUpdates)
     {
-        applicationServerApi.updateSpaces(toSessionToken(sessionTokenOrPAT), spaceUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateProjects(final String sessionTokenOrPAT, final List<ProjectUpdate> projectUpdates)
+    @Override public void updateProjects(final String sessionToken, final List<ProjectUpdate> projectUpdates)
     {
-        applicationServerApi.updateProjects(toSessionToken(sessionTokenOrPAT), projectUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateExperiments(final String sessionTokenOrPAT,
-            final List<ExperimentUpdate> experimentUpdates)
+    @Override public void updateExperiments(final String sessionToken, final List<ExperimentUpdate> experimentUpdates)
     {
-        applicationServerApi.updateExperiments(toSessionToken(sessionTokenOrPAT), experimentUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateExperimentTypes(final String sessionTokenOrPAT,
-            final List<ExperimentTypeUpdate> experimentTypeUpdates)
+    @Override public void updateExperimentTypes(final String sessionToken, final List<ExperimentTypeUpdate> experimentTypeUpdates)
     {
-        applicationServerApi.updateExperimentTypes(toSessionToken(sessionTokenOrPAT), experimentTypeUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateSamples(final String sessionTokenOrPAT, final List<SampleUpdate> sampleUpdates)
+    @Override public void updateSamples(final String sessionToken, final List<SampleUpdate> sampleUpdates)
     {
-        applicationServerApi.updateSamples(toSessionToken(sessionTokenOrPAT), sampleUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateSampleTypes(final String sessionTokenOrPAT,
-            final List<SampleTypeUpdate> sampleTypeUpdates)
+    @Override public void updateSampleTypes(final String sessionToken, final List<SampleTypeUpdate> sampleTypeUpdates)
     {
-        applicationServerApi.updateSampleTypes(toSessionToken(sessionTokenOrPAT), sampleTypeUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateDataSets(final String sessionTokenOrPAT, final List<DataSetUpdate> dataSetUpdates)
+    @Override public void updateDataSets(final String sessionToken, final List<DataSetUpdate> dataSetUpdates)
     {
-        applicationServerApi.updateDataSets(toSessionToken(sessionTokenOrPAT), dataSetUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateDataSetTypes(final String sessionTokenOrPAT,
-            final List<DataSetTypeUpdate> dataSetTypeUpdates)
+    @Override public void updateDataSetTypes(final String sessionToken, final List<DataSetTypeUpdate> dataSetTypeUpdates)
     {
-        applicationServerApi.updateDataSetTypes(toSessionToken(sessionTokenOrPAT), dataSetTypeUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateMaterials(final String sessionTokenOrPAT,
-            final List<MaterialUpdate> materialUpdates)
+    @Override public void updateMaterials(final String sessionToken, final List<MaterialUpdate> materialUpdates)
     {
-        applicationServerApi.updateMaterials(toSessionToken(sessionTokenOrPAT), materialUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateMaterialTypes(final String sessionTokenOrPAT,
-            final List<MaterialTypeUpdate> materialTypeUpdates)
+    @Override public void updateMaterialTypes(final String sessionToken, final List<MaterialTypeUpdate> materialTypeUpdates)
     {
-        applicationServerApi.updateMaterialTypes(toSessionToken(sessionTokenOrPAT), materialTypeUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateExternalDataManagementSystems(final String sessionTokenOrPAT,
-            final List<ExternalDmsUpdate> externalDmsUpdates)
+    @Override public void updateExternalDataManagementSystems(final String sessionToken, final List<ExternalDmsUpdate> externalDmsUpdates)
     {
-        applicationServerApi.updateExternalDataManagementSystems(toSessionToken(sessionTokenOrPAT), externalDmsUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updatePropertyTypes(final String sessionTokenOrPAT,
-            final List<PropertyTypeUpdate> propertyTypeUpdates)
+    @Override public void updatePropertyTypes(final String sessionToken, final List<PropertyTypeUpdate> propertyTypeUpdates)
     {
-        applicationServerApi.updatePropertyTypes(toSessionToken(sessionTokenOrPAT), propertyTypeUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updatePlugins(final String sessionTokenOrPAT, final List<PluginUpdate> pluginUpdates)
+    @Override public void updatePlugins(final String sessionToken, final List<PluginUpdate> pluginUpdates)
     {
-        applicationServerApi.updatePlugins(toSessionToken(sessionTokenOrPAT), pluginUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateVocabularies(final String sessionTokenOrPAT,
-            final List<VocabularyUpdate> vocabularyUpdates)
+    @Override public void updateVocabularies(final String sessionToken, final List<VocabularyUpdate> vocabularyUpdates)
     {
-        applicationServerApi.updateVocabularies(toSessionToken(sessionTokenOrPAT), vocabularyUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateVocabularyTerms(final String sessionTokenOrPAT,
-            final List<VocabularyTermUpdate> vocabularyTermUpdates)
+    @Override public void updateVocabularyTerms(final String sessionToken, final List<VocabularyTermUpdate> vocabularyTermUpdates)
     {
-        applicationServerApi.updateVocabularyTerms(toSessionToken(sessionTokenOrPAT), vocabularyTermUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateTags(final String sessionTokenOrPAT, final List<TagUpdate> tagUpdates)
+    @Override public void updateTags(final String sessionToken, final List<TagUpdate> tagUpdates)
     {
-        applicationServerApi.updateTags(toSessionToken(sessionTokenOrPAT), tagUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateAuthorizationGroups(final String sessionTokenOrPAT,
-            final List<AuthorizationGroupUpdate> authorizationGroupUpdates)
+    @Override public void updateAuthorizationGroups(final String sessionToken, final List<AuthorizationGroupUpdate> authorizationGroupUpdates)
     {
-        applicationServerApi.updateAuthorizationGroups(toSessionToken(sessionTokenOrPAT), authorizationGroupUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updatePersons(final String sessionTokenOrPAT, final List<PersonUpdate> personUpdates)
+    @Override public void updatePersons(final String sessionToken, final List<PersonUpdate> personUpdates)
     {
-        applicationServerApi.updatePersons(toSessionToken(sessionTokenOrPAT), personUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateOperationExecutions(final String sessionTokenOrPAT,
-            final List<OperationExecutionUpdate> executionUpdates)
+    @Override public void updateOperationExecutions(final String sessionToken, final List<OperationExecutionUpdate> executionUpdates)
     {
-        applicationServerApi.updateOperationExecutions(toSessionToken(sessionTokenOrPAT), executionUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateSemanticAnnotations(final String sessionTokenOrPAT,
-            final List<SemanticAnnotationUpdate> annotationUpdates)
+    @Override public void updateSemanticAnnotations(final String sessionToken, final List<SemanticAnnotationUpdate> annotationUpdates)
     {
-        applicationServerApi.updateSemanticAnnotations(toSessionToken(sessionTokenOrPAT), annotationUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void updateQueries(final String sessionTokenOrPAT, final List<QueryUpdate> queryUpdates)
+    @Override public void updateQueries(final String sessionToken, final List<QueryUpdate> queryUpdates)
     {
-        applicationServerApi.updateQueries(toSessionToken(sessionTokenOrPAT), queryUpdates);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IObjectId, Rights> getRights(final String sessionTokenOrPAT,
-            final List<? extends IObjectId> ids, final RightsFetchOptions fetchOptions)
+    @Override public Map<IObjectId, Rights> getRights(final String sessionToken, final List<? extends IObjectId> ids,
+            final RightsFetchOptions fetchOptions)
     {
-        return applicationServerApi.getRights(toSessionToken(sessionTokenOrPAT), ids, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<ISpaceId, Space> getSpaces(final String sessionTokenOrPAT,
-            final List<? extends ISpaceId> spaceIds, final SpaceFetchOptions fetchOptions)
+    @Override public Map<ISpaceId, Space> getSpaces(final String sessionToken, final List<? extends ISpaceId> spaceIds,
+            final SpaceFetchOptions fetchOptions)
     {
-        return applicationServerApi.getSpaces(toSessionToken(sessionTokenOrPAT), spaceIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IProjectId, Project> getProjects(final String sessionTokenOrPAT,
-            final List<? extends IProjectId> projectIds, final ProjectFetchOptions fetchOptions)
+    @Override public Map<IProjectId, Project> getProjects(final String sessionToken, final List<? extends IProjectId> projectIds,
+            final ProjectFetchOptions fetchOptions)
     {
-        return applicationServerApi.getProjects(toSessionToken(sessionTokenOrPAT), projectIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IExperimentId, Experiment> getExperiments(final String sessionTokenOrPAT,
-            final List<? extends IExperimentId> experimentIds,
+    @Override public Map<IExperimentId, Experiment> getExperiments(final String sessionToken, final List<? extends IExperimentId> experimentIds,
             final ExperimentFetchOptions fetchOptions)
     {
-        return applicationServerApi.getExperiments(toSessionToken(sessionTokenOrPAT), experimentIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IEntityTypeId, ExperimentType> getExperimentTypes(final String sessionTokenOrPAT,
+    @Override public Map<IEntityTypeId, ExperimentType> getExperimentTypes(final String sessionToken,
             final List<? extends IEntityTypeId> experimentTypeIds,
             final ExperimentTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.getExperimentTypes(toSessionToken(sessionTokenOrPAT), experimentTypeIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<ISampleId, Sample> getSamples(final String sessionTokenOrPAT,
-            final List<? extends ISampleId> sampleIds, final SampleFetchOptions fetchOptions)
+    @Override public Map<ISampleId, Sample> getSamples(final String sessionToken, final List<? extends ISampleId> sampleIds,
+            final SampleFetchOptions fetchOptions)
     {
-        return applicationServerApi.getSamples(toSessionToken(sessionTokenOrPAT), sampleIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IEntityTypeId, SampleType> getSampleTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> sampleTypeIds, final SampleTypeFetchOptions fetchOptions)
+    @Override public Map<IEntityTypeId, SampleType> getSampleTypes(final String sessionToken, final List<? extends IEntityTypeId> sampleTypeIds,
+            final SampleTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.getSampleTypes(toSessionToken(sessionTokenOrPAT), sampleTypeIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IDataSetId, DataSet> getDataSets(final String sessionTokenOrPAT,
-            final List<? extends IDataSetId> dataSetIds, final DataSetFetchOptions fetchOptions)
+    @Override public Map<IDataSetId, DataSet> getDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds,
+            final DataSetFetchOptions fetchOptions)
     {
-        return applicationServerApi.getDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IEntityTypeId, DataSetType> getDataSetTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> dataSetTypeIds,
+    @Override public Map<IEntityTypeId, DataSetType> getDataSetTypes(final String sessionToken, final List<? extends IEntityTypeId> dataSetTypeIds,
             final DataSetTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.getDataSetTypes(toSessionToken(sessionTokenOrPAT), dataSetTypeIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IMaterialId, Material> getMaterials(final String sessionTokenOrPAT,
-            final List<? extends IMaterialId> materialIds, final MaterialFetchOptions fetchOptions)
+    @Override public Map<IMaterialId, Material> getMaterials(final String sessionToken, final List<? extends IMaterialId> materialIds,
+            final MaterialFetchOptions fetchOptions)
     {
-        return applicationServerApi.getMaterials(toSessionToken(sessionTokenOrPAT), materialIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IEntityTypeId, MaterialType> getMaterialTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> materialTypeIds,
+    @Override public Map<IEntityTypeId, MaterialType> getMaterialTypes(final String sessionToken, final List<? extends IEntityTypeId> materialTypeIds,
             final MaterialTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.getMaterialTypes(toSessionToken(sessionTokenOrPAT), materialTypeIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IPropertyTypeId, PropertyType> getPropertyTypes(final String sessionTokenOrPAT,
-            final List<? extends IPropertyTypeId> typeIds, final PropertyTypeFetchOptions fetchOptions)
+    @Override public Map<IPropertyTypeId, PropertyType> getPropertyTypes(final String sessionToken, final List<? extends IPropertyTypeId> typeIds,
+            final PropertyTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.getPropertyTypes(toSessionToken(sessionTokenOrPAT), typeIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IPluginId, Plugin> getPlugins(final String sessionTokenOrPAT,
-            final List<? extends IPluginId> pluginIds, final PluginFetchOptions fetchOptions)
+    @Override public Map<IPluginId, Plugin> getPlugins(final String sessionToken, final List<? extends IPluginId> pluginIds,
+            final PluginFetchOptions fetchOptions)
     {
-        return applicationServerApi.getPlugins(toSessionToken(sessionTokenOrPAT), pluginIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IVocabularyId, Vocabulary> getVocabularies(final String sessionTokenOrPAT,
-            final List<? extends IVocabularyId> vocabularyIds,
+    @Override public Map<IVocabularyId, Vocabulary> getVocabularies(final String sessionToken, final List<? extends IVocabularyId> vocabularyIds,
             final VocabularyFetchOptions fetchOptions)
     {
-        return applicationServerApi.getVocabularies(toSessionToken(sessionTokenOrPAT), vocabularyIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IVocabularyTermId, VocabularyTerm> getVocabularyTerms(final String sessionTokenOrPAT,
-            final List<? extends IVocabularyTermId> vocabularyTermIds,
-            final VocabularyTermFetchOptions fetchOptions)
+    @Override public Map<IVocabularyTermId, VocabularyTerm> getVocabularyTerms(final String sessionToken,
+            final List<? extends IVocabularyTermId> vocabularyTermIds, final VocabularyTermFetchOptions fetchOptions)
     {
-        return applicationServerApi.getVocabularyTerms(toSessionToken(sessionTokenOrPAT), vocabularyTermIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<ITagId, Tag> getTags(final String sessionTokenOrPAT, final List<? extends ITagId> tagIds,
-            final TagFetchOptions fetchOptions)
+    @Override public Map<ITagId, Tag> getTags(final String sessionToken, final List<? extends ITagId> tagIds, final TagFetchOptions fetchOptions)
     {
-        return applicationServerApi.getTags(toSessionToken(sessionTokenOrPAT), tagIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IAuthorizationGroupId, AuthorizationGroup> getAuthorizationGroups(final String sessionTokenOrPAT,
-            final List<? extends IAuthorizationGroupId> groupIds,
-            final AuthorizationGroupFetchOptions fetchOptions)
+    @Override public Map<IAuthorizationGroupId, AuthorizationGroup> getAuthorizationGroups(final String sessionToken,
+            final List<? extends IAuthorizationGroupId> groupIds, final AuthorizationGroupFetchOptions fetchOptions)
     {
-        return applicationServerApi.getAuthorizationGroups(toSessionToken(sessionTokenOrPAT), groupIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IRoleAssignmentId, RoleAssignment> getRoleAssignments(final String sessionTokenOrPAT,
-            final List<? extends IRoleAssignmentId> ids,
+    @Override public Map<IRoleAssignmentId, RoleAssignment> getRoleAssignments(final String sessionToken, final List<? extends IRoleAssignmentId> ids,
             final RoleAssignmentFetchOptions fetchOptions)
     {
-        return applicationServerApi.getRoleAssignments(toSessionToken(sessionTokenOrPAT), ids, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IPersonId, Person> getPersons(final String sessionTokenOrPAT,
-            final List<? extends IPersonId> ids, final PersonFetchOptions fetchOptions)
+    @Override public Map<IPersonId, Person> getPersons(final String sessionToken, final List<? extends IPersonId> ids,
+            final PersonFetchOptions fetchOptions)
     {
-        return applicationServerApi.getPersons(toSessionToken(sessionTokenOrPAT), ids, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IExternalDmsId, ExternalDms> getExternalDataManagementSystems(final String sessionTokenOrPAT,
-            final List<? extends IExternalDmsId> externalDmsIds,
-            final ExternalDmsFetchOptions fetchOptions)
+    @Override public Map<IExternalDmsId, ExternalDms> getExternalDataManagementSystems(final String sessionToken,
+            final List<? extends IExternalDmsId> externalDmsIds, final ExternalDmsFetchOptions fetchOptions)
     {
-        return applicationServerApi.getExternalDataManagementSystems(toSessionToken(sessionTokenOrPAT), externalDmsIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<ISemanticAnnotationId, SemanticAnnotation> getSemanticAnnotations(final String sessionTokenOrPAT,
-            final List<? extends ISemanticAnnotationId> annotationIds,
-            final SemanticAnnotationFetchOptions fetchOptions)
+    @Override public Map<ISemanticAnnotationId, SemanticAnnotation> getSemanticAnnotations(final String sessionToken,
+            final List<? extends ISemanticAnnotationId> annotationIds, final SemanticAnnotationFetchOptions fetchOptions)
     {
-        return applicationServerApi.getSemanticAnnotations(toSessionToken(sessionTokenOrPAT), annotationIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IOperationExecutionId, OperationExecution> getOperationExecutions(final String sessionTokenOrPAT,
-            final List<? extends IOperationExecutionId> executionIds,
-            final OperationExecutionFetchOptions fetchOptions)
+    @Override public Map<IOperationExecutionId, OperationExecution> getOperationExecutions(final String sessionToken,
+            final List<? extends IOperationExecutionId> executionIds, final OperationExecutionFetchOptions fetchOptions)
     {
-        return applicationServerApi.getOperationExecutions(toSessionToken(sessionTokenOrPAT), executionIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IQueryId, Query> getQueries(final String sessionTokenOrPAT,
-            final List<? extends IQueryId> queryIds, final QueryFetchOptions fetchOptions)
+    @Override public Map<IQueryId, Query> getQueries(final String sessionToken, final List<? extends IQueryId> queryIds,
+            final QueryFetchOptions fetchOptions)
     {
-        return applicationServerApi.getQueries(toSessionToken(sessionTokenOrPAT), queryIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<IQueryDatabaseId, QueryDatabase> getQueryDatabases(final String sessionTokenOrPAT,
+    @Override public Map<IQueryDatabaseId, QueryDatabase> getQueryDatabases(final String sessionToken,
             final List<? extends IQueryDatabaseId> queryDatabaseIds,
             final QueryDatabaseFetchOptions fetchOptions)
     {
-        return applicationServerApi.getQueryDatabases(toSessionToken(sessionTokenOrPAT), queryDatabaseIds, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Space> searchSpaces(final String sessionTokenOrPAT, final SpaceSearchCriteria searchCriteria,
+    @Override public SearchResult<Space> searchSpaces(final String sessionToken, final SpaceSearchCriteria searchCriteria,
             final SpaceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchSpaces(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Project> searchProjects(final String sessionTokenOrPAT,
-            final ProjectSearchCriteria searchCriteria, final ProjectFetchOptions fetchOptions)
+    @Override public SearchResult<Project> searchProjects(final String sessionToken, final ProjectSearchCriteria searchCriteria,
+            final ProjectFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchProjects(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Experiment> searchExperiments(final String sessionTokenOrPAT,
-            final ExperimentSearchCriteria searchCriteria, final ExperimentFetchOptions fetchOptions)
+    @Override public SearchResult<Experiment> searchExperiments(final String sessionToken, final ExperimentSearchCriteria searchCriteria,
+            final ExperimentFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchExperiments(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<ExperimentType> searchExperimentTypes(final String sessionTokenOrPAT,
-            final ExperimentTypeSearchCriteria searchCriteria,
+    @Override public SearchResult<ExperimentType> searchExperimentTypes(final String sessionToken, final ExperimentTypeSearchCriteria searchCriteria,
             final ExperimentTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchExperimentTypes(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Sample> searchSamples(final String sessionTokenOrPAT,
-            final SampleSearchCriteria searchCriteria, final SampleFetchOptions fetchOptions)
+    @Override public SearchResult<Sample> searchSamples(final String sessionToken, final SampleSearchCriteria searchCriteria,
+            final SampleFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchSamples(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<SampleType> searchSampleTypes(final String sessionTokenOrPAT,
-            final SampleTypeSearchCriteria searchCriteria, final SampleTypeFetchOptions fetchOptions)
+    @Override public SearchResult<SampleType> searchSampleTypes(final String sessionToken, final SampleTypeSearchCriteria searchCriteria,
+            final SampleTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchSampleTypes(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<DataSet> searchDataSets(final String sessionTokenOrPAT,
-            final DataSetSearchCriteria searchCriteria, final DataSetFetchOptions fetchOptions)
+    @Override public SearchResult<DataSet> searchDataSets(final String sessionToken, final DataSetSearchCriteria searchCriteria,
+            final DataSetFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchDataSets(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<DataSetType> searchDataSetTypes(final String sessionTokenOrPAT,
-            final DataSetTypeSearchCriteria searchCriteria, final DataSetTypeFetchOptions fetchOptions)
+    @Override public SearchResult<DataSetType> searchDataSetTypes(final String sessionToken, final DataSetTypeSearchCriteria searchCriteria,
+            final DataSetTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchDataSetTypes(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Material> searchMaterials(final String sessionTokenOrPAT,
-            final MaterialSearchCriteria searchCriteria, final MaterialFetchOptions fetchOptions)
+    @Override public SearchResult<Material> searchMaterials(final String sessionToken, final MaterialSearchCriteria searchCriteria,
+            final MaterialFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchMaterials(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<ExternalDms> searchExternalDataManagementSystems(final String sessionTokenOrPAT,
+    @Override public SearchResult<ExternalDms> searchExternalDataManagementSystems(final String sessionToken,
             final ExternalDmsSearchCriteria searchCriteria,
             final ExternalDmsFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchExternalDataManagementSystems(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<MaterialType> searchMaterialTypes(final String sessionTokenOrPAT,
-            final MaterialTypeSearchCriteria searchCriteria,
+    @Override public SearchResult<MaterialType> searchMaterialTypes(final String sessionToken, final MaterialTypeSearchCriteria searchCriteria,
             final MaterialTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchMaterialTypes(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Plugin> searchPlugins(final String sessionTokenOrPAT,
-            final PluginSearchCriteria searchCriteria, final PluginFetchOptions fetchOptions)
+    @Override public SearchResult<Plugin> searchPlugins(final String sessionToken, final PluginSearchCriteria searchCriteria,
+            final PluginFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchPlugins(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Vocabulary> searchVocabularies(final String sessionTokenOrPAT,
-            final VocabularySearchCriteria searchCriteria, final VocabularyFetchOptions fetchOptions)
+    @Override public SearchResult<Vocabulary> searchVocabularies(final String sessionToken, final VocabularySearchCriteria searchCriteria,
+            final VocabularyFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchVocabularies(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<VocabularyTerm> searchVocabularyTerms(final String sessionTokenOrPAT,
-            final VocabularyTermSearchCriteria searchCriteria,
+    @Override public SearchResult<VocabularyTerm> searchVocabularyTerms(final String sessionToken, final VocabularyTermSearchCriteria searchCriteria,
             final VocabularyTermFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchVocabularyTerms(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Tag> searchTags(final String sessionTokenOrPAT, final TagSearchCriteria searchCriteria,
+    @Override public SearchResult<Tag> searchTags(final String sessionToken, final TagSearchCriteria searchCriteria,
             final TagFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchTags(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<AuthorizationGroup> searchAuthorizationGroups(final String sessionTokenOrPAT,
+    @Override public SearchResult<AuthorizationGroup> searchAuthorizationGroups(final String sessionToken,
             final AuthorizationGroupSearchCriteria searchCriteria,
             final AuthorizationGroupFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchAuthorizationGroups(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<RoleAssignment> searchRoleAssignments(final String sessionTokenOrPAT,
-            final RoleAssignmentSearchCriteria searchCriteria,
+    @Override public SearchResult<RoleAssignment> searchRoleAssignments(final String sessionToken, final RoleAssignmentSearchCriteria searchCriteria,
             final RoleAssignmentFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchRoleAssignments(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Person> searchPersons(final String sessionTokenOrPAT,
-            final PersonSearchCriteria searchCriteria, final PersonFetchOptions fetchOptions)
+    @Override public SearchResult<Person> searchPersons(final String sessionToken, final PersonSearchCriteria searchCriteria,
+            final PersonFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchPersons(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<CustomASService> searchCustomASServices(final String sessionTokenOrPAT,
+    @Override public SearchResult<CustomASService> searchCustomASServices(final String sessionToken,
             final CustomASServiceSearchCriteria searchCriteria,
             final CustomASServiceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchCustomASServices(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<SearchDomainService> searchSearchDomainServices(final String sessionTokenOrPAT,
-            final SearchDomainServiceSearchCriteria searchCriteria,
-            final SearchDomainServiceFetchOptions fetchOptions)
+    @Override public SearchResult<SearchDomainService> searchSearchDomainServices(final String sessionToken,
+            final SearchDomainServiceSearchCriteria searchCriteria, final SearchDomainServiceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchSearchDomainServices(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<AggregationService> searchAggregationServices(final String sessionTokenOrPAT,
+    @Override public SearchResult<AggregationService> searchAggregationServices(final String sessionToken,
             final AggregationServiceSearchCriteria searchCriteria,
             final AggregationServiceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchAggregationServices(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<ReportingService> searchReportingServices(final String sessionTokenOrPAT,
+    @Override public SearchResult<ReportingService> searchReportingServices(final String sessionToken,
             final ReportingServiceSearchCriteria searchCriteria,
             final ReportingServiceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchReportingServices(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<ProcessingService> searchProcessingServices(final String sessionTokenOrPAT,
+    @Override public SearchResult<ProcessingService> searchProcessingServices(final String sessionToken,
             final ProcessingServiceSearchCriteria searchCriteria,
             final ProcessingServiceFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchProcessingServices(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<ObjectKindModification> searchObjectKindModifications(final String sessionTokenOrPAT,
-            final ObjectKindModificationSearchCriteria searchCriteria,
-            final ObjectKindModificationFetchOptions fetchOptions)
+    @Override public SearchResult<ObjectKindModification> searchObjectKindModifications(final String sessionToken,
+            final ObjectKindModificationSearchCriteria searchCriteria, final ObjectKindModificationFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchObjectKindModifications(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<GlobalSearchObject> searchGlobally(final String sessionTokenOrPAT,
-            final GlobalSearchCriteria searchCriteria, final GlobalSearchObjectFetchOptions fetchOptions)
+    @Override public SearchResult<GlobalSearchObject> searchGlobally(final String sessionToken, final GlobalSearchCriteria searchCriteria,
+            final GlobalSearchObjectFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchGlobally(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<OperationExecution> searchOperationExecutions(final String sessionTokenOrPAT,
+    @Override public SearchResult<OperationExecution> searchOperationExecutions(final String sessionToken,
             final OperationExecutionSearchCriteria searchCriteria,
             final OperationExecutionFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchOperationExecutions(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<DataStore> searchDataStores(final String sessionTokenOrPAT,
-            final DataStoreSearchCriteria searchCriteria, final DataStoreFetchOptions fetchOptions)
+    @Override public SearchResult<DataStore> searchDataStores(final String sessionToken, final DataStoreSearchCriteria searchCriteria,
+            final DataStoreFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchDataStores(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<SemanticAnnotation> searchSemanticAnnotations(final String sessionTokenOrPAT,
+    @Override public SearchResult<SemanticAnnotation> searchSemanticAnnotations(final String sessionToken,
             final SemanticAnnotationSearchCriteria searchCriteria,
             final SemanticAnnotationFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchSemanticAnnotations(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<PropertyType> searchPropertyTypes(final String sessionTokenOrPAT,
-            final PropertyTypeSearchCriteria searchCriteria,
+    @Override public SearchResult<PropertyType> searchPropertyTypes(final String sessionToken, final PropertyTypeSearchCriteria searchCriteria,
             final PropertyTypeFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchPropertyTypes(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<PropertyAssignment> searchPropertyAssignments(final String sessionTokenOrPAT,
+    @Override public SearchResult<PropertyAssignment> searchPropertyAssignments(final String sessionToken,
             final PropertyAssignmentSearchCriteria searchCriteria,
             final PropertyAssignmentFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchPropertyAssignments(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Query> searchQueries(final String sessionTokenOrPAT,
-            final QuerySearchCriteria searchCriteria, final QueryFetchOptions fetchOptions)
+    @Override public SearchResult<Query> searchQueries(final String sessionToken, final QuerySearchCriteria searchCriteria,
+            final QueryFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchQueries(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<QueryDatabase> searchQueryDatabases(final String sessionTokenOrPAT,
-            final QueryDatabaseSearchCriteria searchCriteria,
+    @Override public SearchResult<QueryDatabase> searchQueryDatabases(final String sessionToken, final QueryDatabaseSearchCriteria searchCriteria,
             final QueryDatabaseFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchQueryDatabases(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteSpaces(final String sessionTokenOrPAT, final List<? extends ISpaceId> spaceIds,
-            final SpaceDeletionOptions deletionOptions)
+    @Override public void deleteSpaces(final String sessionToken, final List<? extends ISpaceId> spaceIds, final SpaceDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteSpaces(toSessionToken(sessionTokenOrPAT), spaceIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteProjects(final String sessionTokenOrPAT, final List<? extends IProjectId> projectIds,
+    @Override public void deleteProjects(final String sessionToken, final List<? extends IProjectId> projectIds,
             final ProjectDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteProjects(toSessionToken(sessionTokenOrPAT), projectIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public IDeletionId deleteExperiments(final String sessionTokenOrPAT,
-            final List<? extends IExperimentId> experimentIds,
+    @Override public IDeletionId deleteExperiments(final String sessionToken, final List<? extends IExperimentId> experimentIds,
             final ExperimentDeletionOptions deletionOptions)
     {
-        return applicationServerApi.deleteExperiments(toSessionToken(sessionTokenOrPAT), experimentIds, deletionOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public IDeletionId deleteSamples(final String sessionTokenOrPAT,
-            final List<? extends ISampleId> sampleIds, final SampleDeletionOptions deletionOptions)
+    @Override public IDeletionId deleteSamples(final String sessionToken, final List<? extends ISampleId> sampleIds,
+            final SampleDeletionOptions deletionOptions)
     {
-        return applicationServerApi.deleteSamples(toSessionToken(sessionTokenOrPAT), sampleIds, deletionOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public IDeletionId deleteDataSets(final String sessionTokenOrPAT,
-            final List<? extends IDataSetId> dataSetIds, final DataSetDeletionOptions deletionOptions)
+    @Override public IDeletionId deleteDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds,
+            final DataSetDeletionOptions deletionOptions)
     {
-        return applicationServerApi.deleteDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, deletionOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteMaterials(final String sessionTokenOrPAT,
-            final List<? extends IMaterialId> materialIds, final MaterialDeletionOptions deletionOptions)
+    @Override public void deleteMaterials(final String sessionToken, final List<? extends IMaterialId> materialIds,
+            final MaterialDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteMaterials(toSessionToken(sessionTokenOrPAT), materialIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deletePlugins(final String sessionTokenOrPAT, final List<? extends IPluginId> pluginIds,
+    @Override public void deletePlugins(final String sessionToken, final List<? extends IPluginId> pluginIds,
             final PluginDeletionOptions deletionOptions)
     {
-        applicationServerApi.deletePlugins(toSessionToken(sessionTokenOrPAT), pluginIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deletePropertyTypes(final String sessionTokenOrPAT,
-            final List<? extends IPropertyTypeId> propertyTypeIds,
+    @Override public void deletePropertyTypes(final String sessionToken, final List<? extends IPropertyTypeId> propertyTypeIds,
             final PropertyTypeDeletionOptions deletionOptions)
     {
-        applicationServerApi.deletePropertyTypes(toSessionToken(sessionTokenOrPAT), propertyTypeIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteVocabularies(final String sessionTokenOrPAT,
-            final List<? extends IVocabularyId> ids, final VocabularyDeletionOptions deletionOptions)
+    @Override public void deleteVocabularies(final String sessionToken, final List<? extends IVocabularyId> ids,
+            final VocabularyDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteVocabularies(toSessionToken(sessionTokenOrPAT), ids, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteVocabularyTerms(final String sessionTokenOrPAT,
-            final List<? extends IVocabularyTermId> termIds,
+    @Override public void deleteVocabularyTerms(final String sessionToken, final List<? extends IVocabularyTermId> termIds,
             final VocabularyTermDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteVocabularyTerms(toSessionToken(sessionTokenOrPAT), termIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteExperimentTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> experimentTypeIds,
+    @Override public void deleteExperimentTypes(final String sessionToken, final List<? extends IEntityTypeId> experimentTypeIds,
             final ExperimentTypeDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteExperimentTypes(toSessionToken(sessionTokenOrPAT), experimentTypeIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteSampleTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> sampleTypeIds, final SampleTypeDeletionOptions deletionOptions)
+    @Override public void deleteSampleTypes(final String sessionToken, final List<? extends IEntityTypeId> sampleTypeIds,
+            final SampleTypeDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteSampleTypes(toSessionToken(sessionTokenOrPAT), sampleTypeIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteDataSetTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> dataSetTypeIds,
+    @Override public void deleteDataSetTypes(final String sessionToken, final List<? extends IEntityTypeId> dataSetTypeIds,
             final DataSetTypeDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteDataSetTypes(toSessionToken(sessionTokenOrPAT), dataSetTypeIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteMaterialTypes(final String sessionTokenOrPAT,
-            final List<? extends IEntityTypeId> materialTypeIds,
+    @Override public void deleteMaterialTypes(final String sessionToken, final List<? extends IEntityTypeId> materialTypeIds,
             final MaterialTypeDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteMaterialTypes(toSessionToken(sessionTokenOrPAT), materialTypeIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteExternalDataManagementSystems(final String sessionTokenOrPAT,
-            final List<? extends IExternalDmsId> externalDmsIds,
+    @Override public void deleteExternalDataManagementSystems(final String sessionToken, final List<? extends IExternalDmsId> externalDmsIds,
             final ExternalDmsDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteExternalDataManagementSystems(toSessionToken(sessionTokenOrPAT), externalDmsIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteTags(final String sessionTokenOrPAT, final List<? extends ITagId> tagIds,
-            final TagDeletionOptions deletionOptions)
+    @Override public void deleteTags(final String sessionToken, final List<? extends ITagId> tagIds, final TagDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteTags(toSessionToken(sessionTokenOrPAT), tagIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteAuthorizationGroups(final String sessionTokenOrPAT,
-            final List<? extends IAuthorizationGroupId> groupIds,
+    @Override public void deleteAuthorizationGroups(final String sessionToken, final List<? extends IAuthorizationGroupId> groupIds,
             final AuthorizationGroupDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteAuthorizationGroups(toSessionToken(sessionTokenOrPAT), groupIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteRoleAssignments(final String sessionTokenOrPAT,
-            final List<? extends IRoleAssignmentId> assignmentIds,
+    @Override public void deleteRoleAssignments(final String sessionToken, final List<? extends IRoleAssignmentId> assignmentIds,
             final RoleAssignmentDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteRoleAssignments(toSessionToken(sessionTokenOrPAT), assignmentIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteOperationExecutions(final String sessionTokenOrPAT,
-            final List<? extends IOperationExecutionId> executionIds,
+    @Override public void deleteOperationExecutions(final String sessionToken, final List<? extends IOperationExecutionId> executionIds,
             final OperationExecutionDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteOperationExecutions(toSessionToken(sessionTokenOrPAT), executionIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteSemanticAnnotations(final String sessionTokenOrPAT,
-            final List<? extends ISemanticAnnotationId> annotationIds,
+    @Override public void deleteSemanticAnnotations(final String sessionToken, final List<? extends ISemanticAnnotationId> annotationIds,
             final SemanticAnnotationDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteSemanticAnnotations(toSessionToken(sessionTokenOrPAT), annotationIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deleteQueries(final String sessionTokenOrPAT, final List<? extends IQueryId> queryIds,
+    @Override public void deleteQueries(final String sessionToken, final List<? extends IQueryId> queryIds,
             final QueryDeletionOptions deletionOptions)
     {
-        applicationServerApi.deleteQueries(toSessionToken(sessionTokenOrPAT), queryIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void deletePersons(final String sessionTokenOrPAT, final List<? extends IPersonId> personIds,
+    @Override public void deletePersons(final String sessionToken, final List<? extends IPersonId> personIds,
             final PersonDeletionOptions deletionOptions)
     {
-        applicationServerApi.deletePersons(toSessionToken(sessionTokenOrPAT), personIds, deletionOptions);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Deletion> searchDeletions(final String sessionTokenOrPAT,
-            final DeletionSearchCriteria searchCriteria, final DeletionFetchOptions fetchOptions)
+    @Override public SearchResult<Deletion> searchDeletions(final String sessionToken, final DeletionSearchCriteria searchCriteria,
+            final DeletionFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchDeletions(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<Event> searchEvents(final String sessionTokenOrPAT, final EventSearchCriteria searchCriteria,
+    @Override public SearchResult<Event> searchEvents(final String sessionToken, final EventSearchCriteria searchCriteria,
             final EventFetchOptions fetchOptions)
     {
-        return applicationServerApi.searchEvents(toSessionToken(sessionTokenOrPAT), searchCriteria, fetchOptions);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void revertDeletions(final String sessionTokenOrPAT,
-            final List<? extends IDeletionId> deletionIds)
+    @Override public void revertDeletions(final String sessionToken, final List<? extends IDeletionId> deletionIds)
     {
-        applicationServerApi.revertDeletions(toSessionToken(sessionTokenOrPAT), deletionIds);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void confirmDeletions(final String sessionTokenOrPAT,
-            final List<? extends IDeletionId> deletionIds)
+    @Override public void confirmDeletions(final String sessionToken, final List<? extends IDeletionId> deletionIds)
     {
-        applicationServerApi.confirmDeletions(toSessionToken(sessionTokenOrPAT), deletionIds);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Object executeCustomASService(final String sessionTokenOrPAT, final ICustomASServiceId serviceId,
+    @Override public Object executeCustomASService(final String sessionToken, final ICustomASServiceId serviceId,
             final CustomASServiceExecutionOptions options)
     {
-        return applicationServerApi.executeCustomASService(toSessionToken(sessionTokenOrPAT), serviceId, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public SearchResult<SearchDomainServiceExecutionResult> executeSearchDomainService(final String sessionTokenOrPAT,
+    @Override public SearchResult<SearchDomainServiceExecutionResult> executeSearchDomainService(final String sessionToken,
             final SearchDomainServiceExecutionOptions options)
     {
-        return applicationServerApi.executeSearchDomainService(toSessionToken(sessionTokenOrPAT), options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public TableModel executeAggregationService(final String sessionTokenOrPAT, final IDssServiceId serviceId,
+    @Override public TableModel executeAggregationService(final String sessionToken, final IDssServiceId serviceId,
             final AggregationServiceExecutionOptions options)
     {
-        return applicationServerApi.executeAggregationService(toSessionToken(sessionTokenOrPAT), serviceId, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public TableModel executeReportingService(final String sessionTokenOrPAT, final IDssServiceId serviceId,
+    @Override public TableModel executeReportingService(final String sessionToken, final IDssServiceId serviceId,
             final ReportingServiceExecutionOptions options)
     {
-        return applicationServerApi.executeReportingService(toSessionToken(sessionTokenOrPAT), serviceId, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void executeProcessingService(final String sessionTokenOrPAT, final IDssServiceId serviceId,
+    @Override public void executeProcessingService(final String sessionToken, final IDssServiceId serviceId,
             final ProcessingServiceExecutionOptions options)
     {
-        applicationServerApi.executeProcessingService(toSessionToken(sessionTokenOrPAT), serviceId, options);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public TableModel executeQuery(final String sessionTokenOrPAT, final IQueryId queryId,
-            final QueryExecutionOptions options)
+    @Override public TableModel executeQuery(final String sessionToken, final IQueryId queryId, final QueryExecutionOptions options)
     {
-        return applicationServerApi.executeQuery(toSessionToken(sessionTokenOrPAT), queryId, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public TableModel executeSql(final String sessionTokenOrPAT, final String sql, final SqlExecutionOptions options)
+    @Override public TableModel executeSql(final String sessionToken, final String sql, final SqlExecutionOptions options)
     {
-        return applicationServerApi.executeSql(toSessionToken(sessionTokenOrPAT), sql, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public PluginEvaluationResult evaluatePlugin(final String sessionTokenOrPAT,
-            final PluginEvaluationOptions options)
+    @Override public PluginEvaluationResult evaluatePlugin(final String sessionToken, final PluginEvaluationOptions options)
     {
-        return applicationServerApi.evaluatePlugin(toSessionToken(sessionTokenOrPAT), options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void archiveDataSets(final String sessionTokenOrPAT, final List<? extends IDataSetId> dataSetIds,
-            final DataSetArchiveOptions options)
+    @Override public void archiveDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds, final DataSetArchiveOptions options)
     {
-        applicationServerApi.archiveDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, options);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void unarchiveDataSets(final String sessionTokenOrPAT,
-            final List<? extends IDataSetId> dataSetIds, final DataSetUnarchiveOptions options)
+    @Override public void unarchiveDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds,
+            final DataSetUnarchiveOptions options)
     {
-        applicationServerApi.unarchiveDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, options);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void lockDataSets(final String sessionTokenOrPAT, final List<? extends IDataSetId> dataSetIds,
-            final DataSetLockOptions options)
+    @Override public void lockDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds, final DataSetLockOptions options)
     {
-        applicationServerApi.lockDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, options);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public void unlockDataSets(final String sessionTokenOrPAT, final List<? extends IDataSetId> dataSetIds,
-            final DataSetUnlockOptions options)
+    @Override public void unlockDataSets(final String sessionToken, final List<? extends IDataSetId> dataSetIds, final DataSetUnlockOptions options)
     {
-        applicationServerApi.unlockDataSets(toSessionToken(sessionTokenOrPAT), dataSetIds, options);
+        invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public IOperationExecutionResults executeOperations(final String sessionTokenOrPAT,
-            final List<? extends IOperation> operations, final IOperationExecutionOptions options)
+    @Override public IOperationExecutionResults executeOperations(final String sessionToken, final List<? extends IOperation> operations,
+            final IOperationExecutionOptions options)
     {
-        return applicationServerApi.executeOperations(toSessionToken(sessionTokenOrPAT), operations, options);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public Map<String, String> getServerInformation(final String sessionTokenOrPAT)
+    @Override public Map<String, String> getServerInformation(final String sessionToken)
     {
-        return applicationServerApi.getServerInformation(toSessionToken(sessionTokenOrPAT));
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
     @Override public Map<String, String> getServerPublicInformation()
     {
-        return applicationServerApi.getServerPublicInformation();
+        return invocation.proceedWithOriginalArguments();
     }
 
-    @Override public List<String> createPermIdStrings(final String sessionTokenOrPAT, final int count)
+    @Override public List<String> createPermIdStrings(final String sessionToken, final int count)
     {
-        return applicationServerApi.createPermIdStrings(toSessionToken(sessionTokenOrPAT), count);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    @Override public List<String> createCodes(final String sessionTokenOrPAT, final String prefix, final EntityKind entityKind, final int count)
+    @Override public List<String> createCodes(final String sessionToken, final String prefix, final EntityKind entityKind, final int count)
     {
-        return applicationServerApi.createCodes(toSessionToken(sessionTokenOrPAT), prefix, entityKind, count);
+        return invocation.proceedWithNewFirstArgument(toSessionToken(sessionToken));
     }
 
-    private String toSessionToken(String sessionTokenOrPAT)
+    @Override protected IPersonalAccessTokenDAO getPersonalAccessTokenDAO()
     {
-        IPersonalAccessTokenDAO patDAO = CommonServiceProvider.getDAOFactory().getPersonalAccessTokenDAO();
-        PersonalAccessToken patToken = patDAO.getTokenByHash(sessionTokenOrPAT);
-
-        if (patToken == null)
-        {
-            return sessionTokenOrPAT;
-        } else
-        {
-            Date now = new Date();
-
-            if (now.before(patToken.getValidFrom()))
-            {
-                throw new InvalidSessionException("Personal access token is not yet valid.");
-            }
-
-            if (now.after(patToken.getValidUntil()))
-            {
-                throw new InvalidSessionException("Personal access token is no longer valid.");
-            }
-
-            patToken.setLastAccessedAt(now);
-            patDAO.updateToken(patToken);
-
-            final PersonalAccessTokenSession patSession =
-                    patDAO.getSessionByUserIdAndSessionName(patToken.getUserId(), patToken.getSessionName());
-
-            if (patSession == null)
-            {
-                throw new InvalidSessionException("Personal access token session does not exist.");
-            } else
-            {
-                return patSession.getHash();
-            }
-        }
+        return CommonServiceProvider.getDAOFactory().getPersonalAccessTokenDAO();
     }
 
 }
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/get/GetServerInformationOperationExecutor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/get/GetServerInformationOperationExecutor.java
index 7fc2c35f2e8..60562e50581 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/get/GetServerInformationOperationExecutor.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/executor/common/get/GetServerInformationOperationExecutor.java
@@ -25,7 +25,6 @@ import javax.annotation.Resource;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetServerInformationOperation;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetServerInformationOperationResult;
 import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.get.GetServerPublicInformationOperation;
@@ -48,6 +47,9 @@ public class GetServerInformationOperationExecutor
         extends OperationExecutor<GetServerInformationOperation, GetServerInformationOperationResult>
         implements IGetServerInformationOperationExecutor
 {
+    @Autowired
+    private IApplicationServerInternalApi server;
+
     @Resource(name = ExposablePropertyPlaceholderConfigurer.PROPERTY_CONFIGURER_BEAN_NAME)
     private ExposablePropertyPlaceholderConfigurer configurer;
 
@@ -66,9 +68,7 @@ public class GetServerInformationOperationExecutor
         Map<String, String> info = new TreeMap<>();
         info.putAll(getPublicInformation(context));
 
-        info.put("api-version",
-                CommonServiceProvider.getApplicationServerApi().getMajorVersion() + "." + CommonServiceProvider.getApplicationServerApi()
-                        .getMinorVersion());
+        info.put("api-version", server.getMajorVersion() + "." + server.getMinorVersion());
         info.put("project-samples-enabled", Boolean.toString(CommonServiceProvider.getCommonServer().isProjectSamplesEnabled(null)));
         info.put("archiving-configured", Boolean.toString(CommonServiceProvider.getCommonServer().isArchivingConfigured(null)));
         info.put("enabled-technologies", configurer.getResolvedProps().getProperty(Constants.ENABLED_MODULES_KEY));
diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenPostProcessor.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenPostProcessor.java
deleted file mode 100644
index 6f8189842f8..00000000000
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/pat/ApplicationServerApiPersonalAccessTokenPostProcessor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ch.ethz.sis.openbis.generic.server.asapi.v3.pat;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-
-import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi;
-import ch.ethz.sis.openbis.generic.server.asapi.v3.IApplicationServerInternalApi;
-
-public class ApplicationServerApiPersonalAccessTokenPostProcessor implements BeanPostProcessor
-{
-
-    @Override public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException
-    {
-        if (!(bean instanceof IApplicationServerInternalApi))
-        {
-            return bean;
-        }
-
-        if (bean instanceof ApplicationServerApiPersonalAccessTokenDecorator)
-        {
-            return bean;
-        }
-
-        return new ApplicationServerApiPersonalAccessTokenDecorator((IApplicationServerInternalApi) bean);
-    }
-}
diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml
index 5662defdcdc..b057992f553 100644
--- a/openbis/source/java/genericApplicationContext.xml
+++ b/openbis/source/java/genericApplicationContext.xml
@@ -520,25 +520,28 @@
 
 	<bean class="ch.systemsx.cisd.openbis.common.spring.LogAdvisor" />
 	<bean
-		class="ch.systemsx.cisd.openbis.common.spring.MarkerLogApplicationListener" />
+			class="ch.systemsx.cisd.openbis.common.spring.MarkerLogApplicationListener"/>
 
 	<!-- // Optimistic Lock Failure Retrying -->
 	<bean
-		class="ch.systemsx.cisd.openbis.generic.server.OptimisticLockingRetryAdvisor" />
+			class="ch.systemsx.cisd.openbis.generic.server.OptimisticLockingRetryAdvisor"/>
 
 	<!-- // Logging of long running threads -->
 	<bean
-		class="ch.systemsx.cisd.openbis.generic.server.LongRunningThreadAdvisor" />
+			class="ch.systemsx.cisd.openbis.generic.server.LongRunningThreadAdvisor"/>
 
+	<!-- // Personal Access Tokens conversion -->
+	<bean
+			class="ch.systemsx.cisd.openbis.common.pat.PersonalAccessTokenAdvisor"/>
 
 	<!-- //Mail Client Parameters -->
 	<bean id="mail-client-parameters" class="ch.systemsx.cisd.common.mail.MailClientParameters">
-		<property name="from" value="${mail.from}" />
-		<property name="smtpHost" value="${mail.smtp.host}" />
-		<property name="smtpPort" value="${mail.smtp.port}" />
-		<property name="smtpUser" value="${mail.smtp.user}" />
-		<property name="smtpPassword" value="${mail.smtp.password}" />
-		<property name="testAddress" value="${mail.smtp.address}" />
+		<property name="from" value="${mail.from}"/>
+		<property name="smtpHost" value="${mail.smtp.host}"/>
+		<property name="smtpPort" value="${mail.smtp.port}"/>
+		<property name="smtpUser" value="${mail.smtp.user}"/>
+		<property name="smtpPassword" value="${mail.smtp.password}"/>
+		<property name="testAddress" value="${mail.smtp.address}"/>
 	</bean>
 
 	<!-- Maintenance Tasks -->
@@ -591,8 +594,6 @@
 			class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
 	<bean
 			class="ch.systemsx.cisd.openbis.common.spring.AnnotationBeanPostProcessorIgnoringMissingBeans"/>
-	<bean
-			class="ch.ethz.sis.openbis.generic.server.asapi.v3.pat.ApplicationServerApiPersonalAccessTokenPostProcessor"/>
 
 	<plugins:component-scan base-package="ch.systemsx.cisd.openbis"
 							annotation-config="false">
-- 
GitLab