Установка ETAG/LastModified для представления, отправленного ServerResource
Я знаю, что могу установить свойства ETAG и LastModified на Представление / Представление Info. Но у меня есть простой ресурс, реализованный так:
public class AccountServerResource extends ServerResource implements AccountResource {
private static Logger log = Logger.getLogger(AccountServerResource.class.getName());
@Override
public Account retrieve() {
User user = getClientInfo().getUser();
AccountDAO dao = new AccountDAO();
Account ret = dao.getAccountByEmail(user.getEmail());
log.info("retrieved " + ret);
// getResponse().getEntity() == null at this point !!!
// ---> cannot do this : getResponse().getEntity().setModificationDate(ret.getLastModified());
return ret;
}
}
Представление еще не прикреплено к ответу в настоящее время. Когда / как мне установить теги ETAG/LastModified?
Какова рекомендуемая практика здесь?
---ОБНОВИТЬ---
Я попробовал этот подход без удачи:
@Override
public Account retrieve() {
User user = getClientInfo().getUser();
AccountDAO dao = new AccountDAO(user.getNamespace());
AccountDAO dao = new AccountDAO();
Account ret = dao.getAccountByEmail(user.getEmail());
log.info("retrieved " + ret);
setOnSent(new StrongEtagCallback<Account>(ret));
return ret;
}
И реализация StrongEtagCallback выглядит так:
public class StrongEtagCallback<T extends DomainResource> implements Uniform {
private static SimpleDateFormat df = new SimpleDateFormat("ddMMyyyyHHmmssSSS");
private DomainResource d;
public StrongEtagCallback(T domainResource) {
d = domainResource;
}
@Override
public void handle(Request request, Response response) {
String eTag = d.getClass().getSimpleName() + "-" + d.getId() + "-" + df.format(d.getLastModified());
response.getEntity().setTag(new Tag(eTag, false));
}
}
Где все мои сущности реализуют DomainResource, которые требуют, чтобы у них были ID и LastModified дата.
Но это не работает. Я действительно ожидал, что это сработает, это очень элегантно!
Тем не менее вызывается StrongEtagCallback, ETAG устанавливает серверную часть объекта. Мой Wireshark и мой клиент GWT не видят заголовок E-TAG в ответе на ответ. Дайвинг глубже сейчас.
2 ответа
При исследовании этой проблемы я заметил параллельный поток, запущенный koma на доске обсуждений Restlet, в котором Тим Пайерлс предложил альтернативное и предпочтительное решение, а именно переопределение Resource.toRepresentation().
Как Кома указал в этой теме, переопределение ServerResource.handle()
вызвало сбой соответствия условий (я не уверен почему?), поэтому такой подход проблематичен.
Пример кода переопределения, предоставленного Тимом Пайерлсом:
@Override public Representation toRepresentation(Object source, Variant target) {
Representation rep = super.toRepresentation(source, target);
if (source instanceof HasLastModified) {
HasLastModified hlm = (HasLastModified) source;
rep.setModificationDate(hlm.getLastModified());
}
if (source instanceof HasEtag) {
HasEtag he = (HasEtag) source;
rep.setTag(he.gettag());
}
return rep;
}
Окончательное решение состояло в том, чтобы сделать объект возвращаемого домена локальной переменной и переопределить метод handle() ServerResource. Это безопасно, потому что Javadoc утверждает, что:
один экземпляр ServerResource создается для каждого вызова, обрабатываемого и доступного только одним потоком за раз
Таким образом, реализация выглядит так:
private Account ret = null;
@Override
public Account retrieve() {
User user = getClientInfo().getUser();
AccountDAO dao = new AccountDAO();
ret = dao.getAccountByEmail(UserServiceFactory.getUserService().getCurrentUser().getEmail());
// getResponse().getEntity().setModificationDate(ret.getLastModified());
// lastModified = ret.getLastModified();
log.info("retrieved " + ret);
//setOnSent(new StrongEtagCallback<Account>(ret));
return ret;
}
@Override
public Representation handle() {
Representation representation = super.handle();
if (ret != null) {
new StrongEtagCallback<Account>(ret).handle(getRequest(), getResponse());
}
return representation;
}
Заголовок ETAG теперь отправлен:
HTTP/1.1 200 OK
Content-Type: application/x-java-serialized-object+gwt; charset=UTF-8
ETag: "Account-104-27012012003721199"
Date: Thu, 26 Jan 2012 23:44:32 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.1rc1
Transfer-Encoding: chunked
PS: мое первое решение, которое устанавливает обратный вызов setOnSent
после принятия ответа, поэтому это решение не сработало. Я на самом деле ожидал бы подобный крюк или какой-то setNext()
Рестлет для постобработки. В конце концов, обратный вызов реализует Uniform
интерфейс. ИМО, это лучше вписалось бы в общую архитектуру Рестлета.