我正在开发一个GWT Web应用程序,并尝试从我的RemoteServiceServlet实现(对于rpc)连接到mysql数据库.
服务器运行,我能够从我工作的机器连接到数据库.出于测试目的,我编写了一个只连接到数据库的小程序.这有效:
Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://192.168.0.106:3306/dbname", "dbuser", "dbpasswd");
但是在我的gwt应用程序中,相同的行失败了大约100行堆栈跟踪,这是"原因":
Caused by: java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission 192.168.0.106:3306 connect,resolve) at com.mysql.jdbc.StandardSocketFactory.unwrapExceptionToProperClassAndThrowIt(StandardSocketFactory.java:408) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:269) at com.mysql.jdbc.MysqlIO.(MysqlIO.java:294) ... 55 more
现在我的问题:为什么?
编辑:用于测试我使用chrome和gwt插件的开发模式
edit2:崩溃的代码部分:
public DataLinkImpl() { Connection tmpConnection = null; try { Class.forName("com.mysql.jdbc.Driver"); tmpConnection = DriverManager.getConnection("jdbc:mysql://192.168.0.106:3306/dbname", "dbuser", "dbpasswd"); } catch (ClassNotFoundException e) { System.err.println("jdbc driver class not found"); } catch (SQLException e) { System.err.println("could not establish database connection"); e.printStackTrace(); e.getNextException().printStackTrace(); } finally { connection = tmpConnection; } }
使用以下堆栈跟踪:
could not establish database connection com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:112) at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:120) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116) at com.mysql.jdbc.MysqlIO.(MysqlIO.java:344) at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2333) at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2370) at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2154) at com.mysql.jdbc.ConnectionImpl. (ConnectionImpl.java:792) at com.mysql.jdbc.JDBC4Connection. (JDBC4Connection.java:47) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:112) at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:120) 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:582) at java.sql.DriverManager.getConnection(DriverManager.java:185) at de.eikecochu.gwt.awidb.server.DataLinkImpl. (DataLinkImpl.java:23) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at org.mortbay.jetty.servlet.Holder.newInstance(Holder.java:153) at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:428) at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:78) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:362) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) Caused by: java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission 192.168.0.106:3306 connect,resolve) at com.mysql.jdbc.StandardSocketFactory.unwrapExceptionToProperClassAndThrowIt(StandardSocketFactory.java:408) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:269) at com.mysql.jdbc.MysqlIO. (MysqlIO.java:294) ... 55 more 01.12.2011 02:33:09 com.google.appengine.tools.development.ApiProxyLocalImpl log SCHWERWIEGEND: javax.servlet.ServletContext log: unavailable java.lang.NullPointerException at de.eikecochu.gwt.awidb.server.DataLinkImpl. (DataLinkImpl.java:29) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at org.mortbay.jetty.servlet.Holder.newInstance(Holder.java:153) at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:428) at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:78) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:362) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 01.12.2011 02:33:09 com.google.apphosting.utils.jetty.JettyLogger warn WARNUNG: /awidb/datalink java.lang.NullPointerException at de.eikecochu.gwt.awidb.server.DataLinkImpl. (DataLinkImpl.java:29) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at org.mortbay.jetty.servlet.Holder.newInstance(Holder.java:153) at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:428) at org.mortbay.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:339) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:78) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:362) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
edit3:我在/Library/Java/.../security/java.policy文件中添加了一个权限:
grant { permission java.net.SocketPermission "192.168.0.106:3306", "connect,resolve"; }
但仍然相同,我无法连接到数据库.我也尝试直接在db所在的机器上执行它,所以我在tomcat中部署了它(在那里添加了相同的权限),但仍然没有去.WTF?
edit4:为了证实这一点,我写了一个非常简单的网络应用程序:
EntryPoint类:
package de.eikecochu.gwt.gwttest.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; public class GWTTest implements EntryPoint { private TestServiceAsync testservice = GWT.create(TestService.class); @Override public void onModuleLoad() { Button b = new Button("test"); RootPanel.get("container").add(b); b.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { testservice.echo("test", new AsyncCallback() { @Override public void onFailure(Throwable caught) { RootPanel.get("container").add(new Label("error")); } @Override public void onSuccess(String result) { RootPanel.get("container").add(new Label(result)); } }); } }); } }
远程服务接口:
package de.eikecochu.gwt.gwttest.client; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("testservice") public interface TestService extends RemoteService { String echo(String s); }
远程服务异步接口:
package de.eikecochu.gwt.gwttest.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface TestServiceAsync { void echo(String s, AsyncCallbackcallback); }
RemoteServiceServlet实现:
package de.eikecochu.gwt.gwttest.server; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import de.eikecochu.gwt.gwttest.client.TestService; public class TestServiceImpl extends RemoteServiceServlet implements TestService { private static final long serialVersionUID = 1L; private final Connection connect() { String driver = "com.mysql.jdbc.Driver"; String dblink = "jdbc:mysql://192.168.0.106:3306/"; String dbname = "dbname"; String dbuser = "dbuser"; String dbpass = "dbpass"; try { Class.forName(driver).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } Connection conn = null; try { conn = DriverManager.getConnection(dblink + dbname, dbuser, dbpass); } catch (SQLException e) { System.err.println("mysql connection error: "); e.printStackTrace(); } return conn; } @Override public String echo(String s) { Connection c = connect(); return s; } }
这也行不通.不在我的机器上,而不在localhost(db所在的位置)上.再次出现相同的错误(AccessControlException bla bla).
edit5: I tried to execute my app directly on my server, which means: i installed eclipse and gwt tools on the server and executed it there locally in chrome/development mode. Still the same error. I get the feeling that either my mysql/ubuntu have wrong configs or I am doing something wrong, fundamentally. Normally, it should be quite easy to connect to a database, yes? I mean, what is a website without a database...
edit6: as baba suggested, I tried to set System.setSecurityManager(null);
in my RemoteServlet right before connecting to the database. It throws following error (abbreviated):
java.security.AccessControlException: access denied (java.lang.RuntimePermission setSecurityManager) at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374) at java.security.AccessController.checkPermission(AccessController.java:546) at java.lang.SecurityManager.checkPermission(SecurityManager.java:532) at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:252) at java.lang.System.setSecurityManager0(System.java:273) at java.lang.System.setSecurityManager(System.java:264)
so it seems I have a SecurityManager installed.
Also, I have tried to access my database with telnet. At first, my connection was refused but I changed my mysql-bind address to the ip of my server (192.168.0.106) and followed the steps here: http://ubuntu-commands.blogspot.com/2008/11/how-do-i-enable-remote-access-to-mysql.html
And when I telnet 192.168.0.106 3306
now, weird symbols appear:
eikes-macbook-air:~ eike$ telnet 192.168.0.106 3306 Trying 192.168.0.106... Connected to eike-server.speedport.ip. Escape character is '^]'. = 5.1.58-1ubuntu1(b5|529h~!dYpI\rHP:qKc ot packets out of orderConnection closed by foreign host.
It seems this is an error?
Plus, I searched for the AccessDenied error and found this link: http://code.google.com/p/gwt-examples/wiki/project_MySQLConn#Tomcat_Setup_Notes which describes exactly the error I am experiencing, although I use the Devmode for developing. Although following these steps didn't help (I edited my default /Library/.../security/java.policy file)
edit7: I installed postgresql and set up a very simple database just to test the connection. Without GWT it works fine, GWT produces the same error again. Therefore, it is not the fault of my mysql config. I played a bit with the java policy file, no reaction. GWT hates me :<
edit8: I tried both postgresql and mysql on another machine (this time win7) and executed my gwt app there locally (before & after editing the policy file), still the same error. This is unmistakably GWTs fault! It seems like the gwt devmode is not allowed to do anyting, anywhere...
Another question: the error clearly states "java.security.AccessControlException: access denied (java.net.SocketPermission localhost resolve)", so why does this still appear when I modify my java policy file to connect,resolve on the needed ports? It seems like that had absolutely no effect! I even tried grant AllPermission, no effect either.
Next, I found the "gwt-log.txt", which lists an error in the loading process:
Public resources found in... [WARN] Error processing classpath URL 'file:/C:/Program Files (x86)/eclipse/plugin/com.google.gdt.eclipse.designer.hosted.2_2_2.4.2.r37x201110201837/gwt-dev-designtime.jar' java.net.URISyntaxException: Illegal character in path at index 16: file:/C:/Program Files (x86)/eclipse/plugins/com.google.gdt.eclipse.designer.hosted.2_2_2.4.2.r37x201110201837/gwt-dev-designtime.jar at java.net.URI$Parser.fail(Unknown Source)
I don't know what that is or if it's important, but it's not my fault!
您已使用 Google App Engine 安装了Google Eclipse插件.创建一个新的GWT项目并确保取消选择Google App Engine,然后重试.或者,从eclipse类路径中删除所有与GAE相关的jar文件.
GAE是Google提供的托管环境.它的环境非常有限.它不允许您打开套接字连接或读/写文件.数据库驱动程序打开套接字连接,因此GAE会阻止它出现安全性异常.
GWT和GAE是谷歌的两个独立产品,但Eclipse插件是相同的.不幸的是,它假设您希望将两种产品用作项目的一部分.