Java Style Dynamic Proxies in Go?

Motivation

I developed a pattern for Unmarshalling JSON that has keys with multiple possible value types.
I know, they are a PITA but when it is from an API you do not control, what can you do other than mitigate the problems on your side.

Say you have something that has 3 different types, I want to unmarshall to a different interface depending on the type, and that interface can just delegate to the native map[string]interface{}

Did this once already in Java and it works a charm!

I wrote an immutable object library for Java that used a Map<String,Object> as a delegate to an interface that used Dynamic Proxy to route the calls to the delegated map. The neat thing about this was I got a very nice “versioned” immutable object implementation for very little effort.

This allowed me to use Interfaces that delegated to Map<String,Object> and switch out the interfaces at runtime to supply the correct semantic.

This is just a single part of the library I wrote, but it is the core piece of it. Fairly straight forward.

“Mutations” created sparse maps that delegated to the previous map.

Interface method names were keys into the map and returned values, if they did not exist it just searched in the nested maps until it found a key.

t think I have made a pretty comprehensive search and have not found anything that does this same thing in Go. I could be wrong.

I am looking to go the equivalent in Go and see how it could be done with an Interface and a map[string]interface{} as well, as I “port” a pretty substantial code base that I am very familiar with from Java to Go.

Before I go and reimplement this particular wheel I wanted to see if anyone had already done something like this before me.

I think I understand the overlay part of your question: That sounds a lot like context.Context.Value. You could build that with something like this:

type Map interface {
    Get(key interface{}) (value interface{})
    Set(key, value interface{})
}

type goMap map[interface{}]interface{}

func (m goMap) Get(key interface{}) interface{} {
    return m[key]
}

func (m goMap) Set(key, value interface{}) {
    m[key] = value
}

type fallbackMap struct {
    Map
    Fallback Map
}

func (m fallbackMap) Get(key interface{}) interface{} {
    v := m.Map.Get(key)
    if v != nil {
        return v
    }
    return v.Fallback.Get(key)
}

func MakeFallbackMap(fallback Map) Map {
    return fallbackMap{make(goMap), fallback}
}

But I don’t know Java so I don’t exactly understand what a “dynamic proxy” is or what the code you’re showing does, but it sounds like you want to intercept calls to something? Can you write some pseudo-code that demonstrates what it’d look like to use the API in Go?

This is the gist of the idea.

public class MapBackedJavaBeanProxy extends AbstractInvocationHandler {
    private MapBackedJavaBeanProxy(@Nonnull final Map<String, Object> values) {
        if (values instanceof ImmutableSortedMap) { this.values = values; }
        else { this.values = ImmutableSortedMap.copyOf(values); }
    }

    @Override
    protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
        final String methodName = method.getName();
        if (this.values.containsKey(methodName)) { return this.values.get(methodName); }
        else { throw new IllegalArgumentException(methodName + " does not exist in " + Joiner.on(',').join(values.keySet())); }
    }
}

The handleInvocation() method is the magic dynamic part.

this basically takes the Interface method name and converts it into a key to lookup the return from a delegate map. This is the basic functionally of a DynamicProxy.

It dynamically proxies method calls.

The you use that to prove an implemenation of an interface with:

public static <T> Builder<T> as(@Nonnull final Class<T> cls)
    {
        return new Builder<T>()
        {
            @Override public T from(@Nonnull final Map<String, Object> map)
            {
                return Reflection.newProxy(cls, new MapBackedJavaBeanProxy(map));
            }
        };
    }

So in Go if I had an interface like:

type Property interface {
	Name() string
	Type() string
}

I would just pass that into the as() method and it would automagically map Name() and Type() to
delegate_map["Name"] and delegate_map["Type"]

The closest I have gotten in Go so far is something like this.

type Property interface {
	Name() string
	Type() string
}

type property struct {
	name     string
	delegate map[string]interface{}
}

func (p property) Name() string {
	return p.name
}

