java - MySQL 访问被拒绝的 GAE CloudSQL

标签 java google-app-engine jpa eclipselink google-cloud-sql

我有一个 Web 应用程序在以下环境下运行良好

  • GWT 2.4.0
  • RestEasy 2.3.2.Final JAX-RS 和 JAXB
  • Hibernate JPA 2.0(hibernate-entitymanager + hibernate-validator)4.2.0.Final
  • 本地主机上的 MySQL 5.5.22 (Ubuntu 12.04)
  • VMware 2.6 tomcat 服务器

应用程序成功地使用 JAX-RS、JAXB、Jackson JSON 提供程序、Hibernate JPA 注释,所有这些都混合到同一个 DTO 中。

我正在尝试将其移植到 GAE CloudSQL。我遇到了 MySQL 访问错误。我不得不将 ORM 从 Hibernate 更改为 EclipseLink 2.3.2。

提醒:

  • 我恭敬地请求回答者不要假设我的代码中可能存在错误,而不是解决手头的问题 - 如何将基于 Hibernate 的 JPA 移植到 EclipseLink。除非您认为我的适用于 Hibernate 的设置或代码需要更改才能与 GAE CloudSQL 一起使用。原因是,该应用程序在 Hibernate 下运行良好。

  • 请不要提供有关如何使 Hibernate 与 GAE CloudSQL 一起工作的说明,除非它涉及 Hibernate JPA 2.0。我意识到 Internet 上有一个关于如何在没有 JPA 的情况下将 Hibernate 与 CloudSQL 结合使用的示例。

  • 如果您有关于如何使 DataNucleus JPA 2.0 与 GAE CloudSQL 一起工作的信息,那将非常有帮助。我无法让它工作,这就是我使用 EclipseLink 的原因。

  • 此外,MySQL 数据源用户和密码能够通过 Eclipse 数据源资源管理器或 SQL Explorer 或 SQL Squirrel Client 访问数据库。因此,用户/密码没有问题。除非您认为我需要修改 MqSQL 用户或主机设置。

  • 我已经在 mysql.db 表中添加了一行以包含主机 localhost.localdomain。

  • 我已经将启动/调试配置修改为 -Drdbms.url=jdbc:mysql://localhost:3306/Site?user=site&password=random&useInformationSchema=true&useUnicode=true&characterEncoding=UTF8&useServerPrepStmts=true,如 http://developers.google.com/cloud-sql/docs/developers_guide_java 中“在开发期间使用本地 MySQL 实例”中的说明.

  • 您的解决建议必须涉及 JPA 2.0 而不是 1.0。

  • 我不是在访问我的 CloudSQL 帐户,而是在 Ubuntu 12.04 上运行的本地主机 MySQL 数据库。我还没有尝试使用此应用程序访问我的 CloudSQL 数据库。

可能是,我的 persistence.xml 中需要更多行?可能是我的 EMF 设置需要修改?可能是,GAE 需要与 Hibernate 不同的获取 EMF 的顺序?也许,我需要禁用 DataNucleus?

请帮忙指教。非常感谢。


错误堆栈表明 java.security.AccessControlException: access denied ("java.net.SocketPermission""localhost""resolve"):

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:126)
    at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:134)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.Util.getInstance(Util.java:386)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2411)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2153)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:792)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:126)
    at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:134)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:381)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
    at java.sql.DriverManager.getConnection(DriverManager.java:579)
    at java.sql.DriverManager.getConnection(DriverManager.java:190)
    at org.eclipse.persistence.sessions.DefaultConnector.connect(DefaultConnector.java:98)
    ... 55 more
Caused by: java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost" "resolve")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
    at java.security.AccessController.checkPermission(AccessController.java:555)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:252)
    at java.lang.SecurityManager.checkConnect(SecurityManager.java:1048)
    at java.net.InetAddress.getAllByName0(InetAddress.java:1203)
    at java.net.InetAddress.getAllByName(InetAddress.java:1127)
    at java.net.InetAddress.getAllByName(InetAddress.java:1063)
    at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:247)
    at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:294)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2332)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2369)

持久性.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  version="1.0">
  <persistence-unit name="Site" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>org.blessedgeek.site.jaxrs.dto.Node</class>
    <properties>
      <property name="javax.persistence.jdbc.user" value="site" />
      <property name="javax.persistence.jdbc.password" value="random" />
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/Site" />
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
    </properties>
  </persistence-unit>
</persistence>

maven 依赖

<properties>
  <resteasy.version>2.3.2.Final</resteasy.version>
