Call Java instance method with no arguments in Clojure - java

I'm trying to call methods that take no arguments on a Java class, but when I do, I get reflection warnings saying that "reference to field [methodName] can't be resolved".
According to this the Clojure docs on Java interop (http://clojure.org/java_interop), "The instance member form works for both fields and methods." How can I tell it that I want a method? It seems to assume that since I'm not passing args that I want a field.

If there are both fields and methods, then the (.member instance) form will invoke the method (which is more common). If you want to force access to the field, the (.-field instance) form will only retrieve the field value.
If you have an example that is not working as you expect, it would be helpful to see the code or error.
There are some circumstances where if the Clojure compiler cannot find the method (by an unknown instance class or parameter types), the error message will indicate it was looking for a field, but this is just an artifact of the order it's evaluating options. Sometimes turning on reflection warnings will help pinpoint the issue better.

Here's an example. It creates a Java class - StringBuilder, initialised with a string. A method with no parameters - reverse - is then called on it and the results are converted to a String by calling the toString method.
user=> (def sb (java.lang.StringBuilder. "Hello World"))
;; #'user/sb
user=> (.toString (.reverse sb))
;; "dlroW olleH"
user=> (.toString (.reverse sb))
;; "Hello World"
user=>
A StringBuilder object is mutable so it retains its state, as a result, the second reverse rolls back the first one. This is not very Clojure like so it has to be used with caution.

Related

groovy issue with groovy.lang.MissingMethodException: No signature of method

folder('AAAA'){
description "BBB"
}
pipelineJob("$CCCC"){
parameters{
stringParam('branch','master')
}
}
I am new in groovy and trying to handle legacy code, I encounter some code like this
actually I don't know what is it stand for , is this mean a function and is folder and pipelineJob a default method? or just a function name.
I got those error message, but don't know where I can fix it
Caught: groovy.lang.MissingMethodException: No signature of method: seed.folder() is applicable for argument types: (String, seed$_run_closure1$_closure3) values: [AAA, seed$_run_closure1$_closure3#3f93e4a8]
Possible solutions: collect(), find()
groovy.lang.MissingMethodException: No signature of method: seed.folder() is applicable for argument types: (String, seed$_run_closure1$_closure3) values: [AAA, seed$_run_closure1$_closure3#3f93e4a8]
Possible solutions: collect(), find()
at seed$_run_closure1.doCall(seed.groovy:35)
at seed.run(seed.groovy:31)
I think you want to start here:
https://github.com/jenkinsci/job-dsl-plugin/blob/master/docs/Job-DSL-Commands.md#folder
Folder is a method on the Pipeline DSL, but it requires you have Cloudbees plugins installed correctly to use (you might not have the environment setup correctly).
Yes, it's a function call, and the curly brackets after are a Closure (ie think fat arrow functions like in javascript () => println('yeah!') ). Groovy has powerful functionality around Closures, but it's very dynamic so it's hard to just bump around in IDE with code assist and figure things out. You'll have to read the docs to figure most things out.
For example description is going to be function too (without the parens), and the next literal is a parameter to it. But, what object is it invoking that function on? Well, that's where things get tricky. It's probably Folder object, but it's either whatever the Closure's this points to or the delegate. Groovy devs can annotate Closures and such so IDE's can provide assistance, but it doesn't always work out that every dev is prudent to properly annotate things.

Java 8 | Using MethodHandle#invokeExact on fields dynamically

My goal is to create a MethodHandle that, by passing a class and a field name, reads that field with a MethodHandle getter and returns the value.
With this method I wanted to return an arbitrary object:
return new ConstantCallSite(MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class))).dynamicInvoker();
I received the Field f via Reflections.
The problem now is that when this method is executed, the typical error for invokeExact (WrongMethodTypeException) occurs:
WrongMethodTypeException: cannot convert MethodHandle(TestClass)String to ()Object
This also applies to ints, floats, etc.
In another thread I also already read that you can use invokeExact dynamically if the return of MethodHandle is changed to Object.
Here is a code snippet from the method, which makes use of passing a static final MethodHandle:
return (T) handle.invokeExact(testObject);
Using MethodHandle#invoke is rather out of the question for me, as I'm after performance. Without invokeExact I could possibly also fall back on using only reflections.
Does anyone know a way to do this or a workaround with similar performance? The latter plays a big role in the project. I thank those in advance who could possibly help with this problem.
A (non-static) getter needs an instance to retrieve the field's value from. You should be able to make this work by adding another Object parameter to the erased method type:
return MethodHandles.lookup().unreflectGetter(f).asType(MethodType.methodType(Object.class, Object.class));
(Also, there's no need to wrap the thing in a ConstantCallsite)

TinyTextImpl insted of String xslt

I have the below XML,
<outer.element>
<bold>
<csc>CSCTEXT</csc>
REST OF THE TEXT
</bold>
</outer.element>,
i try to retrieve the text inside the <outer.element> element tag and sending it to a java method. i get the below exception,
XPathException: A sequence of more than one item is not allowed as the second argument of class:method() ("CSCTEXT", "REST OF THE TEXT").
if i use an array in the java method signature i get the below exception,
"Cannot convert value class net.sf.saxon.tinytree.TinyTextImpl of type text() to class java.lang.String"
how do i send a single concatenated value (class:method() ("CSCTEXT REST OF THE TEXT")) to the java method.?
Thank you in advance.
The first error:
XPathException: A sequence of more than one item is not allowed as the second argument of class:method() ("CSCTEXT", "REST OF THE TEXT").
means that you're calling your Java method with a sequence of values when it is only expecting one.
Using collection classes in the signature of your Java method will tend to mean that the individual items don't get converted, hence the second error "Cannot convert...".
One solution to that is to do the conversion yourself in the function call (for example, by calling the data() function). Or do it in the Java method (call the getStringValue() method on the supplied items).
If I am writing extension functions in Java specifically to be called from XPath/XSLT, then I will nowadays uses Saxon-specific classes in the method signature, for example ZeroOrMore<StringValue>. Saxon will then use exactly the same calling conventions as it uses for native XSLT/XPath functions (for example, implicit atomization) and your called code can do any further conversion needed itself.

How to specify argument type in a dynamically typed language, i.e. Python?

Is there any such equivalent of Java
String myMethod (MyClass argument) {...}
in Python?
Thank you, Tomas
No. (And more stuff to round this up to 15 characters...)
No, there is not.
In fact, checking types is considered "un-Pythonic", because an object of any type that looks enough like the expected type should be treated equally.
Python 3.x has function annotations where you can declare argument and return types:
def myMethod(argument: MyClass) -> str:
...
But currently Python does nothing with them, they serve as documentation only.
I just want to say that I'm in full agreement that type checking is evil. But python is also incredibly flexible and I'm in the mood to be evil. This code will take effect at runtime and not compile time. You could do something similar for return type. Something like this could be useful for debugging and, because it's a decorator, it's easy enough to remove.
For it to be useful for debugging you would have to have a situation where two types had all the same attributes that were getting accessed but with different semantics. So that's a pretty limited case. Other than that, you're about to get a typerror anyways when this code runs. The good news is that this is almost never a problem. I really don't know why people from statically typed languages make such a big deal over it.
def types(*args, **kwargs):
arg_types = args
kwarg_types = kwargs
def decorator(f):
def func(*args, **kwargs):
for arg, arg_type in zip(args, arg_types):
if not isinstance(arg, arg_type):
raise TypeError("Wrong type suckah")
for kw, arg in kwargs.items():
if not isinstance(arg, kwarg_types[kw]):
raise TypeError("this is a bad error message")
return f(*args, **kwargs)
return func
return decorator
#types(int, str, bool, flag=bool)
def demo(i, strng, flag=False):
print i, strng, flag
demo(1, "foo", True)
try:
demo("foo", "bar", flag="foobar")
except TypeError:
print "busted on posargs"
try:
demo(1, "foo", flag=2)
except TypeError:
print "busted on keyargs"
try:
demo(1, "foo", 3)
except TypeError:
print "no use sneaking it through"
No.
In Python, it's the program's
responsibility to use built-in
functions like isinstance() and
issubclass() to test variable types
and correct usage. Python tries to
stay out of your way while giving you
all you need to implement strong type
checking.
from Why is Python a dynamic language and also a strongly typed language. Also
In a dynamically typed language, a
variable is simply a value bound to a
name; the value has a type -- like
"integer" or "string" or "list" -- but
the variable itself doesn't. You could
have a variable which, right now,
holds a number, and later assign a
string to it if you need it to change.
Further, isinstance() and issubclass() can be used to do type-checking. If you want to make sure that argument is of MyClass type, you can have a check inside the function. You can even type-cast the value of the argument (if you have a constructor accepting such value) and assign it to my_object.

JSR223: Calling Java "varargs" methods from script

I have a method that looks like this on Java:
public void myMethod(Object... parms);
But I can't call this method as expected from the scripts.
If, in ruby, I do:
$myObject.myMethod(42);
It gives me org.jruby.exceptions.RaiseException: could not coerce Fixnum to class [Ljava.lang.Object
If I try the following in Javascript:
myObject.myMethod(42);
Then it gives me sun.org.mozilla.javascript.internal.EvaluatorException: Can't find method MyClass.test(number). (#2) in at line number 2
Of course, if I change the signature to take one single object then it works.
I assume that this is because someone along the line does not know how to convert, say Integer to Integer[] with the value at the first position.
I believe something like myMethod({42, 2009}) would work in Ruby, but this seems ugly - I wanted to be able to just do myMethod(42, 2009) to make it less confusing, specially for other languages. Is there any better workaround for this?
Thanks.
Java internally treats the variable-length argument list as an array whose elements are all of the same type. That is the reason why you need to provide an array of objects in your JRuby script.
It works like this:
myMethod [42, 2009].to_java
The to_java method constructs a Java array from a Ruby array. By default, to_java constructs Object arrays as needed in this case. If you need a String array you would use
["a","b","c"].to_java(:string)
More on this at the JRuby wiki
It seems like this is a known bug in jruby. See method dispatch on Java objects / classes should try to find a matching varargs method and NameError thrown when trying to pass argument to a Java method that is defined as having variable length arguments.
According to the link Rhino does support vararg.
Varargs are handled by the compiler as an Object[] which is what the error message describes.
I do not have JRuby experience, but does it work if you have an array argument?

Categories

Resources