Last changed: Mai 18, 2008 15:34 by
Uwe Schaefer Labels:
java,
wicket,
guice
if there is anyone suffering from
https://issues.apache.org/jira/browse/WICKET-1403
, i added a quick hack to make it possible to restart the server while persisting the application“s state.
not a final solution, but it works for now and makes the development cycle much faster (for me)
The Problem is, that java.lang.reflect.Type is not Serializable right now. The solution was to store it in the Application“s MetaData, which is of course lost when restarting the Application.
What i do here is using XStream in order to 'serialize' the Type to XML, which then can be serialized normally, so that the MetaData-stuff can be dropped.
This is of course not a valid solution to the above problem, as it introduces a dependency to XStream, but it temporarily makes the roundtrip with guice possible.
To anyone using this hack: note that XStream does not necessarily behave consistently on any JVM:
http://xstream.codehaus.org/faq.html#Compatibility
.
package org.apache.wicket.guice;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import org.apache.wicket.Application;
import org.apache.wicket.proxy.IProxyTargetLocator;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
class GuiceProxyTargetLocator implements IProxyTargetLocator
{
private static final long serialVersionUID = 1L;
private final Annotation bindingAnnotation;
private transient Type type;
private final String serializedType;
GuiceProxyTargetLocator(final Type type, final Annotation bindingAnnotation)
{
this.type = type;
final XStream xstream = new XStream(new DomDriver());
this.serializedType = xstream.toXML(type);
this.bindingAnnotation = bindingAnnotation;
}
public Object locateProxyTarget()
{
final GuiceInjectorHolder holder = (GuiceInjectorHolder) Application.get().getMetaData(
GuiceInjectorHolder.INJECTOR_KEY);
if (this.type == null)
{
final XStream xstream = new XStream(new DomDriver());
this.type = (Type) xstream.fromXML(this.serializedType);
}
final Key<?> key;
if (this.bindingAnnotation == null)
{
key = Key.get(TypeLiteral.get(this.type));
}
else
{
key = Key.get(TypeLiteral.get(this.type), this.bindingAnnotation);
}
return holder.getInjector().getInstance(key);
}
}
Thinking twice, we could get away without special serialization requirements for at least any Type extending Class....
This does not solve all cases, but might help some people already.
package org.apache.wicket.guice;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import org.apache.wicket.Application;
import org.apache.wicket.proxy.IProxyTargetLocator;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
class GuiceProxyTargetLocator implements IProxyTargetLocator {
private static final long serialVersionUID = 1L;
private final Annotation bindingAnnotation;
private transient Type type;
private Class serializableType;
GuiceProxyTargetLocator(final Type type, final Annotation bindingAnnotation) {
this.type = type;
if (type instanceof Class) {
this.serializableType = (Class) type;
}
this.bindingAnnotation = bindingAnnotation;
}
public Object locateProxyTarget() {
final GuiceInjectorHolder holder = (GuiceInjectorHolder) Application.get().getMetaData(
GuiceInjectorHolder.INJECTOR_KEY);
if (this.type == null) {
if (this.serializableType != null) {
this.type = this.serializableType;
}
else {
throw new IllegalStateException("Used a non-Class type for injection, which is not Serializable.");
}
}
final Key<?> key;
if (this.bindingAnnotation == null) {
key = Key.get(TypeLiteral.get(this.type));
}
else {
key = Key.get(TypeLiteral.get(this.type), this.bindingAnnotation);
}
return holder.getInjector().getInstance(key);
}
}