EDIT: Это удалось устранить, проверив файл журнала на Google Developers Console. Ошибка заключалась не в подключении к базе данных, а в том, что я собирался с JDK 1.8 вместо 1.7. Оказалось, что даже если я сказал Eclipse, использовать JDK 1.7 для проекта, он все еще использует 1.8, потому что я имел следующую строку в моем Затмения конфигурационном файле:Невозможно подключиться к экземпляру Google Cloud SQL из Google App Engine при разработке в Eclipse
-vm
C:\Program Files\Java\jdk1.8.0_20\bin
, когда я изменил это:
-vm
C:\Program Files\Java\jdk1.7.0_71\bin
все работало отлично.
Оригинал Вопрос:
Я пытаюсь подключиться к экземпляру Google Cloud SQL из моего авторизованного приложения в Google App Engine. Я начал с указаний в https://cloud.google.com/appengine/docs/java/cloud-sql/#Java_Build_a_starter_application_and_database и немного изменил их для работы с моим экземпляром Cloud SQL (я не реализовал базу данных гостевой книги, я использовал свою собственную, которая также имеет только одну таблицу с тремя столбцами). Я создал экземпляр Cloud SQL, используя MySQL Workbench.
Когда я отладить мое приложение локально (запустить его на локальном хосте: 8888) она прекрасно работает с моим локальным экземпляром MySQL и экземпляр Google Cloud SQL. Однако, когда я пытаюсь развернуть свое приложение в Google App Engine, он просто плюет назад на 500 Server Error, и я понятия не имею, что пошло не так (я очень новичок в веб-программировании). Я искал по всему Интернету решение этой проблемы, но мне еще предстоит найти что-то, что делает трюк.
Вот мой код сервлета:
package com.rmpm;
import java.io.*;
import java.sql.*;
import javax.servlet.http.*;
import com.google.appengine.api.utils.SystemProperty;
@SuppressWarnings("serial")
public class Synaptic_rmpmServlet extends HttpServlet {
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String url = null;
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
try {
if (SystemProperty.environment.value() ==
SystemProperty.Environment.Value.Production) {
// Load the class that provides the new "jdbc:google:mysql://" prefix.
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://<my-project-id>:<my-instance-id>/test"; // Doesn't work
} else {
// Local MySQL instance to use during development.
Class.forName("com.mysql.jdbc.Driver");
url = "jdbc:mysql://173.###.##.###:3306/test"; // Connects to Google Cloud SQL instance when root password is provided
//url = "jdbc:mysql://127.0.0.1:3306/test"; // Connects to local MySQL instance
}
} catch (Exception e) {
e.printStackTrace();
return;
}
try {
Connection conn = DriverManager.getConnection(url, "root", "");
try {
String pid = req.getParameter("projID");
String own = req.getParameter("owner");
String dur = req.getParameter("duration");
if (pid == "" || own == "" || dur == "") {
out.println(
"<html><head></head><body>You are missing either a projectID, owner name, or duration! Try again! " +
"Redirecting in 3 seconds...</body></html>");
}
else {
int duration = Integer.parseInt(dur);
String statement = "INSERT INTO project VALUES(?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(statement);
stmt.setString(1, pid);
stmt.setString(2, own);
stmt.setInt(3, duration);
int success = 2;
success = stmt.executeUpdate();
if (success == 1) {
out.println(
"<html><head></head><body>Success! Redirecting in 3 seconds...</body></html>");
} else if (success == 0) {
out.println(
"<html><head></head><body>Failure! Please try again! " +
"Redirecting in 3 seconds...</body></html>");
}
}
} finally {
conn.close();
}
}
catch (SQLException e) {
e.printStackTrace();
}
resp.setHeader("Refresh", "3; url=/databaseIO.jsp");
}
}
И мой код databaseIO.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="java.sql.*" %>
<%@ page import="com.google.appengine.api.utils.SystemProperty" %>
<html>
<body>
<%
String url = null;
if (SystemProperty.environment.value() ==
SystemProperty.Environment.Value.Production) {
// Load the class that provides the new "jdbc:google:mysql://" prefix.
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://<my-project-id>:<my-instance-id>/test"; // Doesn't work
} else {
// Local MySQL instance to use during development.
Class.forName("com.mysql.jdbc.Driver");
url = "jdbc:mysql://173.###.##.###:3306/test"; // Connects to Google Cloud SQL instance when root password is provided
//url = "jdbc:mysql://127.0.0.1:3306/test"; // Connects to local MySQL instance
}
Connection conn = DriverManager.getConnection(url, "root", "");
ResultSet rs = conn.createStatement().executeQuery(
"SELECT * FROM project");
%>
<table style="border: 1px solid black">
<tbody>
<tr>
<th width="40%" style="background-color: #CCFFCC; margin: 5px">projectID</th>
<th style="background-color: #CCFFCC; margin: 5px">owner</th>
<th style="background-color: #CCFFCC; margin: 5px">duration</th>
</tr>
<%
while (rs.next()) {
String aPID = rs.getString(1);
String anOwner = rs.getString(2);
int aDur = rs.getInt(3);
%>
<tr>
<td><%= aPID %></td>
<td><%= anOwner %></td>
<td><%= aDur %></td>
</tr>
<%
}
conn.close();
%>
</tbody>
</table>
<br />
No more projects!
<p><strong>Add a project:</strong></p>
<form action="/sign" method="post">
<div>Project ID: <input type="text" name="projID"></input></div>
<br />
<div>Owner: <input type="text" name="owner"></input></div>
<br />
<div>Duration: <input type="text" name="duration"></input></div>
<br />
<div><input type="submit" value="Insert Project"></input></div>
</form>
</body>
</html>
Основываясь на том, что я прочитал в Интернете, я понимаю, что я не должен» t нужен пароль при подключении в качестве пользователя root к моему экземпляру Google Cloud SQL из моего авторизованного приложения Google App Engine. Когда я подключаюсь к экземпляру Google Cloud SQL локально в режиме отладки, я предоставляю пароль root, который я установил в Google Developers Console, и он отлично работает.
Что я сделал:
- Я уже вошел в Eclipse, с учетной записью Google, который связан с моей Google App Engine приложения.
- Я уже включил строку
<use-google-connector-j>true</use-google-connector-j>
в файле appengine-web.xml. - Я скопировал mysql-connector-java-5.1.33-bin.jar в папку проекта/WEB-INF/lib и в каталог GAE SDK в D: \ Program_Files \ Eclipse \ plugins \ com.google .appengine.eclipse.sdkbundle_1.9.13 \ appengine-java-sdk-1.9.13 \ lib \ impl (читайте похожие вопросы онлайн, чтобы это сделать).
- Я уполномочил приложение Google App Engine подключиться к моему экземпляру Google Cloud SQL.
- Я разрешил моей локальной сети подключаться к моему экземпляру Google Cloud SQL.
- Я уверен, что поля
<my-project-id>
и<my-instance-id>
верны в URL-адресе JDBC. - Я попытался использовать свой IP-адрес экземпляра Google Cloud SQL в URL-адресе JDBC вместо идентификатора проекта и идентификатора экземпляра.
Что я использую:
- Затмения SE Luna (4.4.1) с Google Plugin для Eclipse (4.4) и Google App Engine Java SDK (1.9.13). Я развертываю с Eclipse прямо в Google App Engine с помощью плагина.
- JDK 1.7
- для Windows 8.1 64-разрядный
Если вам нужна дополнительная информация просто опубликовать здесь, как я буду проверять это регулярно.
Общей причиной 500 ошибки на приложение двигателя является то, что приложение слишком долго, чтобы начать. Откуда вы знаете, что ошибка 500 связана с подключением к базе данных? Что говорит журнал? – Khalid
Огромное вам спасибо ... Я даже не знал, что журнал вышел! Наверное, я должен был предположить, что для отладки было что-то подобное, но я не думал, что нужно смотреть. Я обновил свой вопрос, какова была фактическая проблема, и мое решение. – Alex
Эй, я думаю, у меня такая же проблема, как и вы. Это сводит меня с ума. Где журнал, чтобы я мог понять, в чем проблема? Благодаря! –