Groovy # symbol before fields - reflection

What does # means before a field name in Groovy? For some classes I am able to access private fields that are not directly accessible, let's take ComposedClosure for example:
public class Person {
private String name
}
def u = new Person(name:"Ron")
println u.#name //Ron
println u.name //Ron
a = {2} >> {3}
println a.#first //first closure object
println a.first //runtime error

It allows you to override groovy's use of property accessors. If you write:
println u.name
groovy will invoke the automatically generated getter Person.getName(). If you write:
println u.#name
it will go directly to the field like it would in Java. In the case of the closure, it seems to have a first field but not a corresponding getFirst accessor.
In the groovy manual, it's documented as the direct field access operator.

It means you're accessing a field directly, rather than going through a getter.
See the Groovy operator docs, although there isn't much more to say. Other than probably avoid it.
The reason it fails for a ComposedClosure is because there's no getter for first (or second).

Related

Provide a Converter for data-binding by defining a pair of SerializableFunction objects

In Vaadin 8 Framework, and Vaadin 10 Flow, the data-binding capability lets us provide a Converter to mediate between the widget’s expected data type (such as String for a TextField) and the data type of the backing bean property (such as Integer number).
In this example, the built-in Converter implementation StringToIntegerConverter is used.
binder
.forField( this.phaseField )
.withConverter(
new StringToIntegerConverter( "Must enter an integer number" )
)
.bind( Panel::getPhase , Panel::setPhase ) ;
But what about defining a Converter for other types? How can I easily define a short-and-sweet Converter? For example, a String-to-UUID converter. I want to show the canonical 36-character hex string in a TextField, and going the other direction, parse that string back into a UUID.
// String to UUID
UUID uuid = UUID.fromString( myString ) ;
// UUID to String
String myString = uuid.toString() ;
I see that Binder.BindingBuilder offers the pair of methods withConverter that both take a pair of SerializableFunction objects.
Binder.BindingBuilder::withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)
Binder.BindingBuilder::withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation, String errorMessage)
➥ So how do I define the pair of SerializableFunction objects/classes?
I noticed that this interface lists a known subinterface ValueProvider<SOURCE,TARGET>. That looks familiar, and I have a hunch it is the key to easily defining a short simple converter. But I do not quite comprehend the syntax with lambdas and all that is going on here.
I am not asking how to write a class implementing Converter. I am asking how to write the pair of SerializableFunction arguments to pass to the Binder.BindingBuilder::withConverter methods listed above as bullet items.
Quoting that JavaDoc:
Interface Binder.BindingBuilder<BEAN,TARGET>
…
withConverter
default <NEWTARGET> Binder.BindingBuilder<BEAN,NEWTARGET> withConverter(SerializableFunction<TARGET,NEWTARGET> toModel, SerializableFunction<NEWTARGET,TARGET> toPresentation)
Maps the binding to another data type using the mapping functions and a possible exception as the error message.
The mapping functions are used to convert between a presentation type, which must match the current target data type of the binding, and a model type, which can be any data type and becomes the new target type of the binding. When invoking bind(ValueProvider, Setter), the target type of the binding must match the getter/setter types.
For instance, a TextField can be bound to an integer-typed property using appropriate functions such as: withConverter(Integer::valueOf, String::valueOf);
Type Parameters:
NEWTARGET - the type to convert to
Parameters:
toModel - the function which can convert from the old target type to the new target type
toPresentation - the function which can convert from the new target type to the old target type
Returns:
a new binding with the appropriate type
Throws:
IllegalStateException - if bind has already been called
You can do it by passing two lambda expressions to withConverter, so something like this:
binder.forField(textField)
.withConverter(text -> UUID.fromString(text), uuid -> uuid.toString())
.bind(/* ... */);
If you need a more complicated conversion, then the right-hand side of the lambda can be surrounded with brackets, e.g.
binder.forField(textField).withConverter( text -> {
if ( text == null ) {
return something;
} else {
return somethingElse;
}
}, uuid -> { return uuid.toString(); } )
.bind(/* ... */);
If you need your converter multiple times, I recommend creating a separate class implementing interface com.vaadin.data.Converter. However, using lambdas is possible, too, as you already know (see answer of #ollitietavainen). But this is not Vaadin specific, it's a Java 8+ feature you can read about e.g. here. Basically, you can use lambdas whereever an object implementing an interface with only one method is required.

Java reflection to set static final field fails after previous reflection

In Java, it turns out that field accessors get cached, and using accessors has side-effects. For example:
class A {
private static final int FOO = 5;
}
Field f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
f.getInt(null); // succeeds
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // fails
whereas
class A {
private static final int FOO = 5;
}
Field mf = Field.class.getDeclaredField("modifiers" );
mf.setAccessible(true);
f = A.class.getDeclaredField("FOO");
f.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.setInt(null, 6); // succeeds
Here's the relevant bit of the stack trace for the failure:
java.lang.IllegalAccessException: Can not set static final int field A.FOO to (int)6
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:100)
at sun.reflect.UnsafeQualifiedStaticIntegerFieldAccessorImpl.setInt(UnsafeQualifiedStaticIntegerFieldAccessorImpl.java:129)
at java.lang.reflect.Field.setInt(Field.java:949)
These two reflective accesses are of course happening in very different parts of my code base, and I don't really want to change the first to fix the second. Is there any way to change the second reflective access to ensure it succeeds in both cases?
I tried looking at the Field object, and it doesn't have any methods that seem like they would help. In the debugger, I noticed overrideFieldAccessor is set on the second Field returned in the first example and doesn't see the changes to the modifiers. I'm not sure what to do about it, though.
If it makes a difference, I'm using openjdk-8.
If you want the modifier hack (don't forget it is a total hack) to work, you need to change the modifiers private field before the first time you access the field.
So, before you do f.getInt(null);, you need to do:
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
The reason is that only one internal FieldAccessor object is created for each field of a class (*), no matter how many different actual java.lang.reflect.Field objects you have. And the check for the final modifier is done once when it constructs the FieldAccessor implementation in the UnsafeFieldAccessorFactory.
When it is determined you can't access final static fields (because, the setAccessible override doesn't works but non-static final fields, but not for static final fields), it will keep failing for every subsequent reflection, even through a different Field object, because it keeps using the same FieldAccessor.
(*) barring synchronization issues; as the source code for Field mentions in a comment:
// NOTE that there is no synchronization used here. It is correct
(though not efficient) to generate more than one FieldAccessor for a
given Field.

