GAE CloudSQL 连接 MySQL 出现访问被拒绝错误

3

我有一个网页应用程序,在以下环境下运行良好:

  • 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 JPA 2.0,请不要提供有关如何使Hibernate与GAE CloudSQL配合工作的说明。我知道互联网上有一个关于如何在CloudSQL上使用Hibernate的示例,但没有JPA。

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

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

  • 我已经在mysql.db表中添加了一行附加的内容,以包括主机localhost.localdomain。

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

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

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

也许我需要在我的persistence.xml文件中添加更多行?也许我的EMF设置需要修改?或许,GAE需要不同的获取EMF顺序而不是Hibernate?也许,我需要禁用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)

persistence.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>

web.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>

示例数据传输对象类
@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。仍然遇到相同的访问控制异常。


1
根据https://dev59.com/Fl3Va4cB1Zd3GeqPD9HY,GAE限制连接,这解释了在连接到MSQL时出现的java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost" "resolve")。您需要一种方法来设置权限,以允许任何提供程序连接到您的数据库。 - Chris
1个回答

3
在 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时这个方法有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接