访问 GAE DB 给出 AccessControlException

Accessing GAE DB gives AccessControlException

我在 Google 的 App Engine 上有一个 Java 应用程序 运行,但我未能成功连接到数据库。我确信这个问题之前一定被问过很多次,但我一直找不到对我有用的东西。我广泛使用了 persistence.xml 文件,我确信这是我的问题所在,但我看不到它。

错误日志显示:

org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions: An SQLException was provoked by the following failure: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup") (SqlExceptionHelper.java:144)

com.mycompany.rfc.web.servlet.ProcessServlet doGet: Problem with servlet operation (ProcessServlet.java:356)
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not open connection
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273)
at com.mycompany.rfc.data.dao.dbimpl.RfcAccess.getAllOpenForUser(RfcAccess.java:25)
at com.mycompany.rfc.web.servlet.ProcessServlet.doGet(ProcessServlet.java:192)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:125)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:37)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.JdbcMySqlConnectionCleanupFilter.doFilter(JdbcMySqlConnectionCleanupFilter.java:60)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:48)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:257)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:145)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:511)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:446)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:453)
at com.google.tracing.CurrentContext.runInContext(CurrentContext.java:276)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:312)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:304)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:450)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:235)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.exception.GenericJDBCException: Could not open connection
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:221)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:157)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.connection(StatementPreparerImpl.java:56)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.doPrepare(StatementPreparerImpl.java:161)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:182)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:159)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1854)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1831)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1811)
at org.hibernate.loader.Loader.doQuery(Loader.java:899)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
at org.hibernate.loader.Loader.doList(Loader.java:2516)
at org.hibernate.loader.Loader.doList(Loader.java:2502)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2332)
at org.hibernate.loader.Loader.list(Loader.java:2327)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264)
... 36 more
Caused by: java.sql.SQLException: An SQLException was provoked by the following failure: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:62)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.<init>(C3P0PooledConnectionPoolManager.java:228)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getPoolManager(AbstractPoolBackedDataSource.java:460)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
at org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:84)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:214)
... 56 more
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:484)
at java.security.AccessController.checkPermission(AccessController.java:698)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at com.google.apphosting.runtime.security.CustomSecurityManager.checkPermission(CustomSecurityManager.java:55)
at com.google.apphosting.runtime.security.CustomSecurityManager.checkAccess(CustomSecurityManager.java:136)
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:445)
at java.util.TimerThread.<init>(Timer.java:499)
at java.util.Timer.<init>(Timer.java:101)
at java.util.Timer.<init>(Timer.java:146)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.poolsInit(C3P0PooledConnectionPoolManager.java:95)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager.<init>(C3P0PooledConnectionPoolManager.java:221)
... 61 more

我的 persistence.xml 文件是: http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<persistence-unit name="rfcJPA2" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <mapping-file>META-INF/orm.xml</mapping-file>
    <properties>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://<IPaddr>:3306/rfc_db" />
        <property name="javax.persistence.jdbc.password" value="<pw>" />
        <property name="javax.persistence.jdbc.user" value="<user>" />
        <property name="hibernate.transaction.factory_class"
            value="org.hibernate.transaction.JDBCTransactionFactory" />
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.hbm2ddl.auto" value="update" />

        <property name="hibernate.connection.provider_class"
            value="org.hibernate.connection.C3P0ConnectionProvider" />

        <property name="hibernate.c3p0.max_size" value="100" />
        <property name="hibernate.c3p0.min_size" value="0" />
        <property name="hibernate.c3p0.acquire_increment" value="1" />
        <property name="hibernate.c3p0.idle_test_period" value="300" />
        <property name="hibernate.c3p0.timeout" value="100" />
    </properties>
</persistence-unit>

我可以在本地运行,但是当我将代码推送到 Google 云时出现异常。我已经使用 MySql 客户端使用 persistence.xml 文件中的 IP 和凭据连接到数据库。

我试过使用 MySQLDialect 方言(目前是 MySQL5Dialect)。我目前使用的是 Hibernate 版本 4.2.0.Final,因为我读到更高版本会产生被 Google.

禁止的线程

在堆栈跟踪中,我注释了 RfcAccess 的第 25 行。

public class RfcAccess extends Access implements IRfcAccess, IAccess {

public RfcAccess() {
    super();
}

@Override
public Map<Long, Rfc> getAllOpenForUser(String user) {
    List<?> results = null;
    results = em.createNamedQuery("getAllOpenRfcForUser").setParameter("owner", user).getResultList(); // This is line 25
    if (results == null) {
        return null;
    }
...
}

public class Access implements IAccess {

EntityManager em;

public Access() {
    em = EMF.get().createEntityManager();
}

public class EMF {
protected static final EntityManagerFactory emfInstance = Persistence
        .createEntityManagerFactory("rfcJPA2");

private EMF() {
}

public static EntityManagerFactory get() {
    return emfInstance;
}
}

在我的 ORM 中,我有以下命名查询

<named-query name="getAllOpenRfcForUser">
    <query>select o from Rfc o where o.status = 0 and o.owner = :owner</query>
    <hint name="org.hibernate.timeout" value="200" />
</named-query>

任何人都可以阐明这一点吗?目前 table (Rfc) 没有在数据库中创建。谢谢。

我终于解决了问题(并了解了 App Engine 在此过程中的工作方式)。原来 C3P0 使用线程——而 GAE 不允许线程。我已经设法使用 DBCP 使它正常工作。