You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by "V. Jenks" <za...@gmail.com> on 2007/11/23 21:38:14 UTC

What exactly isn't serializable?

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: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: What exactly isn't serializable?

Posted by Martijn Dashorst <ma...@gmail.com>.
               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 {@link #check()}. When a
non-serializable
 * object is found, a {@link 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 {@link 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
 * {@link 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 {@link #check()}
will just
 * return and you are advised to rely on the {@link
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 <za...@gmail.com> 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: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>


-- 
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/

Re: What exactly isn't serializable?

Posted by Eelco Hillenius <ee...@gmail.com>.
On Nov 23, 2007 1:43 PM, Johan Compagner <jc...@gmail.com> wrote:
> somehow you hold reference to:
> com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
>
> in your page. That seems to be not serializeable so i guess that one needs
> to be transient
> and needs to be re lookuped

Error reporting of serialization errors is much improved in 1.3. Also
notice that in 1.2 you don't need to have everything serialized as
long as you don't run in a cluster. You can turn the check off if you
want (there's a setting for that in the application settings
somewhere).

Eelco

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: What exactly isn't serializable?

Posted by Johan Compagner <jc...@gmail.com>.
somehow you hold reference to:
com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate

in your page. That seems to be not serializeable so i guess that one needs
to be transient
and needs to be re lookuped

johan



On Nov 23, 2007 9:38 PM, V. Jenks <za...@gmail.com> 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<http://nabble.com/>
> .
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>
>