Re: Assert that all models are detached at the end of the request?
Why do you throw WicketNotSerializableException when the model is still detached? On Fri, Sep 5, 2008 at 11:11 AM, Kaspar Fischer [EMAIL PROTECTED]wrote: For the sake of completeness, here is the solution I am currently using. It uses, as suggested by Martijn, a custom request cycle and a modified version of SerializableChecker. You have to install the custom request cycle in your application using @Override public RequestCycle newRequestCycle(Request request, Response response) { return new CustomRequestCycle(this, (WebRequest) request, (WebResponse) response); } Hope this helps others, too! Kaspar // * FILE: CustomRequestCycle.java * import java.io.NotSerializableException; import org.apache.wicket.Page; import org.apache.wicket.Response; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WebRequest; import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.request.target.component.IPageRequestTarget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A custom request cycle that checks, when in development mode, that all models of a page are * detached. Currently, only model that are instances of LoadableDetachableModel (including * subclasses) are checked. */ public class CustomRequestCycle extends WebRequestCycle { /** Logging object */ private static final Logger log = LoggerFactory.getLogger(WebRequestCycle.class); public CustomRequestCycle(WebApplication application, WebRequest request, Response response) { super(application, request, response); } @Override protected void onEndRequest() { super.onEndRequest(); if (WebApplication.DEVELOPMENT.equalsIgnoreCase(WebApplication.get().getConfigurationType())) { Page requestPage = getRequest().getPage(); testDetachedObjects(requestPage); if (getRequestTarget() instanceof IPageRequestTarget) { Page responsePage = ((IPageRequestTarget) getRequestTarget()).getPage(); if (responsePage != requestPage) { testDetachedObjects(responsePage); } } } } private void testDetachedObjects(final Page page) { if (page == null) { return; } try { NotSerializableException exception = new NotSerializableException( Model is not detached when attempting to serialize!); DetachedChecker checker = new DetachedChecker(exception); checker.writeObject(page); } catch (Exception ex) { log.error(Couldn't test/serialize the Page: + page + , error: + ex); } } } // * FILE: DetachedChecker.java * import java.io.Externalizable; import java.io.IOException; import java.io.NotSerializableException; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamField; import java.io.OutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Date; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.apache.wicket.Component; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.util.lang.Generics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is taken from Wicket SerializableChecker.java (SVN r687197) and customized slightly * (see comments containing KF). See the latter file for all details, including terms of * use. Notice that this does not replace SerializableChecker; the latter is still run. */ public final class DetachedChecker extends ObjectOutputStream { /** * Exception that is thrown when a non-serializable object was found. */ public static final class WicketNotSerializableException extends WicketRuntimeException { private static final long serialVersionUID = 1L; WicketNotSerializableException(String message, Throwable cause) { super(message, cause); } } /** * Does absolutely nothing. */ private static class NoopOutputStream extends OutputStream { @Override public void close() { } @Override public void flush() { } @Override public void write(byte[] b) { } @Override public void write(byte[] b, int i, int l) { } @Override public void write(int b) { } } private static abstract class ObjectOutputAdaptor implements ObjectOutput { public void close() throws IOException { } public void flush() throws IOException { } public void write(byte[] b) throws IOException { } public void write(byte[] b, int off, int len) throws IOException { } public
Re: Assert that all models are detached at the end of the request?
For the sake of completeness, here is the solution I am currently using. It uses, as suggested by Martijn, a custom request cycle and a modified version of SerializableChecker. You have to install the custom request cycle in your application using @Override public RequestCycle newRequestCycle(Request request, Response response) { return new CustomRequestCycle(this, (WebRequest) request, (WebResponse) response); } Hope this helps others, too! Kaspar // * FILE: CustomRequestCycle.java * import java.io.NotSerializableException; import org.apache.wicket.Page; import org.apache.wicket.Response; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WebRequest; import org.apache.wicket.protocol.http.WebRequestCycle; import org.apache.wicket.request.target.component.IPageRequestTarget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A custom request cycle that checks, when in development mode, that all models of a page are * detached. Currently, only model that are instances of LoadableDetachableModel (including * subclasses) are checked. */ public class CustomRequestCycle extends WebRequestCycle { /** Logging object */ private static final Logger log = LoggerFactory.getLogger(WebRequestCycle.class); public CustomRequestCycle(WebApplication application, WebRequest request, Response response) { super(application, request, response); } @Override protected void onEndRequest() { super.onEndRequest(); if (WebApplication .DEVELOPMENT .equalsIgnoreCase(WebApplication.get().getConfigurationType())) { Page requestPage = getRequest().getPage(); testDetachedObjects(requestPage); if (getRequestTarget() instanceof IPageRequestTarget) { Page responsePage = ((IPageRequestTarget) getRequestTarget()).getPage(); if (responsePage != requestPage) { testDetachedObjects(responsePage); } } } } private void testDetachedObjects(final Page page) { if (page == null) { return; } try { NotSerializableException exception = new NotSerializableException( Model is not detached when attempting to serialize!); DetachedChecker checker = new DetachedChecker(exception); checker.writeObject(page); } catch (Exception ex) { log.error(Couldn't test/serialize the Page: + page + , error: + ex); } } } // * FILE: DetachedChecker.java * import java.io.Externalizable; import java.io.IOException; import java.io.NotSerializableException; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamField; import java.io.OutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Date; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.apache.wicket.Component; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.util.lang.Generics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is taken from Wicket SerializableChecker.java (SVN r687197) and customized slightly * (see comments containing KF). See the latter file for all details, including terms of * use. Notice that this does not replace SerializableChecker; the latter is still run. */ public final class DetachedChecker extends ObjectOutputStream { /** * Exception that is thrown when a non-serializable object was found. */ public static final class WicketNotSerializableException extends WicketRuntimeException { private static final long serialVersionUID = 1L; WicketNotSerializableException(String message, Throwable cause) { super(message, cause); } } /** * Does absolutely nothing. */ private static class NoopOutputStream extends OutputStream { @Override public void close() { } @Override public void flush() { } @Override public void write(byte[] b) { } @Override public void write(byte[] b, int i, int l) { } @Override public void write(int b) { } } private static abstract class ObjectOutputAdaptor implements ObjectOutput { public void close() throws IOException { } public void flush() throws IOException { } public void write(byte[] b) throws IOException { } public void write(byte[] b, int off, int len) throws IOException { } public void write(int b) throws IOException { } public void writeBoolean(boolean v) throws IOException { } public void writeByte(int v) throws IOException
Re: Assert that all models are detached at the end of the request?
Could you perhaps use an aspect for this? On Thu, Aug 28, 2008 at 4:57 PM, Kaspar Fischer [EMAIL PROTECTED] wrote: Is there an easy way to assert that all models are detached at the end of the request? It does not look so easy to check this as models do not have common base class where one could register them for a check... I often use an additional model in a component and store it as a member field; if I forgot to detach() this model in the onDetach() handler, I would have a dangling model. That caused me quite some trouble once and I want to avoid it in the future. Thanks, Kaspar - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
Eelco is on http://chillenious.wordpress.com. The link you mentioned http://day-to-day-stuff.blogspot.com/ is from your's truly. Regards, Erik. Kaspar Fischer wrote: Matijn, thank you for your hint. I searched on your blog, http://martijndashorst.com/blog/, and Eelco's, http://day-to-day-stuff.blogspot.com/, but must have searched for the wrong thing (transient, entity, SerializableChecker)... -- Erik van Oosten http://day-to-day-stuff.blogspot.com/ - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
you could extend the serializerchecker to check for underached models. We did something similar checking for non-transient Entity objects. Iirc the code is either on my blog or Eelco's blog. Martijn On 8/28/08, Igor Vaynberg [EMAIL PROTECTED] wrote: no, there is no easy way to assert that any model has been detached, because they do not keep a flag. in 1.5 we will implement it so that all fields of a component that implement idetachable are detached in the end of request via reflection, so that should help somewhat. -igor On Thu, Aug 28, 2008 at 1:57 PM, Kaspar Fischer [EMAIL PROTECTED] wrote: Is there an easy way to assert that all models are detached at the end of the request? It does not look so easy to check this as models do not have common base class where one could register them for a check... I often use an additional model in a component and store it as a member field; if I forgot to detach() this model in the onDetach() handler, I would have a dangling model. That caused me quite some trouble once and I want to avoid it in the future. Thanks, Kaspar - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Become a Wicket expert, learn from the best: http://wicketinaction.com Apache Wicket 1.3.4 is released Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
Matijn, thank you for your hint. I searched on your blog, http://martijndashorst.com/blog/, and Eelco's, http://day-to-day-stuff.blogspot.com/, but must have searched for the wrong thing (transient, entity, SerializableChecker)... Anyways, I'd like to do what you suggest, but have a few question: I guess I have to provide my own implementation of IObjectStreamFactory in order to force my subclass of SerializableChecker to run (in development mode). For this, do I subclass IObjectStreamFactory.DefaultObjectStreamFactory or WicketObjectStreamFactory? Where would I install this custom IObjectStreamFactory? As to SerializableChecker itself, I think my version simply has to look for models in private void check(Object obj) { if (obj == null) { 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()), exception); } // NEW if (obj instanceof LoadableDetachableModel) { LoadableDetachableModel m = (LoadableDetachableModel)m; if (m.isAttached()) { throw new IllegalStateException(Model not detached!); } } // ... Regards, Kaspar On 29.08.2008, at 08:20, Martijn Dashorst wrote: you could extend the serializerchecker to check for underached models. We did something similar checking for non-transient Entity objects. Iirc the code is either on my blog or Eelco's blog. Martijn On 8/28/08, Igor Vaynberg [EMAIL PROTECTED] wrote: no, there is no easy way to assert that any model has been detached, because they do not keep a flag. in 1.5 we will implement it so that all fields of a component that implement idetachable are detached in the end of request via reflection, so that should help somewhat. -igor On Thu, Aug 28, 2008 at 1:57 PM, Kaspar Fischer [EMAIL PROTECTED] wrote: Is there an easy way to assert that all models are detached at the end of the request? It does not look so easy to check this as models do not have common base class where one could register them for a check... I often use an additional model in a component and store it as a member field; if I forgot to detach() this model in the onDetach() handler, I would have a dangling model. That caused me quite some trouble once and I want to avoid it in the future. Thanks, Kaspar - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- Become a Wicket expert, learn from the best: http://wicketinaction.com Apache Wicket 1.3.4 is released Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
We just do it in CustomRequestCycle#onEndRequest(): @Override protected void onEndRequest() { if (Application.get().isDevelopment()) { // controleer of er hibernate objecten in de pagina vastgehouden worden. // eerst de pagina die het request heeft beantwoord Page requestPage = getRequest().getPage(); testDetachedObjects(requestPage); // als de response een Page heeft, dan deze controleren op de aanwezigheid van // hibernate objecten. if (getRequestTarget() instanceof IPageRequestTarget) { Page responsePage = ((IPageRequestTarget) getRequestTarget()).getPage(); if (responsePage != requestPage) { testDetachedObjects(responsePage); } } } And: private void testDetachedObjects(final Page page) { if (page == null) { return; } 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); } } -- Become a Wicket expert, learn from the best: http://wicketinaction.com Apache Wicket 1.3.4 is released Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
and yes, your implementation of the check looks good. Martijn -- Become a Wicket expert, learn from the best: http://wicketinaction.com Apache Wicket 1.3.4 is released Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
Many, many thanks for this! Very much appreciated. - Kaspar On 29.08.2008, at 15:15, Martijn Dashorst wrote: We just do it in CustomRequestCycle#onEndRequest(): @Override protected void onEndRequest() { if (Application.get().isDevelopment()) { // controleer of er hibernate objecten in de pagina vastgehouden worden. // eerst de pagina die het request heeft beantwoord Page requestPage = getRequest().getPage(); testDetachedObjects(requestPage); // als de response een Page heeft, dan deze controleren op de aanwezigheid van // hibernate objecten. if (getRequestTarget() instanceof IPageRequestTarget) { Page responsePage = ((IPageRequestTarget) getRequestTarget()).getPage(); if (responsePage != requestPage) { testDetachedObjects(responsePage); } } } And: private void testDetachedObjects(final Page page) { if (page == null) { return; } 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); } } -- Become a Wicket expert, learn from the best: http://wicketinaction.com Apache Wicket 1.3.4 is released Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Assert that all models are detached at the end of the request?
Is there an easy way to assert that all models are detached at the end of the request? It does not look so easy to check this as models do not have common base class where one could register them for a check... I often use an additional model in a component and store it as a member field; if I forgot to detach() this model in the onDetach() handler, I would have a dangling model. That caused me quite some trouble once and I want to avoid it in the future. Thanks, Kaspar - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Assert that all models are detached at the end of the request?
no, there is no easy way to assert that any model has been detached, because they do not keep a flag. in 1.5 we will implement it so that all fields of a component that implement idetachable are detached in the end of request via reflection, so that should help somewhat. -igor On Thu, Aug 28, 2008 at 1:57 PM, Kaspar Fischer [EMAIL PROTECTED] wrote: Is there an easy way to assert that all models are detached at the end of the request? It does not look so easy to check this as models do not have common base class where one could register them for a check... I often use an additional model in a component and store it as a member field; if I forgot to detach() this model in the onDetach() handler, I would have a dangling model. That caused me quite some trouble once and I want to avoid it in the future. Thanks, Kaspar - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]