if (pilot == null) pilot = new Pilot();
//get bean interface
final PilotLocal bean = BeanLookup.get("PilotBean");
Pilot and PilotLocal should be serializable. You didn't provide the source
code for that so I assume it is one of them, or one of their fields.
Put the following in your onEndRequest of your requestcycle (or create your
own):
try
{
NotSerializableException exception = new NotSerializableException();
SerializableChecker checker = newAndSerializableChecker(exception);
checker.writeObject(page);
}
catch (Exception ex)
{
log.error("Couldn't test/serialize the Page: " + page + ", error: " + ex);
}
And check the request page and the response page. The following class is
used to perform a serializable check and will show directly which field is
offending.
/**
* Utility class that analyzes objects for non-serializable nodes. Construct
with the
* object you want to check, and then call [EMAIL PROTECTED] #check()}. When a
non-serializable
* object is found, a [EMAIL PROTECTED] WicketNotSerializableException} is
thrown with
a message that
* shows the trace up to the not-serializable object. The exception is
thrown for the
* first non-serializable instance it encounters, so multiple problems will
not be shown.
* <p>
* As this class depends heavily on JDK's serialization internals using
introspection,
* analyzing may not be possible, for instance when the runtime environment
does not have
* sufficient rights to set fields accesible that would otherwise be hidden.
You should
* call [EMAIL PROTECTED] EntityAndSerializableChecker#isAvailable()} to see
whether
this class can
* operate properly. If it doesn't, you should fall back to e.g.
re-throwing/ printing the
* [EMAIL PROTECTED] NotSerializableException} you probably got before using
this
class.
* </p>
*
* @author eelcohillenius
* @author Al Maw
*/
public final class SerializableChecker extends ObjectOutputStream
{
/**
* Exception that is thrown when a non-serializable object was found.
*/
public static class WicketNotSerializableException extends
WicketRuntimeException
{
private static final long serialVersionUID = 1L;
WicketNotSerializableException(String message, Throwable cause)
{
super(message, cause);
}
}
public static class WicketContainsEntityException extends
WicketNotSerializableException
{
private static final long serialVersionUID = 1L;
WicketContainsEntityException(String message, Throwable cause)
{
super(message.replace("field that is not serializable", "veld dat een
Entiteit is"),
cause);
}
}
/**
* Does absolutely nothing.
*/
@SuppressWarnings("unused")
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)
{
}
}
@SuppressWarnings("unused")
private static abstract class ObjectOutputAdaptor implements ObjectOutput
{
public void close()
{
}
public void flush()
{
}
public void write(byte[] b)
{
}
public void write(byte[] b, int off, int len)
{
}
public void write(int b)
{
}
public void writeBoolean(boolean v)
{
}
public void writeByte(int v)
{
}
public void writeBytes(String s)
{
}
public void writeChar(int v)
{
}
public void writeChars(String s)
{
}
public void writeDouble(double v)
{
}
public void writeFloat(float v)
{
}
public void writeInt(int v)
{
}
public void writeLong(long v)
{
}
public void writeShort(int v)
{
}
public void writeUTF(String str)
{
}
}
/** Holds information about the field and the resulting object being traced.
*/
private static final class TraceSlot
{
private final String fieldDescription;
private final Object object;
TraceSlot(Object object, String fieldDescription)
{
super();
this.object = object;
this.fieldDescription = fieldDescription;
}
@Override
public String toString()
{
return object.getClass() + " - " + fieldDescription;
}
}
private static final NoopOutputStream DUMMY_OUTPUT_STREAM = new
NoopOutputStream();
/** log. */
private static final Log log = LogFactory.getLog(
EntityAndSerializableChecker.class);
/** Whether we can execute the tests. If false, check will just return. */
private static boolean available = true;
// this hack - accessing the serialization API through introspection - is
// the only way to use Java serialization for our purposes without writing
// the whole thing from scratch (and even then, it would be limited). This
// way of working is of course fragile for internal API changes, but as we
// do an extra check on availability and we report when we can't use this
// introspection fu, we'll find out soon enough and clients on this class
// can fall back on Java's default exception for serialization errors (which
// sucks and is the main reason for this attempt).
private static final Method LOOKUP_METHOD;
private static final Method GET_CLASS_DATA_LAYOUT_METHOD;
private static final Method GET_NUM_OBJ_FIELDS_METHOD;
private static final Method GET_OBJ_FIELD_VALUES_METHOD;
private static final Method GET_FIELD_METHOD;
private static final Method HAS_WRITE_REPLACE_METHOD_METHOD;
private static final Method INVOKE_WRITE_REPLACE_METHOD;
static
{
try
{
LOOKUP_METHOD =
ObjectStreamClass.class.getDeclaredMethod("lookup", new Class[] {Class.class
,
Boolean.TYPE});
LOOKUP_METHOD.setAccessible(true);
GET_CLASS_DATA_LAYOUT_METHOD =
ObjectStreamClass.class
.getDeclaredMethod("getClassDataLayout", (Class< ? >[]) null);
GET_CLASS_DATA_LAYOUT_METHOD.setAccessible(true);
GET_NUM_OBJ_FIELDS_METHOD =
ObjectStreamClass.class.getDeclaredMethod("getNumObjFields", (Class< ? >[])
null);
GET_NUM_OBJ_FIELDS_METHOD.setAccessible(true);
GET_OBJ_FIELD_VALUES_METHOD =
ObjectStreamClass.class.getDeclaredMethod("getObjFieldValues", new Class[] {
Object.class, Object[].class});
GET_OBJ_FIELD_VALUES_METHOD.setAccessible(true);
GET_FIELD_METHOD =
ObjectStreamField.class.getDeclaredMethod("getField", (Class< ? >[]) null);
GET_FIELD_METHOD.setAccessible(true);
HAS_WRITE_REPLACE_METHOD_METHOD =
ObjectStreamClass.class.getDeclaredMethod("hasWriteReplaceMethod",
(Class< ? >[]) null);
HAS_WRITE_REPLACE_METHOD_METHOD.setAccessible(true);
INVOKE_WRITE_REPLACE_METHOD =
ObjectStreamClass.class.getDeclaredMethod("invokeWriteReplace",
new Class[] {Object.class});
INVOKE_WRITE_REPLACE_METHOD.setAccessible(true);
}
catch (SecurityException e)
{
available = false;
throw new RuntimeException(e);
}
catch (NoSuchMethodException e)
{
available = false;
throw new RuntimeException(e);
}
}
/**
* Gets whether we can execute the tests. If false, calling [EMAIL PROTECTED]
#check()}
will just
* return and you are advised to rely on the [EMAIL PROTECTED]
NotSerializableException}.
* Clients are advised to call this method prior to calling the check
method.
*
* @return whether security settings and underlying API etc allow for
accessing the
* serialization API using introspection
*/
public static boolean isAvailable()
{
return available;
}
/** object stack that with the trace path. */
private final LinkedList<TraceSlot> traceStack = new
LinkedList<TraceSlot>();
/** set for checking circular references. */
private final Map checked = new IdentityHashMap();
/** string stack with current names pushed. */
private LinkedList<String> nameStack = new LinkedList<String>();
/** root object being analyzed. */
private Object root;
/** cache for classes - writeObject methods. */
private Map writeObjectMethodCache = new HashMap();
/** current simple field name. */
private String simpleName = "";
/** current full field description. */
private String fieldDescription;
/** Exception that should be set as the cause when throwing a new exception.
*/
private NotSerializableException exception;
/**
* Construct.
*
* @param exception
* exception that should be set as the cause when throwing a new
exception
* @throws IOException
*/
public EntityAndSerializableChecker(NotSerializableException exception)
throws IOException
{
this.exception = exception;
}
/**
* @see java.io.ObjectOutputStream#reset()
*/
@Override
public void reset()
{
root = null;
checked.clear();
fieldDescription = null;
simpleName = null;
traceStack.clear();
nameStack.clear();
writeObjectMethodCache.clear();
}
@SuppressWarnings("unchecked")
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())
.toString(), exception);
}
ObjectStreamClass desc;
for (;;)
{
try
{
desc =
(ObjectStreamClass) LOOKUP_METHOD
.invoke(null, new Object[] {cls, Boolean.TRUE});
Class repCl;
if (!((Boolean) HAS_WRITE_REPLACE_METHOD_METHOD.invoke(desc, (Object[])
null))
.booleanValue()
|| (obj = INVOKE_WRITE_REPLACE_METHOD.invoke(desc, new Object[] {obj})) ==
null
|| (repCl = obj.getClass()) == cls)
{
break;
}
cls = repCl;
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
}
if (cls.isPrimitive())
{
// skip
}
else if (cls.isArray())
{
checked.put(obj, null);
Class ccl = cls.getComponentType();
if (!(ccl.isPrimitive()))
{
Object[] objs = (Object[]) obj;
for (int i = 0; i < objs.length; i++)
{
String arrayPos = "[" + i + "]";
simpleName = arrayPos;
fieldDescription += arrayPos;
check(objs[i]);
}
}
}
else if (obj instanceof Externalizable && (!Proxy.isProxyClass(cls)))
{
Externalizable extObj = (Externalizable) obj;
try
{
extObj.writeExternal(new ObjectOutputAdaptor()
{
private int count = 0;
public void writeObject(Object streamObj)
{
// Check for circular reference.
if (checked.containsKey(streamObj))
{
return;
}
checked.put(streamObj, null);
String arrayPos = "[write:" + count++ + "]";
simpleName = arrayPos;
fieldDescription += arrayPos;
check(streamObj);
}
});
}
catch (Exception e)
{
if (e instanceof WicketNotSerializableException)
{
throw (WicketNotSerializableException) e;
}
log.warn("error delegating to Externalizable : " + e.getMessage() + ", path:
"
+ currentPath());
}
}
else
{
Method writeObjectMethod = null;
Object o = writeObjectMethodCache.get(cls);
if (o != null)
{
if (o instanceof Method)
{
writeObjectMethod = (Method) o;
}
}
else
{
try
{
writeObjectMethod =
cls.getDeclaredMethod("writeObject",
new Class[] {java.io.ObjectOutputStream.class});
}
catch (SecurityException e)
{
// we can't access/ set accessible to true
writeObjectMethodCache.put(cls, Boolean.FALSE);
}
catch (NoSuchMethodException e)
{
// cls doesn't have that method
writeObjectMethodCache.put(cls, Boolean.FALSE);
}
}
final Object original = obj;
if (writeObjectMethod != null)
{
class InterceptingObjectOutputStream extends ObjectOutputStream
{
private int counter;
InterceptingObjectOutputStream() throws IOException
{
super(DUMMY_OUTPUT_STREAM);
enableReplaceObject(true);
}
@Override
protected Object replaceObject(Object streamObj)
{
if (streamObj == original)
{
return streamObj;
}
counter++;
// Check for circular reference.
if (checked.containsKey(streamObj))
{
return null;
}
checked.put(original, null);
String arrayPos = "[write:" + counter + "]";
simpleName = arrayPos;
fieldDescription += arrayPos;
check(streamObj);
return streamObj;
}
}
try
{
InterceptingObjectOutputStream ioos = new InterceptingObjectOutputStream();
ioos.writeObject(obj);
}
catch (Exception e)
{
if (e instanceof WicketNotSerializableException)
{
throw (WicketNotSerializableException) e;
}
log.warn("error delegating to writeObject : " + e.getMessage() + ", path: "
+ currentPath());
}
}
else
{
Object[] slots;
try
{
slots = (Object[]) GET_CLASS_DATA_LAYOUT_METHOD.invoke(desc, (Object[])
null);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
for (int i = 0; i < slots.length; i++)
{
ObjectStreamClass slotDesc;
try
{
Field descField = slots[i].getClass().getDeclaredField("desc");
descField.setAccessible(true);
slotDesc = (ObjectStreamClass) descField.get(slots[i]);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
checked.put(obj, null);
checkFields(obj, slotDesc);
}
}
}
traceStack.removeLast();
nameStack.removeLast();
}
private void checkFields(Object obj, ObjectStreamClass desc)
{
int numFields;
try
{
numFields =
((Integer) GET_NUM_OBJ_FIELDS_METHOD.invoke(desc, (Object[])
null)).intValue();
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
if (numFields > 0)
{
int numPrimFields;
ObjectStreamField[] fields = desc.getFields();
Object[] objVals = new Object[numFields];
numPrimFields = fields.length - objVals.length;
try
{
GET_OBJ_FIELD_VALUES_METHOD.invoke(desc, new Object[] {obj, objVals});
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
for (int i = 0; i < objVals.length; i++)
{
if (objVals[i] instanceof String || objVals[i] instanceof Number
|| objVals[i] instanceof Date || objVals[i] instanceof Boolean
|| objVals[i] instanceof Class)
{
// fitler out common cases
continue;
}
// Check for circular reference.
if (checked.containsKey(objVals[i]))
{
continue;
}
ObjectStreamField fieldDesc = fields[numPrimFields + i];
Field field;
try
{
field = (Field) GET_FIELD_METHOD.invoke(fieldDesc, (Object[]) null);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
simpleName = field.getName();
fieldDescription = field.toString();
check(objVals[i]);
}
}
}
/**
* @return name from root to current node concatted with slashes
*/
private StringBuffer currentPath()
{
StringBuffer b = new StringBuffer();
for (Iterator it = nameStack.iterator(); it.hasNext();)
{
b.append(it.next());
if (it.hasNext())
{
b.append('/');
}
}
return b;
}
/**
* Dump with identation.
*
* @param type
* the type that couldn't be serialized
* @return A very pretty dump
*/
private final String toPrettyPrintedStack(String type)
{
StringBuffer result = new StringBuffer();
StringBuffer spaces = new StringBuffer();
result.append("Unable to serialize class: ");
result.append(type);
result.append("\nField hierarchy is:");
for (Iterator i = traceStack.listIterator(); i.hasNext();)
{
spaces.append(" ");
TraceSlot slot = (TraceSlot) i.next();
result.append("\n").append(spaces).append(slot.fieldDescription);
result.append(" [class=").append(slot.object.getClass().getName());
if (slot.object instanceof Component)
{
Component component = (Component) slot.object;
result.append(", path=").append(component.getPath());
}
result.append("]");
}
result.append(" <----- field that is not serializable");
return result.toString();
}
/**
* @see java.io.ObjectOutputStream#writeObjectOverride(java.lang.Object)
*/
@Override
protected final void writeObjectOverride(Object obj)
{
if (!available)
{
return;
}
root = obj;
if (fieldDescription == null)
{
fieldDescription = (root instanceof Component) ? ((Component)
root).getPath() : "";
}
check(root);
}
}
Martijn
On Nov 23, 2007 9:38 PM, V. Jenks <[EMAIL PROTECTED]> wrote:
>
> I'm upgrading from Wicket 1.2.4 to 1.2.6 and there's obviously a change
> I'm
> not able to find concerning the session (or...who knows?)
>
> I've got a simple pair of pages, one for viewing a list of entity beans
> (EJB3) and one for editing a chosen entity from the list page. I'm
> comparing it to dozens of pages I've built like this in the past in
> previous
> versions of Wicket and I just can't figure out why I keep getting this
> exception:
>
> ***********************************************************
> Internal error cloning object. Make sure all dependent objects implement
> Serializable. Class: com.myapp.ui.admin.EditPilot
> wicket.WicketRuntimeException: Internal error cloning object. Make sure
> all
> dependent objects implement Serializable. Class:
> com.myapp.ui.admin.EditPilot
> at
> wicket.protocol.http.HttpSessionStore.setAttribute(HttpSessionStore.java
> :63)
> at wicket.Session.setAttribute(Session.java:952)
> at wicket.PageMap.put(PageMap.java:531)
> at wicket.Session.touch(Session.java:744)
> at wicket.Page.renderPage(Page.java:414)
> at
> wicket.request.target.component.BookmarkablePageRequestTarget.respond(
> BookmarkablePageRequestTarget.java:226)
> at
> wicket.request.compound.DefaultResponseStrategy.respond(
> DefaultResponseStrategy.java:49)
> at
> wicket.request.compound.AbstractCompoundRequestCycleProcessor.respond(
> AbstractCompoundRequestCycleProcessor.java:66)
> at
> wicket.RequestCycle.doProcessEventsAndRespond(RequestCycle.java:902)
> at
> wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:929)
> at wicket.RequestCycle.step(RequestCycle.java:1010)
> at wicket.RequestCycle.steps(RequestCycle.java:1084)
> at wicket.RequestCycle.request(RequestCycle.java:454)
> at wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:219)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
> at
> org.apache.catalina.core.ApplicationFilterChain.servletService(
> ApplicationFilterChain.java:411)
> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(
> ApplicationFilterChain.java:317)
> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(
> ApplicationFilterChain.java:198)
> at
> org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(
> MonitorFilter.java:390)
> at
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(
> ApplicationFilterChain.java:230)
> at
> org.apache.catalina.core.ApplicationFilterChain.doFilter(
> ApplicationFilterChain.java:198)
> at
> org.apache.catalina.core.StandardWrapperValve.invoke(
> StandardWrapperValve.java:288)
> at
> org.apache.catalina.core.StandardContextValve.invokeInternal(
> StandardContextValve.java:271)
> at
> org.apache.catalina.core.StandardContextValve.invoke(
> StandardContextValve.java:202)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :632)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :577)
> at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
> at
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java
> :206)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :632)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :577)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
> :571)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
> at
> org.apache.catalina.core.StandardEngineValve.invoke(
> StandardEngineValve.java:150)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :632)
> at
> org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java
> :577)
> at
> org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java
> :571)
> at
> org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
> at
> org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:270)
> at
>
> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter
> (DefaultProcessorTask.java:637)
> at
> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(
> DefaultProcessorTask.java:568)
> at
> com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(
> DefaultProcessorTask.java:813)
> at
>
> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask
> (DefaultReadTask.java:339)
> at
> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
> DefaultReadTask.java:261)
> at
> com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(
> DefaultReadTask.java:212)
> at
> com.sun.enterprise.web.portunif.PortUnificationPipeline$PUTask.doTask(
> PortUnificationPipeline.java:361)
> at
> com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
> at
> com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(
> SSLWorkerThread.java:106)
> Caused by: java.io.NotSerializableException:
> com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
> at
> java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java
> :1509)
> at
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
> at
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java
> :1392)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
> at
> java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java
> :1509)
> at
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
> at
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java
> :1392)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
> at
> java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1338)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1146)
> at
> java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java
> :1509)
> at
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
> at
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java
> :1392)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
> at
> java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1338)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1146)
> at
> java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java
> :1509)
> at
> java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
> at
> java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java
> :1392)
> at
> java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
> at
> java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
> at
> wicket.protocol.http.HttpSessionStore.setAttribute(HttpSessionStore.java
> :57)
> ... 47 more
> ***********************************************************
>
> Here's the EditPilot class:
>
> ***********************************************************
> public class EditPilot extends PublicPage
> {
> public EditPilot()
> {
> this(null);
> }
>
> public EditPilot(Pilot pilot)
> {
> //add page components
> add(new FeedbackPanel("feedbackPanel"));
>
> //edit or new?
> if (pilot == null) pilot = new Pilot();
>
> //get bean interface
> final PilotLocal bean = BeanLookup.get("PilotBean");
>
> //init form object
> final Form pilotForm = new Form("pilotForm", new
> CompoundPropertyModel(pilot));
>
> //add form components
> pilotForm.add(new TextField("salutation")
> .add(StringValidator.lengthBetween(1, 3)));
> pilotForm.add(new TextField("firstName")
> .setRequired(true)
> .add(StringValidator.lengthBetween(2,
> 50)));
> pilotForm.add(new TextField("lastName")
> .setRequired(true)
> .add(StringValidator.lengthBetween(2,
> 50)));
>
> pilotForm.add(new Button("saveButton")
> {
> public void onSubmit()
> {
> try
> {
> //save form values, redirect
> Pilot pilot =
> (Pilot)pilotForm.getModelObject();
> bean.persist(pilot);
>
> setResponsePage(new ViewPilots());
> }
> catch (Exception exp)
> {
> info(exp.getMessage());
> }
> }
> });
>
> //add cancel button
> pilotForm.add(new Button("cancelButton")
> {
> public void onSubmit()
> {
> setResponsePage(new ViewPilots());
> }
> }.setDefaultFormProcessing(false));
>
> //add form to page
> add(pilotForm);
> }
> }
>
> which inherits this...
>
> public abstract class PublicPage extends BasePage
> {
> public PublicPage()
> {
> }
> }
>
> which inherits this...
>
> public abstract class BasePage extends WebPage
> {
> public BasePage()
> {
> //add page components
> add(new UserHeaderPanel("userHeaderPanel"));
> add(new TabPanel("tabPanel"));
> add(new FooterPanel("footerPanel"));
> }
>
> protected void redirect(String url) //utility method for
> redirecting
> externally
> {
> //disable wicket redirecting
> getRequestCycle().setRedirect(false);
>
> //make sure no output for the current cycle is sent
> getRequestCycle().setRequestTarget(
> EmptyRequestTarget.getInstance());
>
> //set absolute URL to redirect to
> getResponse().redirect(url);
> }
> }
>
> ...and Abraham beget Lot...whom beget......etc.
> ***********************************************************
>
> Here's the BeanLookup class:
>
> ***********************************************************
> public class BeanLookup
> {
> public static <T> T get(String name)
> {
> T bean = null;
>
> try
> {
> InitialContext ctx = new InitialContext();
> bean = (T)ctx.lookup("java:comp/env/" + name);
> }
> catch (NamingException exp)
> {
> }
>
> return bean;
> }
> }
> ***********************************************************
>
> Here's my 'app' class:
>
> ***********************************************************
> public class MyApp extends WebApplication
> {
> @Override
> public Class getHomePage()
> {
> return Index.class;
> }
>
> @Override
> public void init()
> {
> //create external images resource
> getSharedResources().add("imageResource", new
> ImageResource());
> }
>
> /**
> * set custom session class
> */
> @Override
> public ISessionFactory getSessionFactory()
> {
> return new ISessionFactory()
> {
> public Session newSession()
> {
> return new UserSession(MyApp.this);
> }
> };
> }
> }
> ***********************************************************
>
> I've tried implementing Serializable all over the place but it doesn't
> help...and comparing this to apps I've built in the past in previous
> versions of Wicket, this is "correct". I can pull up the ViewPilots page
> just fine but if I even add a reference to the EditPilot page (i.e.
> setResponsePage(new EditPilot())), then that page also throws the same
> exception.
>
> I'm on Ubuntu 7.10 and using Glassfish v2 as the container...but have
> replicated the issue on Winxp and Vista. As you can see from the error,
> everything is being developed in Netbeans.
>
> What's the obvious trivial detail I'm forgetting? :)
>
> Thanks!
> --
> View this message in context:
> http://www.nabble.com/What-exactly-isn%27t-serializable--tf4863669.html#a13918451
> Sent from the Wicket - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
--
Buy Wicket in Action: http://manning.com/dashorst
Apache Wicket 1.3.0-rc1 is released
Get it now: http://www.apache.org/dyn/closer.cgi/wicket/1.3.0-rc1/