Grails data binding - data-binding

I'm trying to use DataBindingUtils.bindObjectToInstance(object, source) to copy properties from one object to another using this code (which can be run in the Grails console):
import org.codehaus.groovy.grails.web.binding.DataBindingUtils
class Source {
String foo = 'foo'
String bar = 'bar'
}
class Target {
String foo
String bar
}
def s = new Source()
def t = new Target()
def result = DataBindingUtils.bindObjectToInstance(t, s)
assert t.foo == 'foo'
assert t.bar == 'bar'
But the assertions are failing because the properties of t are null, why?

The data binder (below) in Grails has only implemented binding for a select subset of object types, namely Maps and Web Requests. So binding two arbitrary objects isn't implemented.
https://github.com/grails/grails-core/blob/master/grails-web/src/main/groovy/org/codehaus/groovy/grails/web/binding/DataBindingUtils.java

Related

Python unittest Mock an object to not have an attribute

I have a function that runs some code if the object has a certain attribute, and in rare cases if if the object does not have the attribute, it runs different code. It is hard for me to create the object without the attribute for testing. I tried del instance.attribute but got an error. The attribute is actually a #property under the hood.
I have an object instance that has foo attribute. How does one mock it so that when one tries to access instance.foo it raises an AttributeError as usual if there is no attribute?
I tried mock.Mock(side_effect=AttributeError('Boom!')) but it only works with methods.
You could try to use a PropertyMock for the property, and generally you shall be able to set the respective side effect. Here is a simple working example:
from unittest import mock
import pytest
class Foo:
#property
def bar(self):
return "bar"
def test_no_foo():
bar_mock = mock.PropertyMock()
with mock.patch(f"{__name__}.Foo.bar", bar_mock):
bar_mock.side_effect = AttributeError('Boom!')
foo = Foo()
with pytest.raises(AttributeError):
foo.bar
As you patch the property in the class, not in the object, you can can also do this using patch.object if you have access to the object by accessing the class of the object:
def test_no_foo():
bar_mock = mock.PropertyMock()
foo = Foo()
with mock.patch.object(foo.__class__, "bar", bar_mock):
bar_mock.side_effect = AttributeError('Boom!')
with pytest.raises(AttributeError):
foo.bar

How to call Kotlin companion factory method using callBy()?

I have code accepts a class as a parameter and prepares data to call either the constructor for that class of a companion object factory method if the factory method is present.
All works fine when calling the constructor, but I get the error
java.lang.IllegalArgumentException: No argument provided for a required parameter: instance of fun nz.salect.objjson.JVMTest.StudentWithFactory.Companion.fromJson(kotlin.String, kotlin.Int): nz.salect.objjson.JVMTest.StudentWithFactory
when calling the factory method. The factory method in question:
data class StudentWithFactory(val name: String, val years: Int=0) {
companion object {
fun fromJson(name: String="", age: Int = 0):StudentWithFactory {
return StudentWithFactory(name, age)
}
}
}
has no required parameters, unless there is some hidden parameter. Any ideas?
In fact, I reverted removing the parameters completely from fromJson and directly calling the companion method using ::fromJson.callby(emptyMap()). Same error.
It is clear that companion methods need at least one additional parameter. Perhaps the class? Or the companion object?
How can I specify the needed parameter(s)?
The function building up the callBy() is supplied a class (or finds the class from a supplied class) and json names and values.
var funk:KFunction<*>?=null
val companionFuncs=cls.companionObject?.declaredMemberFunctions
if(companionFuncs?.size ?:0 >0){
companionFuncs?.forEach {
if(it.name == "fromJson") funk=it
}
}
val cons:KFunction<T> = if(funk != null)
funk as KFunction<T>
else
cls.primaryConstructor ?: throw IllegalArgumentException("no primary constructor ${cls.simpleName}")
val valuesMap = cons.parameters.filter{it.name in vals}
.associateBy(
{it},
{generateValue(it)}
)
val data = cons.callBy(valuesMap) //as T
return data
In addition to my short answer, a more technical explanation:
Yes, there actually is a hidden parameter and you can see it (for example), if you take a look at the decompiled (to Java) bytecode:
public final class StudentWithFactory {
// ...
public static final class Companion {
// ...
#NotNull
public static StudentWithFactory fromJson$default(StudentWithFactory.Companion var0, String var1, int var2, int var3, Object var4) {
// ...
return var0.fromJson(var1, var2);
}
// ...
}
}
The first parameter (var0) is actually an instance of the companion object. var1 (name) and var2 (age) are the parameters you declared. var3 is a bitmask for determining if explicit values have been passed or if the default ones should be used*. I honestly don't know what var4 is for. It is unused in the Java code. But the imported part is that you only need to worry about var0, var1 and var2 if you want to invoke the function.
So, in the end the non-static version of fromJson* is actually invoked on the instance of the companion object:
var0.fromJson(var1, var2)
*left code out for simplicity
You can use the parameters property to determine how much parameters you have to pass to the function/constructor.
If you call
val paramsConstr = StudentWithFactory::class.primaryConstructor?.parameters
paramsConstr will be of size two as expected, but if you call
val paramsFunc = ::fromJson.parameters
paramsFunc will be of size three. The first element corresponds to the instance of the companion object. So, thats the list of parameters you need to provide.
You can invoke the fromJson like this:
// not using any default parameters
::fromJson.callBy(mapOf(
paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
paramsFunc[1] to "Hello",
paramsFunc[2] to 30
))
// using only the default parameter for "name"
::fromJson.callBy(mapOf(
paramsFunc[0] to StudentWithFactory::class.companionObjectInstance,
paramsFunc[2] to 30
))

