[JAVA-1688] Cannot run Client on AppEngine due to thread creation constraints Created: 15/Mar/15  Updated: 05/Nov/18  Resolved: 05/Nov/18

Status: Closed
Project: Java Driver
Component/s: Cluster Management
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Scott Hernandez (Inactive) Assignee: Unassigned
Resolution: Won't Fix Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible

 Description   

TLDR?: use java.util.concurrent.Executors default thread creator instead of new Thread().

See the thread here: https://groups.google.com/forum/?#!msg/google-appengine/4n_YlemnINE/BG6kiRNxWdUJ

And app engine docs here:
https://cloud.google.com/appengine/docs/java/#Java_The_sandbox

Seems like using the specific appengine api is too much, but could be plugable if needed.



 Comments   
Comment by Jeffrey Yemin [ 08/Dec/17 ]

stickfigure is there still interest in getting the Java driver working in GAE?

Comment by Jeff Schnitzer [ 30/Sep/15 ]

I'm happy to help figure out any way to get the driver working on App Engine. I'll reach out to you via the email in your profile. Thanks!

Comment by Jeffrey Yemin [ 30/Sep/15 ]

Hi Jeff,

I'd prefer finding a way where the driver can invert this so that the driver doesn't have to expose a public method that could be subject to all sorts of abuse. I'm open to having a discussion about it if you'd like.

Comment by Jeff Schnitzer [ 30/Sep/15 ]

Nobody uses GAE backends anymore and the feature has been deprecated. You can use the Mongo driver as-is from GAE Managed VMs (which are dressed-up Compute Engine instances) but that technology has a ways to go before it's production ready, and it may never completely replace the use case of "normal" GAE frontends.

The ideal solution, from my perspective, would be to see the monitoring logic encapsulated in a public method by itself. In normal operation, the mongo driver would start a thread which processes this method at intervals as it does now. Running in a thread-constrained environment like GAE, this method could be called within the context of an inbound request at reasonably appropriate intervals. Implemented as a servlet filter (that perhaps does the work in a parallel thread while the main request is executing), this would not require any impact on the business logic of an app.

I would be happy to write and publish such a filter if I could only get access to a run() method that makes a single pass through the monitoring logic. And of course disable the thread that does the check/sleep loop.

Comment by Jeffrey Yemin [ 30/Sep/15 ]

The background tasks are required for the correctness of the driver. See the Server Discovery and Monitoring Specification for more information.

We could make a start on this by limiting support to backends and using background threads.

Comment by Jeff Schnitzer [ 28/Sep/15 ]

Just wanted to point out that it's more complicated than just using the thread creation API. In GAE frontend instances, threads can't outlive the request that started them. So there really needs to be a way of disabling whatever these threads are doing. It appears to be the DefaultServerMonitor (at least, that's the first failure):

Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
at java.security.AccessController.checkPermission(AccessController.java:559)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:429)
at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkAccess(DevAppServerFactory.java:454)
at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:315)
at java.lang.Thread.init(Thread.java:391)
at java.lang.Thread.init(Thread.java:349)
at java.lang.Thread.<init>(Thread.java:548)
at com.mongodb.connection.DefaultServerMonitor.createMonitorThread(DefaultServerMonitor.java:100)
at com.mongodb.connection.DefaultServerMonitor.<init>(DefaultServerMonitor.java:63)
at com.mongodb.connection.DefaultServerMonitorFactory.create(DefaultServerMonitorFactory.java:37)
at com.mongodb.connection.DefaultServer.<init>(DefaultServer.java:61)
at com.mongodb.connection.DefaultClusterableServerFactory.create(DefaultClusterableServerFactory.java:68)
at com.mongodb.connection.BaseCluster.createServer(BaseCluster.java:352)
at com.mongodb.connection.SingleServerCluster.<init>(SingleServerCluster.java:51)
at com.mongodb.connection.DefaultClusterFactory.create(DefaultClusterFactory.java:55)
at com.mongodb.Mongo.createCluster(Mongo.java:660)
at com.mongodb.Mongo.createCluster(Mongo.java:646)
at com.mongodb.Mongo.<init>(Mongo.java:275)
at com.mongodb.MongoClient.<init>(MongoClient.java:184)
at com.mongodb.MongoClient.<init>(MongoClient.java:160)

Comment by Jeffrey Yemin [ 23/Jun/15 ]

You have to use https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/ThreadManager to create threads, even when using an executor service.

In order to get this to work and not add a dependency on App Engine,, we'd have to allow for the injection of a thread creator deep into the driver.

Generated at Thu Feb 08 08:55:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.