Al mio $ dayjob usiamo qualcosa che descrivi, e cosa ho presented at several meetups (vedi diapositiva 23 e on). Non devi perderti Wicket per quello.
Fondamentalmente ciò che si fa è copiare il codice di controllo del serializzatore e modificarlo per includere il controllo e controllare gli errori di serializzazione. Quindi nell'ultima fase del ciclo di richiesta si esegue il proprio correttore serializzatore sulle pagine interessate.
Il controllo che abbiamo creato assegni per la nostra classe di base comune, e che l'entità abbia o meno persistito. Se è così, falliamo la richiesta. Inoltre abbiamo un callback Ajax nella nostra pagina di base che controlla un attributo di sessione per vedere se c'è stato un errore di serializzazione. In tal caso, reindirizziamo alla pagina di errore con l'errore di serializzazione, per garantire che gli sviluppatori non ignorino l'entità nella gerarchia di pagine.
Ecco la carne del nostro controllo (il metodo check
riscritta dal check serializzatore di Wicket):
private void check(Object obj)
{
if (obj == null || obj.getClass().isAnnotationPresent(Deprecated.class)
|| obj.getClass().isAnnotationPresent(SkipClass.class))
{
return;
}
Class<?> cls = obj.getClass();
nameStack.add(simpleName);
traceStack.add(new TraceSlot(obj, fieldDescription));
if (!(obj instanceof Serializable) && (!Proxy.isProxyClass(cls)))
{
throw new WicketNotSerializableException(toPrettyPrintedStack(obj.getClass().getName())
.toString(), exception);
}
if (obj instanceof IdObject)
{
Serializable id = ((IdObject) obj).getIdAsSerializable();
if (id != null && !(id instanceof Long && ((Long) id) <= 0))
{
throw new WicketContainsEntityException(toPrettyPrintedStack(
obj.getClass().getName()).toString(), exception);
}
}
if (obj instanceof LoadableDetachableModel)
{
LoadableDetachableModel<?> ldm = (LoadableDetachableModel<?>) obj;
if (ldm.isAttached())
{
throw new WicketContainsAttachedLDMException(toPrettyPrintedStack(
obj.getClass().getName()).toString(), exception);
}
}
Per Wicket 1.5 abbiamo creato il nostro PageStoreManager
che esegue questi controlli (e un sacco di altre cose, come consentendo una cronologia di navigazione lato server per i nostri utenti). Abbiamo fornito il nostro RequestAdapter
sovrascrivendo PageStoreManager#newRequestAdapter(IPageManagerContext context)
e fare il check-serializzazione l'adattatore:
class DetachCheckingRequestAdapter extends RequestAdapter
{
public DetachCheckingRequestAdapter(IPageManagerContext context)
{
super(context);
}
@Override
protected void storeTouchedPages(List<IManageablePage> touchedPages)
{
super.storeTouchedPages(touchedPages);
if (Application.get().usesDevelopmentConfig())
{
for (IManageablePage curPage : touchedPages)
{
if (!((Page) curPage).isErrorPage())
testDetachedObjects(curPage);
}
}
}
private void testDetachedObjects(final IManageablePage page)
{
try
{
NotSerializableException exception = new NotSerializableException();
EntityAndSerializableChecker checker = new EntityAndSerializableChecker(exception);
checker.writeObject(page);
}
catch (Exception ex)
{
log.error("Couldn't test/serialize the Page: " + page + ", error: " + ex);
Session.get().setDetachException(ex);
}
}
}
fonte
2011-11-30 10:30:30
Ho implementato questo nella mia domanda, e funziona come un fascino. Sarebbe un po 'più ordinato se Wicket avesse un comodo punto di collegamento per i controlli di sessione, ma questo è abbastanza mantenibile. Grazie. –
Prego. Sei libero di inviare una richiesta di funzionalità. Sfortunatamente non possiamo fare un controllo generico, ma essere in grado di estendere la struttura in un modo più ovvio sarebbe bello. –