I have a web application that is working fine under the following environment
- 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 at localhost (Ubuntu 12.04)
- VMware 2.6 tomcat server
The application is working successfully using JAX-RS, JAXB, Jackson JSON provider, Hibernate JPA annotations all mixed together into the same DTO.
I am trying to port it to GAE CloudSQL. I am encountering MySQL access errors. I had to change the ORM from Hibernate to EclipseLink 2.3.2.
Reminder:
-
I respectfully request answerers not to hypothesize on possibility of mistakes in my code rather than solving the question at hand – how to port my Hibernate-based JPA to EclipseLink. Unless you believe that my set-up or code suitable for Hibernate requires changes to work with GAE CloudSQL. Reason being, the application is working fine under Hibernate.
-
Please do not provide instruction on how to make Hibernate work with GAE CloudSQL unless it involves Hibernate JPA 2.0. I realise there is an example on the internet on how to use Hibernate with CloudSQL but without JPA.
-
It would be extremely helpful if you have information on how to make DataNucleus JPA 2.0 work with GAE CloudSQL. I could not make it work, which is the reason why I am using EclipseLink.
-
Also, the MySQL datasource user and password is able to access the database either thro Eclipse datasource explorer or SQL Explorer or SQL Squirrel Client. So, no problem with the user/password. Unless you believe I need to make modifications to MqSQL user or host setup.
-
I have already included an additional line in mysql.db table to include host localhost.localdomain.
-
I have already modified my launch/debug config to
-Drdbms.url=jdbc:mysql://localhost:3306/Site?user=site&password=random&useInformationSchema=true&useUnicode=true&characterEncoding=UTF8&useServerPrepStmts=true, as instructed by “Using a Local MySQL Instance During Development” in http://developers.google.com/cloud-sql/docs/developers_guide_java. -
Your suggestion for resolution must involve JPA 2.0 not 1.0.
-
I am not accessing my CloudSQL account but localhost MySQL database running on Ubuntu 12.04. I have not tried accessing my CloudSQL database using this application (yet).
May be, I need more lines in my persistence.xml? May be my EMF setup needs to be modified? May be, GAE requires a different sequence of obtaining EMF than Hibernate? Perhaps, I need to disable DataNucleus?
Please help and advise. Thank you very much.
The error stack indicates 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 dependencies
<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>
Example DTO class
@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;
}
}
Update 2012/05/16:
I have also replaced the jdbc driver to com.google.appengine.api.rdbms.AppEngineDriver in persistence.xml. Still encountering the same access control exception.
In persistence.xml, try with :
And also put mysql jar (downloaded from http://dev.mysql.com/downloads/connector/j/) into appengine-java-sdk-1.6.x/lib/impl
Worked for me using local MySQL and JDO.