Last modified by freeleons on 2010/01/17 21:32

Show last authors
1 1 Running and Debugging GWT code in hosted mode
2
3 The purpose is to create a clean (as much as possible) GWT module and then integrate it into an existing web application. The existing web application can serve as a demo for the GWT module. Testing and debugging must be done using GWT's hosted browser. Throughout this tutorial the Wysiwyg project will be used as an example.
4
5 1 *Part 1*: The GWT module
6
7 *Step 0*: follow Claus's [Up and running with GWT and Maven 2>http://techeyes.blogspot.com/2007/06/up-and-running-with-gwt-and-maven-2.html] tutorial if you don't have already a module.
8
9 *Step 1*: {attach:src/main/resources/com/xpn/xwiki/wysiwyg/Wysiwyg.gwt.xml|file=Wysiwyg.gwt.xml}
10
11 Make sure the module descriptor contains at least the entry point and a servlet mapping.
12
13 {code:xml}
14 <module>
15 ...
16 <servlet path="/WysiwygService" class="com.xpn.xwiki.wysiwyg.server.WysiwygServiceImpl" />
17 <entry-point class="com.xpn.xwiki.wysiwyg.client.Wysiwyg" />
18 ...
19 </module>
20 {code}
21
22 *Step 2*: {attach:src/main/resources/com/xpn/xwiki/wysiwyg/public/Wysiwyg.html|file=Wysiwyg.html}
23
24 Make sure you include the right JavaScript file in the module's HTML file.
25
26 {code:xml}
27 <body>
28 <script language="javascript" src="com.xpn.xwiki.wysiwyg.Wysiwyg.nocache.js"></script>
29 <iframe src="javascript:''" id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
30 ...
31 </body>
32 {code}
33
34 *Step 3*: {attach:src/main/webapp/WEB-INF/web.xml|file=web.xml}
35
36 Copy the deployment descriptor of your web application and add a servlet mapping matching the one you have in the module descriptor discussed above. This is definitely not the best solution. Instead, the deployment descriptor could be retrieved using the [maven-remote-resources-plugin>http://maven.apache.org/plugins/maven-remote-resources-plugin/] and be modified in the pom file, provided it is available as a remote resource. Ideally, this deployment descriptor should contain only the servlet mapping for the GWT services, but unfortunately I couldn't find a maven plugin to merge this descriptor with the one from my web application, during the integration stage.
37
38 {code:xml}
39 <web-app>
40 ...
41 <servlet>
42 <servlet-name>WysiwygService</servlet-name>
43 <servlet-class>com.xpn.xwiki.wysiwyg.server.WysiwygServiceImpl</servlet-class>
44 </servlet>
45 ...
46 <servlet-mapping>
47 <servlet-name>WysiwygService</servlet-name>
48 <url-pattern>/WysiwygService</url-pattern>
49 </servlet-mapping>
50 ...
51 </web-app>
52 {code}
53
54 *Step 4*: {attach:pom.xml|file=pomgwt.xml}
55
56 In your pom file you should at least add the GWT specific dependencies and configure the [maven-googlewebtoolkit2-plugin>http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/index.html] and [maven-war-plugin>http://maven.apache.org/plugins/maven-war-plugin/]. In the case of maven-googlewebtoolkit2-plugin make sure you add the mergewebxml goal, which adds to the deployment descriptor discussed above the servlet mappings needed in hosted mode. The maven-war-plugin should include in the final war the deployment descriptor, updated by the mergewebxml goal, and the java sources from the client package. You'll not be able to run in hosted mode without the client sources!
57
58 {code:xml}
59 <project>
60 ...
61 <packaging>war</packaging>
62 ...
63 <properties>
64 <gwtVersion>1.4.62</gwtVersion>
65 <!-- update gwtHome or use the setup profile -->
66 <gwtHome>/home/marius/apps/${gwtArtifactId}-${gwtVersion}</gwtHome>
67 </properties>
68 ...
69 <dependencies>
70 <dependency>
71 <groupId>com.google.gwt</groupId>
72 <artifactId>gwt-servlet</artifactId>
73 <version>${gwtVersion}</version>
74 </dependency>
75 <dependency>
76 <groupId>com.google.gwt</groupId>
77 <artifactId>gwt-user</artifactId>
78 <version>${gwtVersion}</version>
79 <scope>provided</scope>
80 </dependency>
81 <dependency>
82 <groupId>com.google.gwt</groupId>
83 <artifactId>gwt-dev</artifactId>
84 <version>${gwtVersion}</version>
85 <classifier>${os}</classifier>
86 <scope>provided</scope>
87 </dependency>
88 ...
89 </dependencies>
90 <build>
91 <plugins>
92 ...
93 <plugin>
94 <groupId>com.totsp.gwt</groupId>
95 <artifactId>maven-googlewebtoolkit2-plugin</artifactId>
96 <version>1.5.3-SNAPSHOT</version>
97 <configuration>
98 <runTarget>com.xpn.xwiki.wysiwyg.Wysiwyg/Wysiwyg.html</runTarget>
99 <gwtHome>${gwtHome}</gwtHome>
100 <compileTarget>
101 <value>com.xpn.xwiki.wysiwyg.Wysiwyg</value>
102 </compileTarget>
103 </configuration>
104 <executions>
105 <execution>
106 <goals>
107 <goal>mergewebxml</goal><!-- needed by GWT hosted browser -->
108 <goal>compile</goal>
109 </goals>
110 </execution>
111 </executions>
112 </plugin>
113 <plugin>
114 <groupId>org.apache.maven.plugins</groupId>
115 <artifactId>maven-war-plugin</artifactId>
116 <configuration>
117 <webResources>
118 <resource>
119 <directory>target</directory>
120 <targetPath>WEB-INF</targetPath>
121 <includes>
122 <!-- generated by mergewebxml goal -->
123 <include>web.xml</include>
124 </includes>
125 </resource>
126 <resource>
127 <!-- needed by GWT hosted browser -->
128 <directory>src/main/java</directory>
129 <targetPath>WEB-INF/sources</targetPath>
130 <includes>
131 <!-- we need only client java sources -->
132 <include>com/xpn/xwiki/wysiwyg/client/**/*</include>
133 </includes>
134 </resource>
135 </webResources>
136 </configuration>
137 </plugin>
138 ...
139 </plugins>
140 </build>
141 <profiles>
142 <profile>
143 <id>linux</id>
144 <activation>
145 <os>
146 <name>linux</name>
147 </os>
148 </activation>
149 <properties>
150 <gwtArtifactId>gwt-linux</gwtArtifactId>
151 <os>linux</os>
152 </properties>
153 </profile>
154 ...
155 </profiles>
156 <repositories>
157 <repository>
158 <id>gwt-maven</id>
159 <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
160 </repository>
161 </repositories>
162 <pluginRepositories>
163 <pluginRepository>
164 <id>gwt-maven</id>
165 <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
166 </pluginRepository>
167 </pluginRepositories>
168 </project>
169 {code}
170
171 *Step 5*: target/xwiki-web-wysiwyg-0.1-SNAPSHOT.war
172
173 In the end you must install the war file in the local repository.
174
175 {code}
176 $ mvn clean install
177 {code}
178
179 1 *Part 2*: The web application
180
181 *Step 0*: Create a maven web project if you don't have one already.
182
183 This web project will integrate the GWT module discussed above.
184
185 *Step 1*: {attach:pom.xml|file=pomwebapp.xml}
186
187 In the project descriptor you have to add a dependency on the GWT module you made and specify how your web application should be assembled, using the [maven-assembly-plugin>http://maven.apache.org/plugins/maven-assembly-plugin/].
188
189 {code:xml}
190 <project>
191 ...
192 <packaging>pom</packaging>
193 ...
194 <dependencies>
195 <dependency>
196 <groupId>com.xpn.xwiki.platform</groupId>
197 <artifactId>xwiki-web-wysiwyg</artifactId>
198 <version>${pom.version}</version>
199 <type>war</type>
200 </dependency>
201 ...
202 </dependencies>
203 <build>
204 <plugins>
205 ...
206 <plugin>
207 <groupId>org.apache.maven.plugins</groupId>
208 <artifactId>maven-assembly-plugin</artifactId>
209 <configuration>
210 <descriptors>
211 <descriptor>src/assemble/application-no-database.xml</descriptor>
212 </descriptors>
213 </configuration>
214 <executions>
215 <execution>
216 <phase>package</phase>
217 <goals>
218 <goal>single</goal>
219 </goals>
220 </execution>
221 </executions>
222 </plugin>
223 </plugins>
224 </build>
225 </project>
226 {code}
227
228 *Step 2*: {attach:src/assemble/application-no-database.xml|file=application-no-database.xml}
229
230 Create an assembly descriptor to integrate the GWT module in the final web application. I've also added two scripts for running and debugging the (integrated) GWT module in hosted mode.
231
232 {code:xml}
233 <assembly>
234 <formats>
235 <format>dir</format>
236 </formats>
237 ...
238 <dependencySets>
239 ...
240 <dependencySet>
241 <!-- This shouldn't be required but there's a bug in version 2.2-beta-1 of the Assembly
242 plugin where the artifact name will be used instead of / if outputFileNameMapping is
243 not specified -->
244 <outputFileNameMapping></outputFileNameMapping>
245 <includes>
246 <include>com.xpn.xwiki.platform:xwiki-web-wysiwyg</include>
247 </includes>
248 <outputDirectory>webapps/xwiki</outputDirectory>
249 <unpack>true</unpack>
250 </dependencySet>
251 ...
252 </dependencySets>
253 <files>
254 ...
255 <file>
256 <source>${basedir}/src/main/resources/start_gwt_noserver_debug.sh</source>
257 <fileMode>755</fileMode>
258 </file>
259 <file>
260 <source>${basedir}/src/main/resources/start_gwt_noserver.sh</source>
261 <fileMode>755</fileMode>
262 </file>
263 </files>
264 ...
265 </assembly>
266 {code}
267
268 *Step 3*: {attach:src/main/resources/start_gwt_noserver.sh|file=startgwtnoserver.sh}
269
270 Create a shell script similar to the following one to run the GWT module in hosted mode. Make sure that you use a 32-bit JRE. Also, the noserver option is needed in order to bind the GWT hosted browser to an external application server where your web application will be deployed.
271
272 {code}
273 #!/bin/bash
274
275 APP_DIR=`dirname $0`/webapps/xwiki;
276 JAVA32_HOME=/usr/lib/jvm/ia32-java-1.5.0-sun-1.5.0.13/bin;
277 GWT_HOME=/home/marius/apps/gwt-linux-1.4.62;
278
279 $JAVA32_HOME/java \
280 -Xmx1024m \
281 -cp $APP_DIR/WEB-INF/classes:\
282 $APP_DIR/WEB-INF/sources:\
283 $APP_DIR/WEB-INF/lib/xwiki-web-gwt-1.5-SNAPSHOT-sources.jar:\
284 $GWT_HOME/gwt-dev-linux.jar:\
285 $GWT_HOME/gwt-user.jar \
286 com.google.gwt.dev.GWTShell \
287 -logLevel WARN \
288 -style DETAILED \
289 -noserver \
290 -port 8080 \
291 -out $APP_DIR/com.xpn.xwiki.wysiwyg.Wysiwyg \
292 xwiki/com.xpn.xwiki.wysiwyg.Wysiwyg/Wysiwyg.html
293 {code}
294
295 *Step 4*: {attach:src/main/resources/start_gwt_noserver_debug.sh|file=startgwtnoserverdebug.sh}
296
297 Create a shell script similar to the following one to debug the GWT module in hosted mode.
298
299 {code}
300 #!/bin/bash
301
302 APP_DIR=`dirname $0`/webapps/xwiki;
303 JAVA32_HOME=/usr/lib/jvm/ia32-java-1.5.0-sun-1.5.0.13/bin;
304 GWT_HOME=/home/marius/apps/gwt-linux-1.4.62;
305
306 $JAVA32_HOME/java \
307 -Xmx1024m \
308 -Xdebug \
309 -Xnoagent \
310 -Djava.compiler=NONE \
311 -Xrunjdwp:transport=dt_socket,server=y,address=5006,suspend=y \
312 -cp $APP_DIR/WEB-INF/classes:\
313 $APP_DIR/WEB-INF/sources:\
314 $APP_DIR/WEB-INF/lib/xwiki-web-gwt-1.5-SNAPSHOT-sources.jar:\
315 $GWT_HOME/gwt-dev-linux.jar:\
316 $GWT_HOME/gwt-user.jar \
317 com.google.gwt.dev.GWTShell \
318 -logLevel WARN \
319 -style DETAILED \
320 -noserver \
321 -port 8080 \
322 -out $APP_DIR/com.xpn.xwiki.wysiwyg.Wysiwyg \
323 xwiki/com.xpn.xwiki.wysiwyg.Wysiwyg/Wysiwyg.html
324 {code}
325
326 *Step 5*: target/xwiki-web-wysiwyg-demo-0.1-SNAPSHOT.dir
327
328 In the end assemble you web application from the command line. Here I use the mysql profile so that my final application is configured to work with this database.
329
330 {code}
331 $ mvn clean install -Pmysql
332 {code}
333
334 1 *Part 3*: Run & Debug
335
336 1.1 Run
337
338 To run the GWT module in hosted mode you need to open two consoles. In the first one you have to start the web server where you deployed the web application. In the second one execute the shell script from the third step. Make sure the application server and the hosted browser listen to the same port (8080 for instance).
339
340 {code}
341 $1 ./start_xwiki.sh
342 $2 ./start_gwt_noserver.sh
343 {code}
344
345 1.1 Debug
346
347 To debug the GWT module in hosted mode you need to open two consoles. In the first one you have to start in debug mode the web server where you deployed the web application. In the second one execute the shell script from the forth step. Make sure the application server and the hosted browser listen to different ports for debugging (5005 and 5006 for instance).
348
349 {code}
350 $1 ./start_xwiki_debug.sh
351 $2 ./start_gwt_noserver_debug.sh
352 {code}
353
354 To debug using XWiki in the backend you have to first start the server (normal or debug, depending if you wish to debug server side code also) and then run the start_wysiwyg_noserver_debug.sh script from the same directory as start_xwiki.sh (copy it there first). The "noserver" part in the script name means that this script doesn't run a server (like gwt maven plugin does) but connects to an existing server.

Get Connected