4

Is there a way to bind properties from one instance of a class to the properties of an instance of another class (the common fields between the two). See the example below:

class One { String foo String bar } class Two { String foo String bar String baz } def one = new One(foo:'one-foo', bar:'one-bar') def two = new Two() two.properties = one.properties assert "one-foo" == two.foo assert "one-bar" == two.bar assert !two.baz 

The result is an error: Cannot set readonly property: properties for class: Two

2 Answers 2

9

I would choose InvokerHelper.setProperties as I suggesed here.

use(InvokerHelper) { two.setProperties(one.properties) } 
Sign up to request clarification or add additional context in comments.

2 Comments

Does this handles metaClass and class properties safely? I mean, NOT overwriting them?
@Nikem This approach will not override metaClass or class. import org.codehaus.groovy.runtime.InvokerHelper class A { String foo String bar } class B { String foo } A a = new A(foo: 'foo', bar: 'bar')​​​​​​ ​B b = new B() use(InvokerHelper) { b.setProperties(a.properties) } println b.properties​ // [foo:foo, class:class B]
6

The problem is that for every object, .properties includes two built-in Groovy-defined properties, these are the metaClass and class. What you want to do is only set the user-defined properties. You can easily do this using code such as that shown below:

class One { String foo String bar } class Two { String foo String bar String baz } def one = new One(foo:'one-foo', bar:'one-bar') // You'll probably want to define a helper method that does the following 3 lines for any Groovy object def propsMap = one.properties propsMap.remove('metaClass') propsMap.remove('class') def two = new Two(propsMap) assert "one-foo" == two.foo assert "one-bar" == two.bar assert !two.baz 

2 Comments

I am curious about the general approach. I have a web app connecting to a datawarehouse. The domain of the web app is quite different from the tables and data coming from the warehouse. I intend to use the above technic probably in the service layer but would you recommend to have an additional layer responsible to transform legacy objects to your domain objects?
This doesnt work the other way around since baz property is not defined on One

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.