Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Java Executor on AppEngine causes AccessControlException

How do you get java.util.concurrent.Executor or CompletionService to work on Google AppEngine? The classes are all officially white-listed, but I get a runtime security error when trying to submit asynchronous tasks.

Code:

    // uses the async API but this factory makes it so that tasks really
    // happen sequentially
    Executor executor = java.util.concurrent.Executors.newSingleThreadExecutor();
    // wrap Executor in CompletionService
    CompletionService<String> completionService = 
        new ExecutorCompletionService<String>(executor);
    final SomeTask someTask = new SomeTask();
    // this line throws exception
    completionService.submit(new Callable<String>(){
        public String call() {
            return someTask.doNothing("blah");
        }
    });
    // alternately, send Runnable task directly to Executor,
    // which also throws an exception
    executor.execute(new Runnable(){
        public void run() {
            someTask.doNothing("blah");
        }
    });
}

private class SomeTask{
    public String doNothing(String message){
        return message;
    }
}

Exception:

java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323) at java.security.AccessController.checkPermission(AccessController.java:546) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:166) at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:191) at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:288) at java.lang.Thread.init(Thread.java:332) at java.lang.Thread.(Thread.java:565) at java.util.concurrent.Executors$DefaultThreadFactory.newThread(Executors.java:542) at java.util.concurrent.ThreadPoolExecutor.addThread(ThreadPoolExecutor.java:672) at java.util.concurrent.ThreadPoolExecutor.addIfUnderCorePoolSize(ThreadPoolExecutor.java:697) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:652) at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:590) at java.util.concurrent.ExecutorCompletionService.submit(ExecutorCompletionService.java:152)

This code works fine when run on Tomcat or via command-line JVM. However, it chokes in the AppEngine SDK Jetty container (tried with Eclipse plugin and the maven-gae-plugin).

AppEngine is likely designed to not allow potentially dangerous programs to run, so I could see them completely disabling thread creation. However, why would Google allow you to create a class, but not allow you to call methods on it? White-listing java.util.concurrent is misleading.

Is there some other way to do parallel/simultaneous/concurrent tasks on GAE?

like image 724
Drew Avatar asked Dec 18 '22 01:12

Drew


2 Answers

The App Engine Java Overview states

an app cannot spawn threads

This is even more clearly stated in their docs on The Java Servlet Environment

Threads

A Java application cannot create a new java.lang.ThreadGroup nor a new java.lang.Thread. These restrictions also apply to JRE classes that make use of threads. For example, an application cannot create a new java.util.concurrent.ThreadPoolExecutor, or a java.util.Timer. An application can perform operations against the current thread, such as Thread.currentThread().dumpStack().

Perhaps the white-listing is so that you can work with libraries that accept Executors, and you can supply your own Executor that performs the work in the current thread.

You could try the experimental Task Queues

like image 65
Stephen Denne Avatar answered Jan 13 '23 02:01

Stephen Denne


You can start thread in the request context

https://developers.google.com/appengine/docs/java/?csw=1#Java_The_sandbox

like image 33
François Wauquier Avatar answered Jan 13 '23 03:01

François Wauquier