simplicityitself / grails-gwt

New Grails GWT Plugin
Other
23 stars 18 forks source link

Serialization problems: RPC support for normal Java RPC #62

Open oniseijin opened 9 years ago

oniseijin commented 9 years ago

Not sure if this is a grails problem, a plugin problem, or a problem in my head, but for the life of me I cannot get RPC working with Java RPC and GWT in grails.

Caused by SerializationException: Type 'com.sencha.gxt.data.shared.loader.PagingLoadConfigBean' [This is seralizable though, and working in their example]

This happens with 1.0.3 (earlier) and the 2.0-SNAPSHOT that @donbeave made. This makes me wonder if it's possible (and what magic was presumably done to get it working as a Grails Service). The base project is the GXT 3.1.1 Explorer.

  1. In the generated war, I get an error that the RPC is not found: ERROR: The serialization policy file '/static/js/gwt/explorer/954B65F9DE429170F90997B93C81F349.gwt.rpc' was not found; did you forget to include it in this deployment -> it then gives a warning before the error: Failed to get the SerializationPolicy '954B65F9DE429170F90997B93C81F349' for module 'http://localhost:8181/static/js/gwt/explorer/'; a legacy, 1.3.3 compatible, serialization policy will be used. You may experience SerializationExceptions as a result. ->and then the above seralizable error comes 1.1: Going directly to that url, the rpc file is found at http://localhost:8181/static/js/gwt/explorer/954B65F9DE429170F90997B93C81F349.gwt.rpc
  2. In code server mode, the .rpc files are not generated, which may not be an issue, but the same serialization issue happens

To me, it looks like something in the resources plugin gets in the way of finding the url.

After a week, need some input to see what could be interfering. Refreshing caches does not work.

rpc

oniseijin commented 9 years ago

Figured it out: in GWT: http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java?r=5045

the file is opened with InputStream is = getServletContext().getResourceAsStream( serializationPolicyFilePath);

The path on the server would be /js/gwt/explorer/954B65F9DE429170F90997B93C81F349.gwt.rpc, for it to work seamlessly, but the path passed in from the server side has /static in front of it, so definetly conflicts with resources plugin (url is different from absolute location from a resource perspective). Would need to either not use the resources plugin, or provide some custom implementation of RemoteServicesServlet, or something else in the chain.

So, this explains why it won't work as a war file, perhaps something similar in hosted/code server mode.

  1. Change the rpc policy directly in processCall in a custom servlet, similar to GwtController, but for core Java.
  2. Adjust the doGetSerializationPolicy in RemoteServiceServlet to account for the difference in the absolute location and the url
  3. Don't use the resource for anything related to gwt... unsure if there is side effects

This would solve the war problem, but not account for the failure in dev mode...

  1. Ensure that codeServerPort in RemoteServiceServlet is set so that it tries to find the url (if you do run-app, this likely would not be set.. and run-gwt-client doesn't seem to do this. (meaning gwt.codeserver.port property when doing run-app)
oniseijin commented 9 years ago

Fix for run-app: ensure codeserver is running and set property in BuildConfig.groovy (does anyone know a better place to do this, maybe plugin specific? _Events.groovy under compile didn't work) System.setProperty("gwt.codeserver.port", "9876")

Fix for war deployment: in an extension of RemoteServiceServlet [Bit of a hack, but it works for this problem, would need something more generic, perhaps detecting some property, or the location of /static in the url) @Override protected SerializationPolicy doGetSerializationPolicy( HttpServletRequest request, String moduleBaseURL, String strongName) {

    moduleBaseURL = moduleBaseURL.replace("/static", "");
    return super.doGetSerializationPolicy(request, moduleBaseURL, strongName);
}

Any suggestions on the best way to do either of the above in the most generic way?