Skip to Content »

GWT XDoclet

  • September 9th, 2006
  • 12:56 am

Having used Google Web Toolkit to build an application, I found out that I had to write a good portion of code, which might as well be generated automatically. I then decided to mess around with XDoclet a little to see if it was possible to make a new module. It was, and now you can use it too.

Download

xdoclet-gwt-module-0.5.jar
xdoclet-gwt-module-0.4.jar
xdoclet-gwt-module-0.3.jar
xdoclet-gwt-module-0.2.jar
xdoclet-gwt-module-0.1.jar

Changelog

0.5: Added support for @gwt.typeArgs in service methods.

0.4: Added support for setting ServiceFactory prefix (set prefix attribute in servicefactory tag in build.xml), @gwt.style and @gwt.script in EntryPoint classes. See this post for more information.

0.3: Added support for file upload, added @gwt.inherits tag instead of inherits parameter in @gwt.module. This means that it's possible to inherit from multiple modules.

Documentation

Basically, it can generate service interfaces, async services interface, module definitions (.xml.gwt), and a basic web.xml file. Finally, it can create a service factory for creating new Async-objects.

Service interfaces
When creating a remote service, just annotate the class like this:

CODE:
  1. package dk.contix.gwt.service;
  2.  
  3. /**
  4. * @gwt.interface service="dk.contix.gwt.shared.RemoteService" path="/remoteService"
  5. */
  6. public class RemoteServiceImpl implements RemoteService {
  7.  
  8.   /**
  9.    * @gwt.serviceMethod
  10.    */
  11.   public String getStuff(String what) {
  12.      // code here
  13.   }
  14. }

This will create the interface dk.contix.gwt.shared.RemoteService containing all methods which are annotated with @gwt.serviceMethod. It will also generate the async interface in dk.contix.gwt.shared.RemoteServiceAsync

Modules
To generate module definitions (.gwt.xml files), annotate the EntryPoint classes, like this:

CODE:
  1. package dk.contix.gwt.client;
  2.  
  3. /**
  4. * @gwt.module package="dk.contix.gwt" include="client,shared"
  5. */
  6. public class Client implements EntryPint {
  7.   // code here
  8. }

This will generate a file in dk/contix/gwt calles Client.gwt.xml. The file will contain the entry-point declaration, all remote servlets, and additional source paths (those specified in the include parameter).

ServiceFactory
If a service factory is generated, a class with static methods for creating instances of the Async interfaces will be created. The factory class will automatically detect url prefixes (if the application is deployed in another context than ROOT).

Generating the files
Create a build.xml file for Ant, if you don't already have one. Include the following target:

CODE:
  1. <path id="classpath">
  2.   <pathelement location="src"/>
  3.   <pathelement location="${build.dir}/classes"/>
  4.         <fileset dir="lib">
  5.             <include name="**/*.jar"/>
  6.         </fileset>
  7. </path>
  8.  
  9. <target name="generate">
  10.   <taskdef resource="xdoclet/modules/gwt/doclet.xml" classpathref="classpath"/>
  11.  
  12.   <gwtdoclet destdir="src">
  13.     <fileset dir="src">
  14.       <include name="**/*.java"/>
  15.     </fileset>
  16.    
  17.     <interface/>
  18.     <async/>
  19.     <module/>
  20.     <webxml output="web.xml"/>
  21.     <servicefactory class="dk.contix.gwt.client.ServiceFactory"/>
  22.   </gwtdoclet>
  23. </target>

Finally, place xdoclet-gwt-module-0.2.jar in lib/ so that it becomes a part of the classpath. xdoclet-*.jar and xjavadoc-*.jar is also required. They can be downloaded from xdoclet.sourceforge.net.

Bootstrapping
When a new remote service is created, there's no interface to implement. I work around this simply by annotating the service implementation, generating the code, and then adding the implements declaration.

Inheritance
If a module inherits another, this can be specified too, like this:

CODE:
  1. /**
  2. * @gwt.inherits name="dk.contix.gwt.BaseModule"
  3. * @gwt.inherits name="com.google.gwt.user.User"
  4. */
  5. public class Module implements EntryPoint {
  6.  ...
  7. }

File Uploads
The XDoclet module supports code generation for file upload support. The generated code includes a factory class for FormPanels, GWT module xml configuration and web.xml configuration. To use, add one or more @gwt.upload annotations to client classes which need upload capabilities:

CODE:
  1. package dk.contix.gwt.client;
  2.  
  3. /**
  4. * @gwt.upload path="/upload" servlet="dk.contix.gwt.service.FileUpload"
  5. * @gwt.upload path="/jpegUpload" servlet="dk.contix.gwt.service.FileUpload"
  6. */
  7. public class UploadPanel extends Composite {
  8.   public UploadPanel() {
  9.     VerticalPanel p = new VerticalPanel();
  10.     final FormPanel fp1 = UploadFactory.createUpload();
  11.     fp1.setWidget(p);
  12.     fp1.addFormHandler(...);
  13.  
  14.     final FormPanel fp2 = UploadFactory.createJpegUpload();
  15.     fp2.setWidget(p);
  16.     ...
  17.   }
  18. }

To generate the factory, a line needs to be added to the ant build target in the gwtdoclet tag:

CODE:
  1. <gwtdoclet destdir="target/gensrc">
  2.   <fileset dir="src" include="**/*.java"/>
  3.   <interface />
  4.   <async />
  5.   <module />
  6.   <servicefactory class="${serviceFactory}"/>
  7.   <uploadfactory class="${uploadFactory}"/>
  8.   <webxml output="web.xml"/>
  9. </gwtdoclet>

The upload servlet isn't generated, so you need to implement it yourself. Search for implementations in the GWT group.