Inject anything other than param value

I'm trying to inject anything other than values using the #Query N1QL query syntax but can't get it to work.
Here is the pure N1QL query:
SELECT * from `my-bucket` WHERE _class = 'my.package.MyModel' AND myParam = 'myValue'
I successfully manage to inject a value in Java and get the correct results:
// In my repository
#Query("#{#n1ql.selectEntity} WHERE myParam = $1 AND #{#n1ql.filter}")
Collection<MyModel> myCustomSearch(String value);
// In my business code
myRepository.myCustomSearch("myValue");
However I can't manage to inject anything else (like a param). This doesn't work:
// In my repository
#Query("#{#n1ql.selectEntity} WHERE $1 = 'myValue' AND #{#n1ql.filter}")
Collection<MyModel> myCustomSearch(String param);
// In my business code
myRepository.myCustomSearch("myParam");
Considering that in a pure N1QL query, the value usually is wrapped in single quotes ('') and it's not necessary when injecting it, I'm afraid spring-data-couchbase always wraps injected elements with single or double quotes (thus my query is transformed into
SELECT * from `my-bucket` WHERE _class = 'my.package.MyModel' AND 'myParam' = 'myValue'
which explains why Couchbase doesn't return any result).
Did I miss something? Otherwise, is there a way to bypass the quote injection from spring-data-couchbase?
I am aware I could simply use a com.couchbase.client.java.Bucket and call query on it, but this loses the whole point of spring-data-couchbase for me, which is to always manipulate POJOs and hide the JSON manipulation.
I appreciate any help!
$1 is actually just using the N1QL syntax for parameterized statements. I haven't extensively tested it, but you could use SpEL here. The way to use a method parameter in SpEL is to use the #{[x]} syntax where x is the 0-based index of the parameter to use.
Careful when mixing the two approaches though: as soon as a $x is detected in the statement, Spring Data Couchbase will use all method arguments as the array to populate $x placeholders. So the first argument will map to $1, the second to $2, etc...
So to use both syntax (one to dynamically choose a field name, the other to let N1QL inject the searched value) you'd have to write something like:
#Query("#{#n1ql.selectEntity} WHERE #{[0]} = $2 AND #{#n1ql.filter}")
public List<Entity> findAllBySomeCriteria(String fieldName, String value);
Notice how #{[0]} and $1 will both point to the fieldName parameter, so the N1QL placeholder used is $2, that points to value.
Edit: See #simon-baslé 's answer, even shorter and more elegant than mine.
I think I found the best solution for my needs, in the form of implementing a custom method in my repository.
public interface MyRepositoryCustom {
Collection<MyModel> customN1qlQuery(String query);
}
public interface MyRepository extends CrudRepository<MyModel, String>, MyRepositoryCustom { }
public class MyRepositoryImpl implements MyRepositoryCustom {
#Autowired
RepositoryOperationsMapping templateProvider;
#Override
public Collection<MyModel> customN1qlQuery(String query) {
CouchbaseOperations template = templateProvider.resolve(MyRepository.class, MyModel.class);
return template.findByN1QL(N1qlQuery.simple(query), MyModel.class);
}
}
// In my business code
Collection<MyModel> result = myRepository.customN1qlQuery("select META().id AS _ID, META().cas AS _CAS, * from `" + bucket.name() + "` where _class = '"
+ MyModel.class.getCanonicalName() + "' and " + myCustomParam + " = '" + myCustomValue + "'");
I keep manipulating POJOs, yet I have full control over the N1QL query statement. The only (minor) drawback is that I can no longer inject Spring SpEL syntax (like #{#n1ql.selectEntity} to retrieve the full entity, or #{#n1ql.filter} to filter on the entity class name). I found literal equivalent (as shown in my example above), so I can live with that.

How to get name of method parameter/argument in groovy?

I have groovy script that has a function with 2 arguments, one of which is a hashmap. I want to check the name of a hashmap variable contains a substring or not, inside a function. How do i do it?
def myfunc(String var, HashMap var2)
{
// need a routine to retrive the name of the variable var2
}
It's well explained here :
Getting the name of a method parameter
To access groovy script's method follow syntax :
metaClass.methods
Sounds like you want the --parameters (alias -pa) compiler argument.
Generates metadata for reflection on method parameter names on JDK 8 and above. Defaults to false.
Usage: groovy --parameters Person.groovy
Also available for groovyc, groovyConsole, groovysh and groovy ant tasks. Check out the PR some awesome person contributed...
e.g.
class HelloWorld {
static void speak(String firstName) {
println "Hello $firstName"
}
}
Student.methods.each {
if (it.name === 'speak') println it.parameters
}
// groovy HelloWorld.groovy => "[java.lang.String arg0]"
// groovy -pa HelloWorld.groovy => "[java.lang.String firstName]"

Scala 2.10 Pass field as argument

Think of a case class like this:
case class User(firstname: String, lastname: String)
now think of calling a method check with the firstname
check(User.firstname)
The Problem is, that the method check must have the name of the field too. It must have fieldname and fieldvalue -> "firstname" and "John"
The Question is, is it possible to pass the field of a class instead of its value in the style check(User.firstname)?
I thought check could look like this (preudocode):
def check(fieldName: String, fieldValue: Any) = {
println(fieldName + ": " + fieldValue)
}
or this
def check(field: Field) = {
println(field.getName)
}
I could pass the fieldname as String by hand but the problem is, the String would not change if I refactor the fieldname and it must match.
Maybe a macro could help? Is there any other solution?
enter link description herefirst I assume check method is always return same type(Unit\String) else you need to use generics.
second, you can use Enums for mapping
myEnum match {
case MyEnum.firstname => myObj.firstname
case MyEnum.lastname =>myObj.lastname
case _ => ....
}
if you dont want to use Enums, you will have to use scala reflection.
Scala 2.10 reflection, how do I extract the field values from a case class
If the fieldname is known at compile time you can use macros. Otherwise you can use runtime reflection. So runtime reflection gives you more flexibility, while macros give you better performance and compile time safety.

Resources