CloudSQL Eclipse Java Standard GAE java.lang.UnsatisfiedLinkError

时间:2018-06-05 17:30:16

标签: google-app-engine google-cloud-sql google-eclipse-plugin

我正在构建一个连接到Google CloudSQL实例的简单Java Standard Google App Engine应用程序。当我使用mvn clean appengine:runmvn clean appengine:deploy从命令行执行项目时,我可以成功连接到CloudSQL实例中的数据库。

但是,如果我run or debug项目来自Eclipse"运行为" - > App Engine或" Debug as" - > App Engine功能,执行DriverManager.getConnection(serverURL)时收到以下错误。

INFO: Dev App Server is now running 
connecting to: REDACTED
Jun 05, 2018 10:06:06 AM com.google.cloud.sql.mysql.SocketFactory connect
INFO: Connecting to Cloud SQL instance [REDACTED].
Jun 05, 2018 10:06:06 AM com.google.cloud.sql.mysql.SocketFactory connect
INFO: Using GAE Unix Sockets
java.sql.SQLException: java.lang.UnsatisfiedLinkError: The operation 
completed successfully.

at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:877)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:873)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:443)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at generic.HelloAppEngine.init(HelloAppEngine.java:55)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:643)
at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:499)
at org.eclipse.jetty.servlet.ServletHolder.ensureInstance(ServletHolder.java:791)
at org.eclipse.jetty.servlet.ServletHolder.prepare(ServletHolder.java:776)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:579)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at com.google.appengine.tools.development.jetty9.DevAppEngineWebAppContext.doScope(DevAppEngineWebAppContext.java:94)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at com.google.appengine.tools.development.jetty9.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:597)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:534)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:320)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Unknown Source)


Caused by: java.lang.UnsatisfiedLinkError: The operation completed successfully.
at jnr.ffi.provider.jffi.AsmRuntime.newUnsatisifiedLinkError(AsmRuntime.java:40)
at jnr.unixsocket.Native$LibC$jnr$ffi$0.socket(Unknown Source)
at jnr.unixsocket.Native.socket(Native.java:92)
at jnr.unixsocket.UnixSocketChannel.<init>(UnixSocketChannel.java:101)
at jnr.unixsocket.UnixSocketChannel.open(UnixSocketChannel.java:65)
at com.google.cloud.sql.mysql.SocketFactory.connect(SocketFactory.java:61)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:300)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2192)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2225)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2024)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:779)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
... 35 more

我的POM.xml是

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <packaging>war</packaging>
    <version>0.1.0-SNAPSHOT</version>

    <groupId>generic</groupId>
    <artifactId>testdb</artifactId>

    <properties>
        <appengine.api.sdk.version>1.9.63</appengine.api.sdk.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
        </properties>

        <dependencies>
            <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>google-cloud-bom</artifactId>
                <version>0.47.0-alpha</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        <!-- Compile/runtime dependencies -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency> <!-- Only used locally -->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.42</version>
        </dependency>
        <dependency>
            <groupId>com.google.cloud.sql</groupId>
            <artifactId>mysql-socket-factory</artifactId>
            <version>1.0.8</version>
        </dependency>

        <!-- Test Dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <!-- for hot reload of the web application -->
        <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.0.0</version>
                <configuration>
                    <webResources>
                        <!-- in order to interpolate version from pom into appengine-web.xml -->
                        <resource>
                            <directory>${basedir}/src/main/webapp/WEB-INF</directory>
                            <filtering>true</filtering>
                            <targetPath>WEB-INF</targetPath>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>

            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>appengine-maven-plugin</artifactId>
                <version>1.3.1</version>
            </plugin>
        </plugins>
    </build>
</project>

我的Servlet是:

package generic;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.base.Stopwatch;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.concurrent.TimeUnit; 

@SuppressWarnings("serial")
@WebServlet(
    name = "HelloAppEngine",
    urlPatterns = {"/hello"}
)
public class HelloAppEngine extends HttpServlet {

    Connection conn;

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) 
      throws IOException {

    resp.setContentType("text/plain");
    resp.setCharacterEncoding("UTF-8");

    resp.getWriter().print("Hello App Engine!\r\n");

    if(conn!=null)
        resp.getWriter().println("connected:"+conn.toString());

    }

    @Override
    public void init()
    {
      //String url = System.getProperty("cloudsql");
      String serverURL = "jdbc:mysql://google/DB?cloudSqlInstance=INSTANCE&"+               "socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=USER&password=PWD&useSSL=false";

      //System.out.println("connecting to: " + url);
      System.out.println("connecting to: " + serverURL);
      try {
        conn = DriverManager.getConnection(serverURL);

      } catch (SQLException e) {
          e.printStackTrace();
      }
    }
}

我的appengine-web.xml是:

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

  <threadsafe>true</threadsafe>
  <runtime>java8</runtime>

</appengine-web-app>

请帮我在Eclipse中运行和调试这个应用程序!!

1 个答案:

答案 0 :(得分:1)

更新:此问题已修复。升级到最新的Cloud SQL JDBC套接字库。

Cloud SQL JDBC套接字工厂库存在问题;错误地假设代码在App Engine服务器上运行:https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory/issues/77。他们正在修复(如GitHub问题中所述),不幸的是,只要您使用套接字工厂库,似乎没有立即解决方法。

mvn appengine:run工作的原因是您使用的是com.google.cloud.tools:appengine-maven-plugin插件的旧版本(1.3.1)。将它升级到1.3.2会破坏目前使用Eclipse插件(Cloud Tools for Eclipse插件)的功能。

技术细节

对于那些对根本原因的技术细节感兴趣的人,请参阅上面的GitHub问题和以下内容:https://github.com/GoogleCloudPlatform/google-cloud-eclipse/issues/3136。基本上,最新版本的插件使本地App Engine开发服务器上的GAE_RUNTIMEGAE_ENV环境变量可用,这使得JDBC套接字库错误地认为它位于生产服务器上。