Is it possible to implement collection literal initializers for custom classes in Groovy?

For example LibGDX framework has custom made collection classes such as Array<T> and ObjectMap<K, V> which aid app/game performance. Would it be possible to create a literal initializer so that Array could be initialized with for example [1,2,3,4] and ObjectMap with [key:"value"].
I know that access operators [] can be added to objects by implementing putAt/getAt methods but haven't seen anything about literal initializers.
Are they locked down into the language itself like operator overriding is in Java or is there a way to create list/map initializers for custom classes?
One possible method is to manipulate the existing LinkedHashMap.asType() method to accept ObjectMap as a parameter:
def originalMethod = LinkedHashMap.getMetaClass().getMetaMethod("asType", Class)
LinkedHashMap.getMetaClass().asType = { Class clazz ->
if(clazz == ObjectMap) {
def map = new ObjectMap()
delegate.each { key, value -> map.put(key, value) }
map
}
else {
originalMethod.invoke(delegate, clazz)
}
}
You can then do:
def map = [a:1] as ObjectMap
Another option would be to add a method toObjectMap() to the base Map metaClass like so:
Map.getMetaClass().toObjectMap = { ->
def map = new ObjectMap()
delegate.each { key, value -> map.put(key, value) }
map
}
Then, you can do:
def map2 = [a:2].toObjectMap()
Or, just write a utility method to convert Maps to ObjectMaps ;-)

Using Jaxb2Marshaller with multiple classes having same #XmlRootElement name

I am working on a web service using spring-mvc and Jaxb2Marshaller.
I have two classes, both annotated with the same #XmlRootElement name
#XmlRootElement(name="request")
class Foo extends AstractRequest {
}
#XmlRootElement(name="request")
class Bar extends AbstractRequest {
}
All three classes (AbstractRequest, Foo, Bar) are included in the classesToBeBound list in the same order
Now the request that uses Bar works fine. But the one that uses Foo throws a ClassCastException exception during unmarshalling with message Bar cannot be cast to Foo
The controller code is this,
Source source = new StreamSource(new StringReader(body));
Foo request = (Foo) this.jaxb2Marshaller.unmarshal(source);
I guess this is happening because Bar is kind of overriding Foo since it's written after Foo in the list of classes to be bound in the spring-servlet.xml file
However I am also having multiple classes annotated with #XmlRootElement(name="response") and marshalling the response doesn't give any problem.
Is there a way to specify the class to be used by the jaxb2Marshaller for unmarshalling ?
You can pass the class to Jaxb2Marshaller before unmarshal:
Source source = new StreamSource(new StringReader(body));
jaxb2Marshaller.setMappedClass(Foo.class);
Foo request = (Foo) jaxb2Marshaller.unmarshal(source);
You can create an Unmarshaller from the Jaxb2Marshaller, then you can pass the class you want to unmarshal as a parameter to the unmarshal method that takes a Source:
Source source = new StreamSource(new StringReader(body));
Unmarshaller unmarshaller = jaxb2Marshaller.createUnmarshaller();
Foo request = (Foo) unmarshaller.unmarshal(source, Foo.class).getValue();
For more information see:
http://bdoughan.blogspot.com/2011/03/handling-duplicate-xmlrootelement.html

How to access a field's value via reflection (Scala 2.8)

Consider the following code:
class Foo(var name: String = "bar")
Now i try to get the value and the correct type of it via reflection:
val foo = new Foo
val field = foo.getClass.getDeclaredField("name")
field.setAccessible(true)
//This is where it doesn't work
val value = field.get(????)
I tried things like field.get(foo), but that just returns an java.lang.Object but no String. Basically I need the correct type, because I want to invoke a method on it (e. g. toCharArray).
What is the suggested way to do that?
As others have mentioned, the reflection methods return Object so you have to cast. You may be better using the method that the Scala compiler creates for field access rather than having to change the visibility of the private field. (I'm not even sure if the name private field is guaranteed to be the same as that of the accessor methods.)
val foo = new Foo
val method = foo.getClass.getDeclaredMethod("name")
val value = method.get(foo).asInstanceOf[String]
getDeclaredField is a method of java.lang.Class.
You have to change foo.getDeclaredField("name") to foo.getClass.getDeclaredField("name") (or classOf[Foo].getDeclaredField("name")) to get the field.
You can get the type with getType method in class Field but it won't help you because it returns Class[_]. Given than you know that the type is a String you can always cast the value returned using field.get(foo).asInstanceOf[String]
AFAIK, reflection always work with Object, and you have to cast the results yourself.
This is how one can get list of fieldnames and its value of a case class:
First, using reflection, get fields info as follows -
val TUPLE2_OF_FIELDNAME_TO_GETTERS = typeOf[<CLASS>].members
.filter(!_.isMethod)
.map(x => (x.name.toString, classOf[<CLASS>].getDeclaredMethod(x.name.toString.trim)))
How to use it?
getFieldNameAndValue(obj: <CLASS>): Seq[(String, String)] {
var output = Seq[(String, String)]()
for(fieldToGetter <- TUPLE2_OF_FIELDNAME_TO_GETTERS) {
val fieldNameAsString = fieldToGetter._1
val getter = fieldToGetter._2
val fieldValue = getter.invoke(obj).toString
output += (fieldName, fieldValue)
}
}
foo.getClass.getDeclaredField("name").getString(foo)
should work if you want to avoid asInstanceOf. get* is available for various types

Resources