func (p property) Type() string {
	return p.delegate["type"].(string)
}

And while this gives me a type safe abstraction around a delegate map instance, it does not do it via method name like the Java version allows me to. I have to implement every method in the interface manually.

I really want to be able to do like the Java implementation, that is very powerful for wrapping things like JSON or XML that is unmarshalled into a generic structure and turning it into a typesafe thing you can use dynamically.

Ok after much more searching, reading, clicking on rabbit holes on Google I finally found an article that tells me what I needed to know.

There’s one big limitation on reflection. While you can use reflection to create new functions , there’s no way to create new methods at runtime. This means you cannot use reflection to implement an interface at runtime.

That is that, other than code generation, which I am already have a solution to I created that generates the crapload of boilerplate code to map nested structs/interfaces from JSON from JSON Schemas.

I had hope to simplify that generated code with something that said, call a method => intercept the method call and do this instead …

Apparently that would require creating an instance of the Interface as a struct and implementing the methods at runtime.

I see that you already posted that generating methods cannot be done right now, but I’m still curious about the point of this. My understanding of what this would look like to use would be something like this:

type Property interface {
    Name() string
    Type() string
}


func DynamicPropertyOf(m map[string]interface{}) Property {
    var p Property
    ProxyMap(m, &p)    // some magic function that creates a property implementation
    return p
}

func DoSomethingWithProperty(m map[string]interface{}) (name, ptype string) {
    // is this how you want to use it?
    p := DynamicPropertyOf(m)
    return p.Name(), p.Type()
}

If this is the case, then how is this any better than:

type Property struct {
    Name string
    Type string
}

func PropertyOf(m map[string]interface{}) Property {
    var p Property
    ProxyMap(m, &p)    // some not-so-magic function that populates p's fields
    return p
}

func DoSomethingWithProperty(m map[string]interface{}) (name, ptype string) {
    // is this how you want to use it?
    p := DynamicPropertyOf(m)
    return p.Name, p.Type
}

Thanks for the responses!

type Property interface {
    Name() string
    Type() string
}

by definition is immutable, and that is my main driving goal.
It also gives me a better abstraction to work with, I can wrap it with another delegate implementation of Property and it is still the same interface.

For example, if I wanted to make Name return something that was in UpperCamelCase I could just wrap that interface with another and implement just Name to do that.

Your second example can be done with the following approach:

type Property struct {
    Name string `json:"name"` <= the tags is the "magic" that makes this work
    Type string `json:"type" <= the tags is the "magic" that makes this work
}

Unfortunately that tag “magic” only works on Exported fields. If I want to Unmarshal and Marshall from/to an immutable struct I have to do something like the following.

type Property interface {
	Name() string
	Type() string
}

type property struct {
	name     string
	_type     string
}

func (p *property) Name() string {
	return p.name
}

func (p *property) Type() string {
	return p._type
}

func (p *property) MarshalJSON() ([]byte, error) {
    // bunch of Javaesque boilerplate mapping code :-(
}
func (p *property) UnmarshalJSON(bytes []byte) error {
   // bunch of Javaesque boilerplate mapping code :-(
}

Being able to just delegate to a map[string]interface{} gets rid all the boilerplate that I am having to generate right now as well as makes marshalling and unmarshalling a one liner.

If anyone has any suggestions about some Go-ish way to do this better I am all for them!

The driving motivation for this is I am using JSON Schema to define my domain objects right now and I have written a generator to generate all the boilerplate code. It works well, but now I am working on refactoring the generator code, which has to READ the JSON Schema, which is obviously JSON and there is no way to Unmarshall into anything other than map[string]interface{} because it could be pretty much anything.

So I am working on an approach I developed in other languages which is Unmarshall to a map, then just wrap each map with a proxy interface which just delegates to the map. Bingo, typesafe map access.

Mainly because JSON Schema property definitions can be multi-variant types. I can switch on type and pick the appropriate wrapper interface at runtime. Kind of like the standard library xml parse does for Token parsing.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.