#1 2019-07-02 08:22:27

Patryx
Member
Registered: 2019-03-25

GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi!
First of all I explain what I do:
I have script file A and script file B - both are in folder which is "Share folder for web access".
In script B I have defined classes which I use in script A.
In script A I do:

GLOBALS.exec("/fileserver/bin/shared/B.groovy");

I don't restart Report Server when I change script here.
I call script A from URL and I get result as JSON.
When I make changes in script A everything works as I expect.
Problem is when I change sth inside class in script B because I cannot see changes of script B from script A...
What's strange if I change name in script B (class name or method name) I get an exception, but when I change sth only inside method of class in script B and call script A I don't see changes which I made in script B.
Is there any caching? Can I foce ReportServer to reload attached script without restarting ReportServer every time I make changes in script?

Last edited by Patryx (2019-07-02 08:23:11)

Offline

#2 2019-07-02 08:40:42

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

I notice that if I go to Report Server Administration, open Terminal and execute script B, than it also starts to work properly. Could you explain how to write script to use in GLOBALS.exec?

Offline

#3 2019-07-02 09:00:11

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Patryx,

please post a minimal version of both scripts where this happens. Ideal would be only one method and a simple output in the method.

Regards,
Eduardo

Offline

#4 2019-07-02 13:26:11

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Script A.groovy:

/* Add nested script files with classes */
GLOBALS.exec("/fileserver/bin/shared/B.groovy");
	
return new MyError(code: 403, message: "Forbidden eror!").createJsonObject().toString();

Script B.groovy:

/* Script with utils classes */

import org.json.*;

/* Class MyError */
public class MyError {
   public int code
   public String message
   
   public JSONObject createJsonObject(String rootName = "error") {
	    JSONObject jo = new JSONObject();
		jo.put("code", this.code ?: JSONObject.NULL);
		jo.put("message", this.message ?: JSONObject.NULL);
		if (rootName) {
			JSONObject mainObj = new JSONObject();
			mainObj.put(rootName, jo ?: JSONObject.NULL);
			return mainObj;			
		} 
		return jo;
   }
}

When I call script:
http://.../reportserver/scriptAccess?path=/bin/shared/A.groovy

I get such a result:

{"error":{"code":403,"message":"Forbidden eror!"}}

Then I change file B.Groovy adding one line:
        jo.put("test", "added test msg");   // new added field

/* Script with utils classes */

import org.json.*;

/* Class MyError */
public class MyError {
   public int code
   public String message
   
   public JSONObject createJsonObject(String rootName = "error") {
	    JSONObject jo = new JSONObject();
		jo.put("code", this.code ?: JSONObject.NULL);
		jo.put("message", this.message ?: JSONObject.NULL);
		jo.put("test", "added test msg");   // new added field
		if (rootName) {
			JSONObject mainObj = new JSONObject();
			mainObj.put(rootName, jo ?: JSONObject.NULL);
			return mainObj;			
		} 
		return jo;
   }
}

When call url again I get the same result:

{"error":{"code":403,"message":"Forbidden eror!"}}

There should have been a field: "test":"added test msg".

Offline

#5 2019-07-02 13:30:08

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Patryx,

here you have a lot of things, including JSON, etc. Does this also happen for a more minimal example? E.g. without JSON. Just some printout lines. If I understand correctly your description it should, or ? If yes please post the most minimal example you can think of where this happens.

Regards,
Eduardo

Offline

#6 2019-07-02 13:43:12

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Eduardo,
It's a minimal one...

I changed for you:
A.groovy:

/* Add nested script files with classes */
GLOBALS.exec("/fileserver/bin/shared/B.groovy");
	
return new MyError().prepareString();

B.groovy:

/* Class MyError */
public class MyError {
   
   public String prepareString() {
		return "Easy example v1";
   }
}

As result:

Easy example v1

I change B.groovy:

/* Class MyError */
public class MyError {
   
   public String prepareString() {
		return "Easy example v2";
   }
}

I get the same string with v1 as a result to call the script A.groovy again.  Changing browser doesn't help (not connected with session).
The example doesn't matter in this case...

Last edited by Patryx (2019-07-02 13:45:39)

Offline

#7 2019-07-02 14:10:12

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Patryx,

thanks for the simple scripts. Compiled scripts are being cached, yes. We will think of a solution of being able to clear the cache, maybe a new terminal command or similar: RS-2755
I will update here when I have more information.

Regards,
Eduardo

Offline

#8 2019-07-03 07:31:24

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Eduardo,
I would be gratefull if I have oportunity to clear such a cache, in terminal or maybe in script before doing GLOBALS.exec.
Any workaround till that time to force to clear a cache? I think restarting ReportServer does not always help, am I right?

Offline

#9 2019-07-05 08:51:08

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Patryx,

yes, both ideas seem good. I noted both into the ticket.

Restarting reportserver should always help as a workaround.

Regards,
Eduardo

Offline

#10 2019-07-05 13:09:50

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi,
Unfortunately restarting server doesn't help!
In my script "A.groovy" I have GLOBALS.exec("B.groovy") and GLOBALS.exec("C.groovy").
"B.groovy" has some utils methods shared between other scripts. "C.groovy" has some classes used by some scripts.
After restarting the server I call from url:

http://reportbase/reportserver/scriptAccess?path=/bin/shared/A.groovy&exception=true

And I get an error that classes (defined in "C.groovy") are unabled to resolve sad
If I want to use script "A.groovy" I have to do FIRST:
1) use Terminal and exec C.groovy
2) or call first http://reportbase/reportserver/scriptAccess?path=/bin/shared/C.groovy

After that "A.groovy" works as I expected...
What's interesting I don't have problem with "B.groovy" - the methods work and are seen by script "A.groovy" without any calling/executiong before.

As a result I think that there is asynchronous mechanism to load scripts for the first time after restarting server so I cannot use GLOBALS.exec at all...
How can I fix this problem?

I see only one solution nowadays: copy contents of script "B.groovy" and "C.groovy" into "A.groovy" and all other scripts when I used GLOBALS.exec...
But the solution is totally inconvenient sad

Offline

#11 2019-09-02 08:35:39

Patryx
Member
Registered: 2019-03-25

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Eduardo!
Is the problem RS-2755 with caching scripts used in GLOBALS.exec(...) resolved in RS 3.1.0 version?
Can I now be sure that all scripts used in GLOBALS.exec(...) will be included in the right order (no asynchronous loading)?

Offline

#12 2019-09-24 06:53:59

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi Patryx,

as you can check in the release notes, RS-2755 was not included in the 3.1.0 beta.

Regards,
Eduardo

Offline

#13 2022-12-13 08:01:36

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Patryx wrote:

Hi,
Unfortunately restarting server doesn't help!
In my script "A.groovy" I have GLOBALS.exec("B.groovy") and GLOBALS.exec("C.groovy").
"B.groovy" has some utils methods shared between other scripts. "C.groovy" has some classes used by some scripts.
After restarting the server I call from url:

http://reportbase/reportserver/scriptAccess?path=/bin/shared/A.groovy&exception=true

And I get an error that classes (defined in "C.groovy") are unabled to resolve sad
If I want to use script "A.groovy" I have to do FIRST:
1) use Terminal and exec C.groovy
2) or call first http://reportbase/reportserver/scriptAccess?path=/bin/shared/C.groovy

After that "A.groovy" works as I expected...
What's interesting I don't have problem with "B.groovy" - the methods work and are seen by script "A.groovy" without any calling/executiong before.

As a result I think that there is asynchronous mechanism to load scripts for the first time after restarting server so I cannot use GLOBALS.exec at all...
How can I fix this problem?

I see only one solution nowadays: copy contents of script "B.groovy" and "C.groovy" into "A.groovy" and all other scripts when I used GLOBALS.exec...
But the solution is totally inconvenient sad

Hi Patryx,

for completeness:
this has always worked as designed. We are looking into the caching issues, but the problem you describe here is not directly related to caching.

In your case, you have A.groovy, B.groovy and C.groovy, where B and C are classes. In this case, you cannot use

GLOBALS.exec()

as groovy tries to compile A and cannot resolve B if you create an instance like this:

new B()

The same for C.

So in this case you have to use:

def bSource = GLOBALS.read('/fileserver/bin/B.groovy')
def bClass = new GroovyClassLoader(getClass().classLoader).parseClass( bSource )
// don't use clazz.newInstance(): https://stackoverflow.com/questions/195321/why-is-class-newinstance-evil
// use getDeclaredConstructor() instead:
def bInstance = bClass.getDeclaredConstructor().newInstance()

return bInstance.prepareString()

for loading the class in B.groovy into the class loader and creating an instance of B. The same for C.

As of ReportServer 4.5.0 you can use the more compact form:

def bClass = GLOBALS.loadClass('B.groovy', 'net.datenwerke.rs.samples.tools.nesting.nestedclass.B')
def bInstance = GLOBALS.newInstance()

I created these two examples for demonstration and will include this information in the documentation:
https://github.com/infofabrik/reportser … estedclass
and
https://github.com/infofabrik/reportser … tipleclass

Regarding the cache issue: I will write here when we have more information.

Regards,
Eduardo

Offline

#14 2022-12-13 11:08:07

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Note that if your .groovy files contain multiple classes, you can use something similar as this example:

https://github.com/infofabrik/reportser … tipleclass

Regards,
Eduardo

Offline

#15 2022-12-15 16:27:29

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi,

regarding cache:
we improved the internal cache implementation, so it will work better in the next ReportServer version 4.5.0. Nevertheless, in some cases, the cache does not work as expected: we discovered it is a Groovy bug which we will send to the Groovy team.
For these cases we added a "clearInternalScriptCache" command that allows to manually clear the script cache. This will also be available as a service: net.datenwerke.rs.scripting.service.scripting.ScriptingService.clearCache()

Regards,
Eduardo

Offline

#16 2023-01-30 18:25:22

eduardo
Administrator
Registered: 2016-11-01
Website

Re: GLOBALS.exec(pathToScriptFile) - is the script file caching?

Hi,

we released RS 4.5.0 where the "clearInternalScriptCache" is available: https://forum.reportserver.net/viewtopic.php?id=3428
https://reportserver.net/releasenotes/RS4.5.0.html

Regards,
Eduardo

Offline

Board footer

Powered by FluxBB