typeArgs
Add @gwt.typeArgs to service methods to tell the GWT compiler which types are contained in a collection:

CODE:
  1. /**
  2. * @gwt.serviceMethod
  3. * @gwt.typeArgs dk.contix.Test
  4. */
  5. public List getObjects() {
  6.   return new ArrayList();
  7. }

Don't include <> in the annotation as you would do when using GWT directly.

16 People had this to say...

[...] GWT XDoclet [...]

Gravatar
  • Marcin Konopka
  • December 3rd, 2006
  • 10:29 pm

Download links are broken. They point to files xdoclet-gwt-module.0.x.jar whereas should point
to xdoclet-gwt-module-0.x.jar (a minus sign instead of dot). So these are, correct:


Gravatar
  • recht
  • December 4th, 2006
  • 12:14 am

Good catch, that should be fixed now, thanks.

Gravatar

Hi,

I’m new to GWT development, but I’m using your tool from the very first day. I just have a doubt with your statically initialized prefix in servicefactory.xdt: it doesn’t work for me when I deploy my app on an external Tomcat. I removed it and simply used endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + ": it works fine in all cases.

I'm using GWT 1.3 RC 1.

Gravatar
  • Hendrik Seffler
  • February 16th, 2007
  • 2:53 pm

I am seeing the same Problem with the ServiceFactory Luciano is having and solved it the same way.

Seems something is wrong here.

Gravatar
  • Jam
  • February 27th, 2007
  • 10:56 am

Hello world, Thank you for this interesting module! I think, there is a bug in the version 0.3 of the gwtdoclet module. The bug is in the template “module.xdt” (line4) : -> has to be replaced by : its”>

I have just a feature request : the possibility to generate 1 factory by service…

Gravatar
  • Jam
  • February 27th, 2007
  • 10:58 am

Hooo my previous post has got some problems…

line 4 : replace “gwt.inherts” by -> “gwt.inherits”

Gravatar
  • Thomas Recloux
  • February 27th, 2007
  • 7:34 pm

Hi,

Thanks for this great Job.

I had a problem with the ServiceFactory’s prefix compute.

In hosted mode, everything is Ok, but in server mode, it computes an URL of this form :
http://server/modulepath/../servicePath

When I use the path provided by “GWT.getModuleBaseURL()”, everything is OK in hosted and server mode.

Thanks, Thomas

Gravatar
  • Jam
  • March 1st, 2007
  • 1:06 pm

Hi,

I’ve got a new request…

with the version 0.3, it’s impossible to generate in the module .gwt.xml information related to the stylesheet

You can add this code in the module.xdt in the jar :

“/>

So, if youd had :
@gwt.style src=”YourCss.css” in your java code

It generate :
in your .gwt.xml

Gravatar
  • Jam
  • March 1st, 2007
  • 1:10 pm

arffff the code don’t appear in my previous post.

So, if you want to include the possibility to generate information related to the stylesheet, you an modify the module.xdt. copy/paste the portion of code concerning the inerits tag and adapt them to generate the declaration of the stylsheet in the module…

Gravatar
  • Jam
  • March 6th, 2007
  • 6:13 pm

hi,

I’ve got a new…new… request :-)

It’s about the generation of the module.gwt.xml again. can you add the possibility to generate information like extend-porperty (for i18n)

you can see an exemple of what generate here :
http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.Internationalization.SpecifyingLocale.html

the caracteristics of the tag gwt.extend-property:
-name
-value

I made change in module.xdt. It works perfect…

Jérémy

Gravatar
  • Jam
  • March 7th, 2007
  • 3:08 pm

Hi,
It’s me again…

I’ve got a problem with the generation of the factory and the system of the prefix (in 0.4 version). I try it.

Can you add this rules :
is the prefix is not define, default base url is Gwt.getModuleBaseUrl();
if the prefix is define, use the prefix to the base url.

the same application in hosted mode and in a war deploy in an application server doesn’t use the same base url. If you want to have the possibility to use the same application in this twice status, use GWT.getModuleBaseUrl() can be a solution…

I have implement this tule in the servicefactory.xdt and it works.

thanks

Jérémy

Gravatar
  • Francesco
  • November 28th, 2007
  • 5:13 pm

Great job!
But still we need to “edit” the outputs. In our case, the generated interface implementing RemoteService produced by has to be tagged with @gwt.typeArgs
Wouldn’t be possible to copy these tags from the **Impl class?

Gravatar
  • recht
  • December 4th, 2007
  • 11:15 pm

I’ve created a new version of the module which supports typeArgs. See http://braindump.dk/tech/2007/12/04/gwt-xdoclet-with-typeargs/

Gravatar
  • Francesco
  • December 11th, 2007
  • 1:04 pm

Thank you for your prompt reply – and work :-)

There is still one problem.
The template adds angle brackets (’less than’ < and ‘more than’ >) to the full class names specified.
This way it’s not possible to specify typeArgs for inputs, see:

http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.RemoteProcedureCalls.html#SerializableTypes

A solution (which I did now) could be to remove brackets from the template (by the way it is does not seem possible to change it for ant tasks) and leave them in the source code.
But also consider that typeArgs clauses can be more than one:

/**
* @gwt.serviceMethod
*
* @gwt.typeArgs
* @gwt.typeArgs apples
* @gwt.typeArgs lemons
*/
public List doSomething(List apples, List lemons) {
createCakes(apples, lemons);
}

There I think you need to iterate through the list of typeArgs but don’t know how to do it with XDT.
Thank you for your time.

[...] GWT XDoclet [...]

Want your say?

* Required fields. Your e-mail address will not be published on this site

You can use the following XHTML tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>