CloudSQL Eclipse Java Standard GAE java.lang.UnsatisfiedLinkError

Aditya спросил: 12 мая 2018 в 03:50 в: google-app-engine

Я создаю простое приложение Java Standard Google App Engine, которое подключается к экземпляру Google CloudSQL. Когда я выполняю проект из командной строки с помощью mvn clean appengine:run или mvn clean appengine:deploy, я мог бы успешно подключиться к базе данных в экземпляре CloudSQL.

Однако, если я запустил или отладить проект из 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>

Мой сервлет:

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 ответ

Chanseok Oh ответил: 15 мая 2018 в 02:26

Есть проблема в фабричной библиотеке сокетов облачного SQL JDBC; неверно предположить, что код запущен на серверах App Engine: https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory/issues/77. Они работают над исправлением (как указано в выпуске GitHub), и, к сожалению, не существует немедленного решения, если вы используете фабричную библиотеку сокетов.

Причина, по которой mvn appengine:run работал то, что вы использовали старую версию (1.3.1) плагина com.google.cloud.tools:appengine-maven-plugin. Обновление до 1.3.2 приведет к поломке вещей, как в настоящее время с плагином Eclipse (плагин Cloud Tools для Eclipse).

Технические данные

Для тех, кто интересуется техническим сведения об основной причине, см. выше проблему GitHub и следующее: https://github.com/GoogleCloudPlatform/google-cloud-eclipse/issues/3136. В основном, последние версии плагинов позволяют использовать переменные среды GAE_RUNTIME и GAE_ENV на локальном сервере разработки App Engine, что заставило библиотеку сокетов JDBC неправильно предположить, что она находится на рабочем сервере .