I'm trying to implement Java interface with Groovy as follows:
//MyGroovyClassImpl.groovy
class MyGroovyClassImpl implements MyJavaInterface
{
MyGroovyClassImpl()
{
MyGroovyClassImpl.metaClass.getNext = {-> println 'This is next
command.';}
}
}
Then I call above class from Java as follows:
//Java code to access MyGroovyClassImpl.groovy
GroovyClassLoader gcl = new GroovyClassLoader();
Class cls = gcl.parseClass(new File(<path to MyGroovyClassImpl.groovy>));
Object obj = cls.newInstance();
MyJavaInterface myInterface = MyJavaInterface.class.cast(obj);
Binding binding = new Binding();
binding.setVariable("myInterface",myInterface);
GroovyShell gs = new GroovyShell(binding);
gs.evaluate("myInterface.next");
The last line produces the following exception:
groovy.lang.MissingPropertyException: No such property: next for class:
ScriptExecutionContext
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:479)
at Script1.run(Script1.groovy)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:543)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:518)
...
I've added ExpandoMetaClass.enableGlobally(), but the problem persists.
Any help would be greatly appreciated.
Regards,
Setya
--
View this message in context: http://www.nabble.com/Method-created-via-ExpandoMetaClass-is-not-recognized-tp19108704p19108704.html
Sent from the groovy - user mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
please try:
> //MyGroovyClassImpl.groovy
> class MyGroovyClassImpl implements MyJavaInterface
> {
> MyGroovyClassImpl()
> {
> MyGroovyClassImpl.metaClass.getNext = {-> println 'This is next command.';}
> this.metaClass = null
> }
> }
because at the point you add the method the class has already a per
instance meta class, but you call will only affect global meta
classes... also... do you really want to do that each time? how about
> //MyGroovyClassImpl.groovy
> class MyGroovyClassImpl implements MyJavaInterface {
> static {
> this.metaClass.getNext = {-> println 'This is next command.';}{
> }
> }
then it will be executed only once and I think the hack with
this.metaClass = null is also not needed any more.
> The last line produces the following exception:
> groovy.lang.MissingPropertyException: No such property: next for class:
> ScriptExecutionContext
> at
> org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:50)
> at
> org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:479)
> at Script1.run(Script1.groovy)
> at groovy.lang.GroovyShell.evaluate(GroovyShell.java:543)
> at groovy.lang.GroovyShell.evaluate(GroovyShell.java:518)
> ...
>
> I've added ExpandoMetaClass.enableGlobally(), but the problem persists.
you did, hmm.. so maybe I am wrong then... unless... is it the first
thing you do?
bye blackdrag
--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/
Thanks for quick response.
I've tried your suggestions, but none of them works.
Regarding ExpandoMetaClass.enableGlobally(), If I put it in
MyGroovyClassImpl.groovy than the GroovyClassLoader won't parse the file as
instance of MyJavaInterface. If I add it when evaluating the script, it
doesn't take effect.
But If I put those scripts in 1 file it works as expected as follows:
class MyGroovyClassImpl
{
MyGroovyClassImpl()
{
MyGroovyClassImpl.metaClass.getNext = {->println 'This is next
command.';};
}
}
ExpandoMetaClass.enableGlobally();
def context = new MyGroovyClassImpl();
context.next;
Regards,
Setya
--
View this message in context: http://www.nabble.com/Method-created-via-ExpandoMetaClass-is-not-recognized-tp19108704p19110800.html
Sent from the groovy - user mailing list archive at Nabble.com.
>
> I am also trying to learn Groovy and I tried this thing and for me both
> the
> things worked -
>
> 1) setting this.metaClass = null in the MyGroovyClassImpl constructor in
> MyGroovyClassImpl.groovy
>
> 2) setting MyGroovyClassImpl.metaClass.getNext in a static block so that
> it
> happens only once.
>
> Can you please take out a few moments and explain the effect
> "this.metaClass
> = null" internally has? Does setting it null make the instance use the
> global metaclass that has been affected by setting
> "MyGroovyClassImpl.metaClass.getNext"?
Does your class implement a Java (not Groovy) interface ? and you invoke the
script exactly the way I did it from Java (not Groovy) ?
Regards,
Setya
--
View this message in context: http://www.nabble.com/Method-created-via-ExpandoMetaClass-is-not-recognized-tp19108704p19113164.html
does not? hmm... should have.. do you use 1.5.6?
> Regarding ExpandoMetaClass.enableGlobally(), If I put it in
> MyGroovyClassImpl.groovy than the GroovyClassLoader won't parse the file as
> instance of MyJavaInterface. If I add it when evaluating the script, it
> doesn't take effect.
>
> But If I put those scripts in 1 file it works as expected as follows:
>
> class MyGroovyClassImpl
> {
> MyGroovyClassImpl()
> {
> MyGroovyClassImpl.metaClass.getNext = {->println 'This is next
> command.';};
> }
> }
> ExpandoMetaClass.enableGlobally();
> def context = new MyGroovyClassImpl();
> context.next;
ok, imagine you need to call a method or set a field/property on a class
in Groovy. To accomplish this, Groovy needs a MetaClass. Now, this
happens not only for code you see, but also for code you do not see...
for example to set fields in the constructor
This means when the first line of your code is executed in the
constructor you already need a MetaClass. Therefor you can not affect
the current meta class with ExpandoMetaClass.enableGlobally(); in the
constrcutor, beause the point where this would affect the meta class is
already passed.
bye blackdrag
so they do work... strange
> 1) setting this.metaClass = null in the MyGroovyClassImpl constructor in
> MyGroovyClassImpl.groovy
well... null is an invalid meta class. But we ned one and the global
meta class is used to set the per instance meta class. That means if the
global meta class is changed and the current meta class of the object is
"delegted", then the global meta class becomes the new current meta class.
> 2) setting MyGroovyClassImpl.metaClass.getNext in a static block so that
> it happens only once.
this works, because at this point the meta class for the class is not
yet set.. since there is no instance yet. So if you change the global
meta class and then make an instance, then you get the global metaclass
as current meta class for the current instance.
so it is two different effects
bye blackdrag
One thing that I forgot to mention is that if I tried your suggestions in
Eclipse using plain JUnit Test, it worked as expected, but when I run it on
JUnit Plug-in Test it didn't. Is this a known issue when adding
method/property via ExpandoMetaClass in Eclipse Equinox envronment ?
Regards,
Setya
--
View this message in context: http://www.nabble.com/Method-created-via-ExpandoMetaClass-is-not-recognized-tp19108704p19124043.html
Sent from the groovy - user mailing list archive at Nabble.com.
yes
byeblackdrag
--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/
---------------------------------------------------------------------