I plan to write an R script using FastR implementation which looks like
java.addToClasspath("build/libs/polyglot-example-f.jar")
clientClass <- java.type('org.algo.polyglot.JavaClient')
javaClient <- new(clientClass, threadPoolSize=10)
javaClient$startScheduleWithFixedDelay(5)
The org.algo.polyglot.JavaClient
class looks like (packaged into a jar):
package org.algo.polyglot;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.graalvm.polyglot.HostAccess;
import java.text.MessageFormat;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.graalvm.polyglot.HostAccess.Export;
public class JavaClient {
private final ScheduledExecutorService service;
@Export
public JavaClient(int threadPoolSize) {
this.service = Executors.newScheduledThreadPool(threadPoolSize);
}
@Export
public void startScheduleWithFixedDelay(int delayInSeconds) {
service.scheduleWithFixedDelay(
() -> {
postMessage(fetchMessage());
},
0,
delayInSeconds,
TimeUnit.SECONDS
);
}
@Export
public void startScheduleWithFixedRate(int period) {
service.scheduleAtFixedRate(
() -> {},
0,
period,
TimeUnit.SECONDS
);
}
@Export
public PolyglotMessage fetchMessage() {
return new PolyglotMessage(
RandomStringUtils.randomAlphabetic(10, 15),
RandomStringUtils.randomAlphabetic(10, 15),
System.currentTimeMillis()
);
}
@Export
public void postMessage(PolyglotMessage message) {
System.out.println("[Printed from JavaClient] Posting message: " + message.toString());
}
}
When running the script with Rscript sample.R --polyglot
the script finished execution with output:
$ Rscript sample.R --polyglot
NULL
I have these motives:
- R script should be the entry point, because my use case requires me to leverage java functionality in R
- Run the R script with the provided jar
- Execute the script with Rscript
Get aThis can be fixed by returning the scheduled future and awaiting on it usingScheduledExecutorService
running with either fixed delay or fixed rate from the R script itself without the R script finishing execution (Stay alive till the service is running)ScheduledFuture$get()
The changes made to the script and code are:
future <- javaClient$startScheduleWithFixedDelay(5)
future$get()
@Export
public ScheduledFuture<?> startScheduleWithFixedDelay(int delayInSeconds) {
return service.scheduleWithFixedDelay(
() -> {
postMessage(fetchMessage());
},
0,
delayInSeconds,
TimeUnit.SECONDS
);
}
- Pass a function to the executor from the R script so that the function is called accordingly by the ScheduledExecutorService (an R function can be passed to run in java code and the receiver will be a functional interface, example:)
myFunc <- function() {
# do some stuff
}
javaClient$runProvidedFunction(myFunc)
@Export
public void runProvidedFunction(Runnable runnable) {
runnable.run();
}
But the access from different threads is restricted
- Build a native image with the runnable script and jar
I want to know if these motives are possible and if possible, the proper way to do so.