User Tools
archive:simplicityitself.ie:gwt
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| archive:simplicityitself.ie:gwt [2018/02/22 14:08] – wlee | archive:simplicityitself.ie:gwt [2021/06/25 10:09] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | http:// | ||
| + | Luckily we have it on webarchive so this is copied from | ||
| + | https:// | ||
| + | |||
| + | |||
| + | ====== 1 Introduction ====== | ||
| + | The [[http:// | ||
| + | The plugin makes it easy to incorporate GWT code into your GSP pages, and it also simplifies the handling of RPC requests on the server. If you have not used GWT before, please read the documentation on the GWT website. | ||
| + | |||
| + | Jan Ehrhardt has kindly created a simple [[http:// | ||
| + | |||
| + | You can also join in the discussions about the plugin and ask questions on the [[http:// | ||
| + | |||
| + | The plugin host page is at http:// | ||
| + | |||
| + | |||
| + | ====== 2 Getting Started ====== | ||
| + | **How to use it** | ||
| + | When starting with GWT, the first thing you need to do is create a module. This packages a bunch of client-side code into a single unit. | ||
| + | |||
| + | **Creating a module** | ||
| + | < | ||
| + | | ||
| + | </ | ||
| + | The above command will generate a module file and a corresponding client class under your project' | ||
| + | |||
| + | < | ||
| + | grails create-gwt-module org.example.MyApp | ||
| + | </ | ||
| + | will create the files | ||
| + | - src/ | ||
| + | - src/ | ||
| + | |||
| + | **Creating a host page** | ||
| + | Once you have a module, you need to create an HTML page that will host the user interface elements defined by it. Again, this is as simple as running another Grails command: | ||
| + | |||
| + | < | ||
| + | grails create-gwt-page < | ||
| + | </ | ||
| + | The first argument specifies the page to create, and the second specifies which GWT module the page should host. The page is given as a relative path to a file, which can for example have an " | ||
| + | |||
| + | < | ||
| + | // This will create the view file: grails-app/ | ||
| + | grails create-gwt-page main/ | ||
| + | // This will create the file: web-app/ | ||
| + | grails create-gwt-page dir/ | ||
| + | // This will create the file: web-app/ | ||
| + | grails create-gwt-page index.gsp org.example.AnotherModule | ||
| + | </ | ||
| + | |||
| + | With the first method, the script will offer to create the relevant controller if it does not already exist. | ||
| + | |||
| + | Trying it out | ||
| + | GWT has something called hosted mode that allows you to test and debug your web interface from a custom browser. This is also available from the plugin. Just run this command: | ||
| + | |||
| + | < | ||
| + | grails run-gwt-client | ||
| + | </ | ||
| + | This will launch GWT Developer Mode runtime. Once this has launched, follow the link it gives you in your normal browser (with the GWT Plugin install) (it would be a good idea to run grails run-app in one console, and this in another). | ||
| + | |||
| + | To actually hit a breakpoint, you'll need to pass in -debug=8000 (default debugPort is 5006). Then launch a process to attach to the debug port. I use STS(eclipse)' | ||
| + | |||
| + | < | ||
| + | grails run-gwt-client -debug | ||
| + | </ | ||
| + | will cause the following output: | ||
| + | |||
| + | < | ||
| + | Starting the GWT hosted mode client. … | ||
| + | | ||
| + | </ | ||
| + | Then, create a launch config in STS: | ||
| + | |||
| + | < | ||
| + | (Run-> | ||
| + | Under Connect tab-> | ||
| + | Project: | ||
| + | Connection Type: Standard (Socket Attach) | ||
| + | Connection Properties: | ||
| + | Host: localhost (or remote host) | ||
| + | Port: 5006 (default, but whatever GWT Dev Mode is listening for) | ||
| + | Name: < | ||
| + | Click Apply (or Debug if you're ready) | ||
| + | </ | ||
| + | |||
| + | ====== 3 Server RPC ====== | ||
| + | |||
| + | **Introduction** | ||
| + | Almost any non-trivial GWT application will require the use of its RPC support at some stage. GWT normally requires you to write a servlet for each service interface that you define, but the plugin simplifies this step by allowing you to implement the server-side RPC with normal Grails services. Any service can be configured for GWT by adding an expose property, as is done with the Remoting plugin and others: | ||
| + | <code java> | ||
| + | class MyService { | ||
| + | static expose = [ ' | ||
| + | List listUsers() { | ||
| + | … | ||
| + | } | ||
| + | … | ||
| + | } | ||
| + | </ | ||
| + | The format of the GWT expose entry is basically: gwt:< | ||
| + | |||
| + | You could create the RPC interfaces yourself, but the plugin provides a nice little command to give you a head start: | ||
| + | |||
| + | < | ||
| + | grails generate-gwt-rpc [--force] [--non-interactive] | ||
| + | </ | ||
| + | This will create the required normal and asynchronous interfaces under the src/java directory. The optional arguments shown only take effect if the interface files already exist. By default, the plugin asks you whether you want to overwrite such a file | ||
| + | |||
| + | For example, say you have a Grails service example.MyService exposed via GWT. The plugin will generate these files for it: | ||
| + | |||
| + | - src/ | ||
| + | - src/ | ||
| + | Once you have generated the files, it is generally a good idea to maintain them yourself rather than regenerating them. You then have much greater control and usually much cleaner code. | ||
| + | |||
| + | When accessing the service from your client GWT code, use the URL described in this example: | ||
| + | |||
| + | <code java> | ||
| + | MyServiceAsync myService = (MyServiceAsync) GWT.create(MyService.class); | ||
| + | ServiceDefTarget endpoint = (ServiceDefTarget) myService; | ||
| + | // Note the URL where the RPC service is located! | ||
| + | String moduleRelativeURL = GWT.getModuleBaseURL() + " | ||
| + | endpoint.setServiceEntryPoint(moduleRelativeURL); | ||
| + | |||
| + | // Call a method on the service! | ||
| + | List users = myService.listUsers() | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | **Collection and map types** | ||
| + | GWT supports both collections (list, sets, etc.) and maps as method arguments and return types. However, it does not support generics to determine what types are collection or map holds; instead, the user must add a custom javadoc annotation to the RPC interface definition, ' | ||
| + | |||
| + | <code java> | ||
| + | import org.codehaus.groovy.grails.plugins.gwt.annotation.CollectionTypeArg | ||
| + | import org.codehaus.groovy.grails.plugins.gwt.annotation.MapTypeArg | ||
| + | class MyService { | ||
| + | static expose = [ ' | ||
| + | // The return list contains objects of type java.lang.String. | ||
| + | @CollectionTypeArg(String) | ||
| + | List listUsers() { | ||
| + | … | ||
| + | } | ||
| + | |||
| + | // The ' | ||
| + | // and values are java.lang.Strings. | ||
| + | void processMap(@MapTypeArg(key=Integer, | ||
| + | … | ||
| + | } | ||
| + | … | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Note At the time of writing, the annotations will not work with method arguments. Hopefully this will be rectified for the Grails 1.0 release. | ||
| + | |||
| + | **Including inherited modules** | ||
| + | Create a sub-directory called " | ||
| + | **Note for GWT 2+** | ||
| + | If you are using gwt 2+, you can put the following to the service interface MyService.java: | ||
| + | |||
| + | <code java> | ||
| + | import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; | ||
| + | @RemoteServiceRelativePath(" | ||
| + | </ | ||
| + | Then you can change these lines: | ||
| + | |||
| + | <code java> | ||
| + | MyServiceAsync myService = (MyServiceAsync) GWT.create(MyService.class); | ||
| + | ServiceDefTarget endpoint = (ServiceDefTarget) myService; | ||
| + | // Note the URL where the RPC service is located! | ||
| + | String moduleRelativeURL = GWT.getModuleBaseURL() + " | ||
| + | endpoint.setServiceEntryPoint(moduleRelativeURL); | ||
| + | </ | ||
| + | |||
| + | into: | ||
| + | |||
| + | <code java> | ||
| + | MyServiceAsync myService = GWT.create(MyService.class); | ||
| + | </ | ||
| + | |||
| + | ====== 4 Compilation ====== | ||
| + | The plugin will automatically compile your GWT modules the first time that you perform a normal Grails compile, for example via grails compile or grails run-app . Once a module has been compiled, however, it will not be compiled again in development mode. This is fine if you are using GWT's hosted mode to test your application, | ||
| + | < | ||
| + | grails compile-gwt-modules | ||
| + | </ | ||
| + | Creating a WAR | ||
| + | This is as simple as running the normal Grails command: | ||
| + | |||
| + | < | ||
| + | grails war | ||
| + | </ | ||
| + | The plugin will ensure that the GWT modules are re-compiled before everything is packaged up in the WAR file. Once that's done, you can deploy your web application to any servlet container as normal. | ||
| + | |||
| + | This is as simple as running the normal Grails command: | ||
| + | |||
| + | grails war The plugin will ensure that the GWT modules are re-compiled before everything is packaged up in the WAR file. Once that's done, you can deploy your web application to any servlet container as normal. | ||
| + | |||
| + | ====== 5 Configuration ====== | ||
| + | |||
| + | Dependency Management | ||
| + | GWT and Gin Versions | ||
| + | The GWT module uses the Ivy dependency management of Grails to download GWT/ Gin and other dependencies specifically for use by GWT. It will use any repositories that you set up in the main BuildConfig.groovy It does not use the dependencies block from BuildConfig, | ||
| + | |||
| + | The following options control dependency management | ||
| + | |||
| + | * gwt.version - Set a version number (eg " | ||
| + | * gwt.home (prefer to set a version have have it downloaded) - use the gwt version installed at the given location | ||
| + | * gwt.gin.version - download gin and any necessary libraries | ||
| + | |||
| + | **example** | ||
| + | |||
| + | < | ||
| + | gwt { | ||
| + | version=" | ||
| + | gin.version=" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | **GWT Modules** | ||
| + | * gwt.dependencies - a List of dependencies to import as GWT module dependencies (they will be given to the GWT Developer mode and compiler). Uses the same format as in BuildConfig.groovy | ||
| + | < | ||
| + | gwt.dependencies=[' | ||
| + | </ | ||
| + | |||
| + | **Import Plugins int GWT Scope** | ||
| + | * gwt.plugins - A list of plugins (that are already installed into your project) that are to be imported as GWT sources. Both their src/java and src/gwt (if it exists) will be include | ||
| + | < | ||
| + | gwt.plugins = [' | ||
| + | </ | ||
| + | |||
| + | **Other Configuration** | ||
| + | * gwt.local.workers - Fix the number of workers at the given level. (See Compilation for more information on this) | ||
| + | * gwt.run.args - A closure that can contain gant style jvmargs (or any other arg) for the java invocation of the compiler/ dev mode | ||
| + | * gwt.parallel - can force the full parallel compiler mode to be on/ off | ||
| + | * gwt.javac.cmd - The command to use to compile .java source files (default: javac) | ||
| + | * gwt.java.cmd - The Java interpreter command (default: java) | ||
| + | * gwt.output.style - The output style of the compiled Javascript produced by GWT - one of OBF, (default) to create compressed obfuscated output; PRETTY, to create human- | ||
| + | * gwt.compile.disable - Set to true to disable compilation | ||
| + | * gwt.output.path - Directory where the compiled output files are written (default: < | ||
| + | * gwt.hosted.output.path - Directory where the compiled output files are written in hosted mode (default: tomcat/ | ||
| + | … other options … | ||