Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interfaces and autobeans. #3

Open
jnorthrup opened this issue Feb 5, 2014 · 1 comment
Open

interfaces and autobeans. #3

jnorthrup opened this issue Feb 5, 2014 · 1 comment

Comments

@jnorthrup
Copy link

I have something that you may want to pick up and run with.

im using gwt autobeans and had to figure out a way to make gson work around incompatible proxies on the server side. what works is to use groovy to be the enclosing classloader during TypeAdapter registration and for groovy to copmile the adapter class and register it. the generation code can be cleaned up and some references to my gson singletions exist here. i think the generated fromJson method is now superfluous as well. this is the only groovy in my project, fwiw, using pure java syntax, so cleaner solutions exist with bytecode engineering, but this one was an easy sample to plug in.

cheers.

import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
import groovy.lang.GroovyClassLoader;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;

public class GroovyGsonShimFactory {
private Map<Class, Method> shimMethods = new LinkedHashMap<>();

private void generateGroovyProxy(Class ifaceClass) {
String shimClassName = ifaceClass.getSimpleName() + "$Proxy";
String ifaceClassCanonicalName = ifaceClass.getCanonicalName();
String s = "import com.google.gson.;\n" +
"import org.apache.commons.beanutils.BeanUtils;\n" +
"import java.lang.reflect.
;\n" +
"import java.util.*;\n\n" +
"public class "+shimClassName+" implements "+ifaceClassCanonicalName+" {\n" ;

{
  PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(ifaceClass);
  for (PropertyDescriptor p : propertyDescriptors) {
    String name = p.getName();
    String tname = p.getPropertyType().getCanonicalName();
    s += "public " + tname + " " + name + ";\n";
    s += " " + p.getReadMethod().toGenericString().replace("abstract", "").replace(ifaceClassCanonicalName + ".", "") + "{return " + name + ";};\n";
    Method writeMethod = p.getWriteMethod();
    if (writeMethod != null)
      s += " " + writeMethod.toGenericString().replace("abstract", "").replace(ifaceClassCanonicalName + ".", "").replace(")", " v){" + name + "=v;};") + "\n\n";
  }
}
s+=        "  public static "+ifaceClassCanonicalName+" fromJson(String s) {\n" +
    "    return (" +ifaceClassCanonicalName+
    ")cydesign.strombolian.server.ddl.DefaultDriver.gson().fromJson(s, "+shimClassName+".class);\n" +
    "  }\n" +  
    "  static public interface foo extends InstanceCreator<"+ifaceClassCanonicalName+">, JsonSerializer<"+ifaceClassCanonicalName+">, JsonDeserializer<"+ifaceClassCanonicalName+"> {}\n" +
    "  static {\n" +
    "    cydesign.strombolian.server.ddl.DefaultDriver.builder().registerTypeAdapter("+ifaceClassCanonicalName+".class, new foo() {\n" +
    "      public "+ifaceClassCanonicalName+" deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {\n" +
    "        return context.deserialize(json, "+shimClassName+".class);\n" +
    "      }\n" +
    "\n" +
    "      public "+ifaceClassCanonicalName+" createInstance(java.lang.reflect.Type type) {\n" +
    "        try {\n" +
    "          return new "+shimClassName+"();\n" +
    "        } catch (Exception e) {\n" +
    "          e.printStackTrace(); \n" +
    "        }\n" +
    "        return null;\n" +
    "      }\n" +
    "\n" +
    "      @Override\n" +
    "      public JsonElement serialize("+ifaceClassCanonicalName+" src, Type typeOfSrc, JsonSerializationContext context) {\n" +
    "        LinkedHashMap linkedHashMap = new LinkedHashMap();\n" +
    "        try {\n" +
    "          BeanUtils.populate(src, linkedHashMap);\n" +
    "          return context.serialize(linkedHashMap);\n" +
    "        } catch (Exception e) {\n" +
    "          e.printStackTrace(); \n" +
    "        }\n" +
    "\n" +
    "        return null;\n" +
    "      }\n" +
    "    });\n" +
    "  }\n\n" +
    "};";

System.err.println("" + s);
ClassLoader parent = DefaultDriver.class.getClassLoader();
GroovyClassLoader loader = new GroovyClassLoader(parent);

final Class gClass = loader.parseClass(s);
try {
  Method shimMethod = gClass.getMethod("fromJson", String.class);
  shimMethods.put(ifaceClass, shimMethod);
} catch (NoSuchMethodException e) {
  e.printStackTrace();
}

}

public T getShim(String json, Class ifaceClass) {
if (!shimMethods.containsKey(ifaceClass))
generateGroovyProxy(ifaceClass);
T shim = null;//= gson().shimMethods(json, CowSchema.class);
try {
shim = (T) shimMethods.get(ifaceClass).invoke(null, json);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return shim;
}
}

@adamdubiel
Copy link
Owner

I't been too long since i had time to develop new features in Jason and i feel like this is the day, i will look into this issue after work and post some feedback. Thanks for the tip!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants