APIが例外をスローすることがあり、そのサーバーは私のリクエストを処理できません。API呼び出しを再度呼び出すAOPアスペクトを作成することにしました。たとえば、5回以降、それでも機能しない場合は例外がスローされます。
私のAOPクラスをご覧ください。これは全身ではありませんが、何が起こっているのかを理解していただければ幸いです。
@Aspect
public class RetryRequestExecutor {
....
@Around("@annotation(com.test.RequestRetriable)")
public Object retryApiRequest(ProceedingJoinPoint point) throws Throwable {
int numAttempts = 0;
ServiceException lastException;
do {
numAttempts++;
try {
preInvokeLog(point);
Object retValue = point.proceed();
postInvokeLog(point);
return retValue;
} catch (ServiceException e) {
lastException = handleServiceException(point, numAttempts, e);
}
} while (numAttempts <= maxRetries);
throw lastException;
}
....
}
これは私のサービスクラスです:
public class UserApiImpl implements UserApi {
...
@Override
public List<DomainUser> retrieveSuspendedUsers() throws Exception{
LOG.debug("Retrieving suspended users.");
...
List<DomainUser> users = new ArrayList<DomainUser>(64);
do {
//Invoke API. AOP invoke it two times!
currentPage = getUsers(retrieveUrl);
...
URL nextLink = currentPage.getNextLink();
if (nextLink == null){
break;
}
...
} while (nextLink != null);
return users;
}
@Override
@RequestRetriable
public UserFeed getUsers(URL feedUrl) throws Exception {
return userService.getFeed(feedUrl, UserFeed.class);
}
...
}
ご覧のとおり、getUsers
メソッドのみに注釈を付けています。メソッドretrieveSuspendedUsers
には注釈が付けられていません。
Springの構成は次のようになります。
<aop:aspectj-autoproxy/>
これで、メソッドを直接呼び出すと、getUsers
すべてが正常に機能します。AOPは1回だけ呼び出します。しかし、retrieveSuspendedUsers
メソッドを呼び出すと、AOPはページごとに2回呼び出します(ページサイズが100のユーザーをページごとに取得します)。私は以下の行のログで見ることができます:
2013-03-11 13:06:40,179 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/]
2013-03-11 13:06:40,180 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/]
2013-03-11 13:06:41,745 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/] finished successfully
2013-03-11 13:06:41,745 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/] finished successfully
API呼び出しは非常に時間がかかるため、追加の不要な呼び出しは避けたいと思います。この動作を修正する方法は?