</properties>
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.google.gwt</groupId>
    <artifactId>gwt-user</artifactId>
    <version>2.4.0</version>
  </dependency>
  <dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
  </dependency>

  <dependency>
    <groupId>com.smartgwt</groupId>
    <artifactId>smartgwt</artifactId>
    <version>3.0</version>
  </dependency>
  <dependency>
    <groupId>com.smartgwt</groupId>
    <artifactId>smartgwt-skins</artifactId>
    <version>3.0</version>
  </dependency>
  <dependency>
    <groupId>com.googlecode.mvp4g</groupId>
    <artifactId>mvp4g</artifactId>
    <version>1.4.0</version>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.18</version>
  </dependency>

  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>${resteasy.version}</version>
    <type>jar</type>
  </dependency>
  <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxb-provider</artifactId>
    <version>${resteasy.version}</version>
  </dependency>
  <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jackson-provider</artifactId>
      <version>${resteasy.version}</version>
  </dependency>
</dependencies>

appengine-web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application></application>
  <version>1</version>

  <threadsafe>true</threadsafe>

  <!-- Configure serving/caching of GWT files -->
  <static-files>
    <include path="**" />

    <include path="**.nocache.*" expiration="0s" />

    <include path="**.cache.*" expiration="365d" />
    <exclude path="**.gwt.rpc" />
  </static-files>

  <system-properties>
    <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
  </system-properties>

  <sessions-enabled>true</sessions-enabled>
  <async-session-persistence enabled="true" />

</appengine-web-app>

网络.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Blessed Geek Site</display-name>
  <!-- Auto scan REST service -->
  <context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
  </context-param>

  <!-- this need same with resteasy servlet url-pattern -->
  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/site</param-value>
  </context-param>

  <listener>
    <listener-class>
      org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
  </listener>

  <servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <description>JAX-RS Tools Generated - Do not modify</description>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/site/*</url-pattern>
  </servlet-mapping>
</web-app>

示例 DTO 类

@Entity
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement (name="node")
@XmlType(propOrder = { "id", "name", "description", "iconURL", "parentID", "active", "type"})
public class Node
implements Serializable{

  public enum Type{
    VIEW, ROOTNode, FOLDER, LEAF
  }

  @XmlAttribute
    @Id
    @GeneratedValue
    private Long id;
  @XmlAttribute
  private String name;
  @XmlAttribute
  private String description;
  @XmlAttribute
  private String iconURL;
  @XmlAttribute
  private long parentID;
  @XmlAttribute
  private boolean active;
  @XmlAttribute
    @Enumerated(EnumType.STRING)
  private Type type;

  public Node() {
    super();
  }

  public Node(String name, String description) {
    super();
    this.name = name;
    this.description = description;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public String getIconURL() {
    return iconURL;
  }

  public void setIconURL(String iconURL) {
    this.iconURL = iconURL;
  }

  public long getParentID() {
    return parentID;
  }

  public void setParentID(long parentID) {
    this.parentID = parentID;
  }

  public boolean isActive() {
    return active;
  }

  public void setActive(boolean active) {
    this.active = active;
  }

  public Type getType() {
    return type;
  }

  public void setType(Type type) {
    this.type = type;
  }

}

2012/05/16 更新:

我还在 persistence.xml 中将 jdbc 驱动程序替换为 com.google.appengine.api.rdbms.AppEngineDriver。仍然遇到相同的访问控制异常。

最佳答案

在 persistence.xml 中,尝试使用:

javax.persistence.jdbc.url = jdbc:google:rdbms://localhost/Site
javax.persistence.jdbc.driver = com.google.appengine.api.rdbms.AppEngineDriver

同时将 mysql jar(从 http://dev.mysql.com/downloads/connector/j/ 下载)放入 appengine-java-sdk-1.6.x/lib/impl

使用本地 MySQL 和 JDO 为我工作。

关于java - MySQL 访问被拒绝的 GAE CloudSQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10585140/

相关文章:

firebase - Firestore 已超过节点截止时间

google-app-engine - 谷歌应用引擎 jinja2 : ImportError: No module named _markupsafe

jpa - 错误新的缺失/不满足的依赖项 : (Cannot configure datasource)

java - 通过 JPQL UPDATE 查询获取更新的实体

java - Hibernate:嵌入式 id 字段命名问题

java - 双嵌套 Java 泛型

java - 映射到实体时出现 JPA 异常

java - 峰值内存使用不超过限制

python - 如何将任何 Google API 服务对象传递给 App Engine 中的延迟任务?

java - 在操作调用中生成 Struts 2 JSON 输出