1
votes

EDIT: This has been resolved by checking the log file on the Google Developers Console. The error was not in connecting to the database, but was because I was compiling with JDK 1.8 instead of 1.7. It turned out that even though I had told Eclipse to use JDK 1.7 for the project, it was still using 1.8 because I had the following line in my Eclipse configuration file:

-vm
C:\Program Files\Java\jdk1.8.0_20\bin

when I changed this to:

-vm
C:\Program Files\Java\jdk1.7.0_71\bin

everything worked perfectly.

Original Question:

I am trying to connect to a Google Cloud SQL instance from my authorized Google App Engine application. I started by following the directions at https://cloud.google.com/appengine/docs/java/cloud-sql/#Java_Build_a_starter_application_and_database and modifying them slightly to work with my Cloud SQL instance (I did not implement the guestbook database, I used my own which also has just one table with three columns). I created the Cloud SQL instance using MySQL Workbench.

When I debug my application locally (run it at localhost:8888) it works perfectly with my local MySQL instance AND the Google Cloud SQL instance. However, when I try to deploy my application to Google App Engine it just spits back a 500 Server Error and I have no clue what went wrong (I am very new to web programming). I have been searching all over the web for a solution to this issue but I've yet to find something that does the trick.

Here is my code for the servlet:

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");
      }
}

And my code for the 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>

Based on what I've read online, I gather that I shouldn't need a password when connecting as the root user to my Google Cloud SQL instance from my authorized Google App Engine application. When I connect to the Google Cloud SQL instance locally in debug mode, I do provide the root password which I set in the Google Developers Console and it works perfectly.

What I've done:

  • I am already logged into Eclipse with the Google account that is linked to my Google App Engine application.
  • I have already included the <use-google-connector-j>true</use-google-connector-j> line in the appengine-web.xml file.
  • I have copied the mysql-connector-java-5.1.33-bin.jar to the project's war/WEB-INF/lib folder and to the GAE SDK directory at D:\Program_Files\Eclipse\plugins\com.google.appengine.eclipse.sdkbundle_1.9.13\appengine-java-sdk-1.9.13\lib\impl (reading similar questions online said to do this).
  • I have authorized my Google App Engine application to connect to my Google Cloud SQL instance.
  • I have authorized my local network to connect to my Google Cloud SQL instance.
  • I am 100% sure the <my-project-id> and <my-instance-id> fields are correct in the JDBC url.
  • I've tried using my Google Cloud SQL instance's IP address in the JDBC url instead of the project-id and instance-id.

What I'm using:

  • Eclipse SE Luna (4.4.1) with Google Plugin for Eclipse (4.4) and Google App Engine Java SDK (1.9.13). I deploy from Eclipse straight to Google App Engine with the plugin.
  • JDK 1.7
  • Windows 8.1 64-bit

If you need any additional information just post here as I'll be checking this regularly.

1
A common reason for the 500 error on the app engine is that the app is taking too long to start. How do you know that the 500 error is related to the database connection? What does the log say?Khalid
Thank you so much... I did not even know that log exited! I guess I should have assumed that there was something like that for debugging purposes but I didn't think to look. I've updated my question with what the actual problem was and my solution.Alex
Hey i think i have the same problem as you. It's driving me nuts. Where is the log so i can see what the problem is? Thanks!Jonathan Laliberte

1 Answers

0
votes

Local mysql will be working on your code , i was having the same problem but as i changed .GoogleDriver to .Driver it started working