Groovy: Dynamically addings methods with a specific signature - java

So, I need to dynamically create (or inject) methods into an object that have a specific return type and method signature, because a Java tool we're using will be finding this methods via Reflection and checks for void type. Method names will be determined at runtime.
Using metaClass. = { ... } however adds a closure which doesn't show up as a regular method (even if it can be used as one) and also has a return type.
I can't modify the method finding code, and it it not Groovy-aware.
I can't use methodMissing() or invokeMethod() because the method needs to actually exist. If I could overload class.getMethods() I think it would be possible, but I can't figure out how.
Is there any way to do this in Groovy?

You could use AST Transformations to add the code at compile time, but it wont work on classes that you don't compile, so I'm guessing that probably wont work.
You could probably replace the object with a CGLIB based proxy. If you can be more specific about the code in question...
EDIT: A little more info. Groovy metaClass magic is not available in Java unless the Java code were to explicitly call groovyClass.invokeMethod("someMethod",args);. So there isn't a way to do what you're asking with MetaClasses. CGLIB maybe.

Related

Java reflection finding method

I have a problem with finding a method with Java, for example, I have to print a value to System.out via reflection:
public static void print(Object value) {
Method method = PrintStream.class.getMethod("print", value.getClass());
method.invoke(System.out, value);
}
It works fine with strings, but when I pass an instance of MyClass, for example, I receive the following error:
java.lang.NoSuchMethodException: java.io.PrintStream.print(MyClass)
at java.lang.Class.getMethod(Class.java:1786)
at Test.print(Test.java:20)
at Test.main(Test.java:15)
I believe that's because Java cannot find the method with the exact signature, but here java.io.PrintStream.print(java.lang.Object) suits well. How can I find a method that suits the following classes, not just has the same signature? The approach should also work for multiple arguments.
I believe that's because Java cannot find the method with the exact signature ...
That is correct. The reflection APIs don't support this. There is no simple way to replicate Java's (static) method overload resolution when looking up a method reflectively.
The non-simple way is to:
Identify all of the classes and interfaces that MyClass implements. (You can do that reflectively.)
Call PrintStream.class.getMethod("print", type) for each of those class / interface types.
If you get more than one result from step 2, use some heuristic to work out which method is the "best" one to use. (It doesn't have to be one that mirrors what the JLS does, though that would probably be the "least surprising" approach to use.)
There are 3rd party libraries that will do this for you; look at this Q&As for some suggestions:
Getting the best fit Instance Method in Java

How to determine if a Java method modifies an object passed as parameter

I come from a C++ background and I am currently learning Java. One question arose when I have tried using some third party libraries. How do I determine if the call to a method taking an object reference as parameter modifies the object?
In C++ this is clear thanks to the use of the const keyword. If the method signature is:
void foo(Boo& boo);
I know that the referenced object might be modified, while if the method signature is:
void foo(const Boo& boo);
The compiler guarantees that the referenced object is not modified.
I haven't seen something analogous in Java, as only the reference itself can be declared final, not the referenced object, and a final argument doesn't make much sense in the first place since it is passed by value anyway. Therefore, when I see a method such as:
void foo(Boo boo) {...}
How do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)? If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
how do I determine if the object referenced by boo is modified inside the body of the function (maybe using annotations)?
The only way is to read the code unfortunately.
If there is no way to know, is there some widely used convention or some best practices to avoid confusion and bugs?
The common convention is to pass an object which cannot be modified, using a wrapper if needed. This ensure the class cannot modify the object.
List<String> readOnly = Collections.unmodifiableList(list);
If the object is Cloneable, you can also use clone() but another common approach is to use a copy.
List<String> readOnly = new ArrayList<>(list);
If you care about such behaviour, unit tests can show whether a method modifies an object or not. If you have unit tests already, it is usually one or two lines extra to check for this.
There's no such facility built in to the language, unfortunately. A good defensive practice is to define the data objects you pass around as immutable (i.e., without any public method that allows modifying their state). If you are really concerned about this, you could copy/clone an object before passing it to a method you don't trust, but this is usually a redundant precaution.
NOTE: this answer is a more detailed version of
You can also write purity or side-effect annotations in your code — mernst
There exists the Checker Framework among the various things it can check at compile-time via annotations is the IJG Immutablity checker. This checker allows you to annotate object references with #Immutable or #ReadOnly.
The problem is that you often would have to annotate the library yourself. To ease your task the Checker Framework can automatically infer part of the annotations; you will still have to do much yourself.
A side effect analysis is not built into the Java language.
You can perform side effect analysis via manual inspection, but several tools exist to automate the process.
You can use an inference tool (1, 2, 3) to detect whether your code side-effects a parameter.
You can also write purity or side-effect annotations in your code and then use a checking/verification tool (1, 2) to ensure that your code conforms to the annotations you have written.
All of the above-linked tools have limitations, but you might find them useful. If you know of other tools, mention them in comments.
How do I determine if the object referenced by boo is modified inside
the body of the function (maybe using annotations)?
I must agree with other answers that there is no direct way to determine that method will modify your object or not and yes to make sure that method can not modify your Object you all have to do it is from your side.
If there is no way to know, is there some widely used convention or
some best practices to avoid confusion and bugs?
Here the method name comes to the scene. Moving ahead with the naming convention of method we have to take a look at some method declarations which clearly convince you that your Object will not be changed at all.
For example, You know that Arrays.copyOf will not change your actual array, System.out.println(boo) will not change your boo
Method names are real weapons to provide as much information as possible to the method user.(Yes! it's always not possible but quite a good practice to follow.)
Let's consider it in your case that say printBoo will only print, copyBoo will only copy, clearBoo will reset all attributes, checkAndCreateNewBoo will check your boo Object and create new if required.
So, ultimately if we can use them in a proper way caller can be assured with the fact that Object will remain the same after calling the method.
As everyone says, prefer using immutable objects and also avoid void methods
The available purposes of methods like this
void foo(Boo boo) {...}
are to change the state of the object itself or change the object passed as a parameter
void completOrder(Order order) { ... }
//or
void parserTokenEnded(String str) { ... }
There is a way , that the method developer should mark parameter as final , if it is not going to modify the parameter.
public void test(final Object param)
However very few people follow this , so it is difficult to know. However good programmer follow this rule , especially writing the api. If you want to write method and expose it. Make param final to indicate that passed object is not going to be modified.

getting the argument names of a function like netbeans does

Ok, this could be a tricky one. For a code generating tool I need to know methods and arguments of a class. The method name and argument types are the easy ones - just using reflection. But the argument name - and I need the real argument name - is a tricky one because this information is in the javadoc. In my case I use Netbeans 8 and I am pretty sure if Netbeans can get the arguments name I can too. Does anyone know how to read the javadoc to get the argument names of a method?
PS I know this question will pop up. I need the real argument names because the generated code provides an api and it is not very helpful for a developper to use an api where the api methods are something like set_a1, set_a2, and so on.
Indeed, this is tricky, and will involve a considerable effort if you intend to find a general solution that works for arbitrary (third-party) classes and arbitrary Java versions.
However, under certain conditions, there may be a simple solution:
If you can compile the classes on your onw, and if you can use Java 8, then you can use the Method Parameter Reflection infrastructure that was added in Java 8. When compiling the classes with javac -parameters ..., then the parameter names are added to the class file, and can be obtained from the method by calling getParameters on the Method object, and then Parameter#getName()
Parameter parameters[] = method.getParameters();
String name = parameters[0].getName();
...

Is the Method object equivalent to the Command object in the Command design pattern?

I've just discovered about the existence of the Method class in Java.
Is an instance of this class equivalent to an instance of a Command class in the context of the Command design pattern?
If not, what are this class' practical uses?
Is an instance of this class equivalent to an instance of a Command class in the context of the Command design pattern?
No, absolutely not: Method class is part of reflection feature of Java. Command pattern, on the other hand, is language-agnostic, so it can be implemented in any language, including ones that lack reflection capabilities.
The practical use of the Method class is to access methods of classes to which you do not have access at compile time. You can load a class by name, grab its method object - also by name, and perform an invocation.
With this said, it does not mean that you couldn't implement something that behaves like the command pattern using reflection. In fact, you could make your implementation more flexible by eliminating compile-time dependency on your code. For example, you could build a system that take plugins, and requires that plugin classes implement a particular method. Rather than shipping to plugin writers an interface with the signature of the method, you could tell them that as long as their class implements the method that you need, the plugin is going to be accepted. At runtime you would be able to discover the proper method through reflection, and call user code without compile-time dependencies on either side.
This class, as well as the class Field, class Class, are all part of reflection API. This API is used to provide access to object in an indirect way.
The first idea behind reflection was to allow an object to describe itself. For instance an IDE could display all properties of an object for debugging, RAID development and so on.
If reflection is still used that way, it's also used today to discover dynamically the structure of an object or a class and "act on" it without explicitly knowing it : to change the values of its fields or invoke one its methods.
For instance, if you know class A, you can invoke the method m() of A this way :
A a = new A();
a.m();
With reflection, without knowing class A explicitly, you could :
Object a = A.getDeclaredConstructors()[0].newInstance();
Method m = a.getClass().getMethod("m");
m.invoke(a, null);
In the second case, you can imagine a more generic mechanism where you discover methods or fields and invoke them or change their values without knowing them in advance.
So, to answer directly your question, it has nothing to do with the Command design pattern.

Java/Ruby: is there a way to do .constantize or Object.send() in Java?

In Ruby, you can do "var1".constantize to get the actual variable var1.
Ruby also has Model.Send("method name, parameters can be here, etc"), and it would be the same as actually calling that method.
What I want to do.. is... kinda tricky... I want the string "var1 == var2" to be converted to actual variables in my java app, then evaluated.
Is there a way to do this?
Have you considered using JRuby?
As to your questions:
There is no peer to constantize that will allow for an eval like syntax where you can pass in a String and convert it to code in Java. You can do things like Class.forName to load a particular class from a String, but it doesn't sound that is what you are looking for.
You can use the Java reflection API to dynamically invoke methods on a class Check out Jakarta Commons BeanUtils for some utility methods that may help.
In Java, similar behaviour is achieved through the Reflection API. However, since Java is a compiled language, local variables' (within methods, constructors, parameters, etc) information is erased on compilation.
However you still have complete access to class names, hierarchies, methods and fields (class variables).
A good starting point is the Reflection API tutorial or the getClass() method of Object.
In Java if you want a dynamic lookup of variables, you would typically place them in a Map and lookup use the keys of that Map.
Can you explain what you are trying to do in more detail, I suspect what you are trying to do can be done simply a different way in Java.

Categories

Resources