Re: How to access global variables from a class?
ÐилÑн ÐÐ°Ð»Ð°Ñ Ð·Ð¾Ð² Via Users <users-GSC0n/0aZo1d/SJB6HiN2Ni2O/[email protected]> Tue, 24 Sep 2024 14:58:28 +0300
| Newsgroups | gmane.comp.lang.groovy.user |
|---|---|
| Message-ID | <[email protected]> |
Hello Per,
thanks for your answer. I used org.slf4j.Logger in my example, in order to show something more understandable. While the constructor for org.slf4j.Logger can be invoked in the script, the objects inserted by OpenHAB are constructed outside of Groovy, are available in the script, and cannot be constructed by the JSR223 script. Using metaClass does indeed work.
But when I try to add @groovy.transform.CompileStatic and @groovy.transform.TypeChecked to the class, it fails:
import org.slf4j.LoggerFactory
import org.slf4j.Logger
Logger logger = LoggerFactory.getLogger("org.openhab.core.model.script.rele1")
@groovy.transform.CompileStatic
@groovy.transform.TypeChecked
class A {
public A() {
logger.info("L")
}
}
A.metaClass.logger = logger
A a = new A()
logger.info('DONE')
Any of the annotations CompileStatic or TypeChecked triggers:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
[Static type checking] - The variable [logger] is undeclared.
I want to have CompileStatic in order to speed up the execution. (I would have used Java directly, but more or less OpenHAB allows Groovy as scripting language, but not Java).
So eventually I pass the objects from the JSR223 via the constructor, e.g. using Binding.
Greetings // Дилян
-----Original Message-----
From: Per Nyfelt <[email protected]>
Reply-To: users-GSC0n/0aZo1d/SJB6HiN2Ni2O/[email protected]
To: users-GSC0n/0aZo1d/SJB6HiN2Ni2O/[email protected]
Subject: Re: How to access global variables from a class?
Date: 24/09/24 00:22:15
Another way which maybe is slightly more what you are after is to augment the class e.g:
@Grab('org.slf4j:slf4j-simple:2.0.16')
import org.slf4j.LoggerFactory
import org.slf4j.Logger
import groovy.transform.Field
logger = LoggerFactory.getLogger("l")
class A {
A() {
logger.info("L")
}
}
A.metaClass.logger = logger
A a = new A()
Or you can pass the binding to the class. From there you can get any "globally" defined variables i.e:
@Grab('org.slf4j:slf4j-simple:2.0.16')
import org.slf4j.LoggerFactory
import org.slf4j.Logger
import groovy.transform.Field
@Field Logger logger = LoggerFactory.getLogger("l")
class A {
Logger logger
public A(Binding binding) {
logger = binding.logger
logger.info("L")
}
}
A a = new A(binding)
Another idea would be to use a closure instead of a class which may or may not be feasible in your case:
@Grab('org.slf4j:slf4j-simple:2.0.16')
import org.slf4j.LoggerFactory
import org.slf4j.Logger
logger = LoggerFactory.getLogger("l")
def c = {
logger.info("L")
}
c.call()
On 9/23/24 22:17, Per Nyfelt wrote:
>
> You have a scope problem and need to move the logger declaration into your A class. Also if slf4j is not available in your classpath, @Grab is your friend.
>
> The following works when running the script in the GroovyScriptEngine:
>
> @Grab('org.slf4j:slf4j-simple:2.0.16')
> import org.slf4j.LoggerFactory
> import org.slf4j.Logger
>
> class A {
> Logger logger = LoggerFactory.getLogger("l")
> public A() {
> logger.info("L")
> }
> }
> A a = new A()
>
> Note: I don't know how OpenHAB is executing the Groovy code. If it is using the GroovyShell then use groovy.grape.Grape.grab('org.slf4j:slf4j-simple:2.0.16') instead.See https://docs.groovy-lang.org/latest/html/documentation/grape.html for details.
>
> Hope this helps.
>
>
> On 8/21/24 13:16, Дилян Палаузов via users wrote:
>
>
> >
> > Hello,
> >
> > OpenHAB 4.2.1 is written in Java and has a Groovy 4.0.11 plugin to programme logic. It allows writing code outside of classes, which is executed immediately. When I place a file openhab/jsr223/test.groovy:
> >
> >
> > import org.slf4j.LoggerFactory
> >
> > logger = LoggerFactory.getLogger("l")
> >
> > class A {
> > public A() {
> > logger.info("L")
> > }
> > }
> > A a = new A()
> >
> >
> > the system logs
> >
> > 2024-08-21 12:15:21.061 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script ‘/etc/openhab/automation/jsr223/test.groovy’: javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: logger for class: A
> >
> > How can I make logger visible within the methods of class A, without passing it as parameter to the constructor?
> >
> > Also asked at https://community.openhab.org/t/groovy-how-to-access-global-variable-from-a-class/ .
> >
> > Kind regards
> > Дилян
> >
>