tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Tapestry Wiki] Update of "Tapestry5GWTIntegration" by DanielJue
Date Wed, 31 Dec 2008 19:24:15 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for change notification.

The following page has been changed by DanielJue:
http://wiki.apache.org/tapestry/Tapestry5GWTIntegration

------------------------------------------------------------------------------
  = Tapestry 5 GWT Integration =
- 
+ [http://www.phy6.net/downloads/T5GWT/myapp.zip Download the Source code and Project]
  This article is on making use of both of these technologies.
- 
+ [http://www.phy6.net/downloads/T5GWT/myapp.png]
  ==== Reader Requirements ====
  
   *Basic knowledge of T5 features
   *Know how to create the hello world archetype of both T5 and GWT.
   *very basic Maven knowledge
+  *Suggest you read through the first GWT tutorial, linked from the wiki page.
  
  ==== Technologies Used ====
  
@@ -32, +33 @@

  
  
  
- === More in a bit ===
+ === Lets get you set up ===
+ You can download the whole project using the link above.  Here's the POM for you to look
at:
  
- What I will show here:
+ '''full pom.xml'''
  
- A single project using WTP, includes Tapestry 5 and GWT in one project.
- Modifying the POM and Web XML for new entrypoints.
- Maven and or CMD file to execute gwt builds
- Multiple simple components on one page
- Multiple instances of the same RPC component on one page!
+ {{{
+ <project
+ 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
+ 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
+ 	<modelVersion>4.0.0</modelVersion>
+ 	<groupId>org.example</groupId>
+ 	<artifactId>myapp</artifactId>
+ 	<version>1.0.0-SNAPSHOT</version>
+ 	<packaging>war</packaging><!--
+ 	First use clean compile gwt:compile, and afterwards you can just run the compile.cmd that
gets generated.
+ 	Remember to refresh your source directory before serving this, since the GWT compilation
outputs into a source dir!
+ 	--><name>myapp Tapestry 5 Application</name>
+ 	<dependencies>
+     	<!--  GWT deps (from central repo) -->
+ 		<dependency>
+ 			<groupId>com.google.gwt</groupId>
+ 			<artifactId>gwt-servlet</artifactId>
+ 			<version>${gwtVersion}</version>
+ 			<scope>runtime</scope>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>com.google.gwt</groupId>
+ 			<artifactId>gwt-user</artifactId>
+ 			<version>${gwtVersion}</version>
+ 			<scope>provided</scope>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>com.google.gwt</groupId>
+ 			<artifactId>gwt-dev</artifactId>
+ 			<version>${gwtVersion}</version>
+ 			<classifier>${platform}-libs</classifier>
+ 			<type>zip</type>
+ 			<scope>provided</scope>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>com.google.gwt</groupId>
+ 			<artifactId>gwt-dev</artifactId>
+ 			<version>${gwtVersion}</version>
+ 			<classifier>${platform}</classifier>
+ 			<scope>provided</scope>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>log4j</groupId>
+ 			<artifactId>log4j</artifactId>
+ 			<version>1.2.14</version>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>junit</groupId>
+ 			<artifactId>junit</artifactId>
+ 			<version>4.1</version>
+ 			<scope>test</scope>
+ 		</dependency>
+ 		<dependency>
+ 			<groupId>org.apache.tapestry</groupId>
+ 			<artifactId>tapestry-core</artifactId>
+ 			<version>${tapestry-release-version}</version>
+ 		</dependency>
+ 		<!--
+ 			A dependency on either JUnit or TestNG is required, or the surefire
+ 			plugin (which runs the tests) will fail, preventing Maven from
+ 			packaging the WAR. Tapestry includes a large number of testing
+ 			facilities designed for use with TestNG (http://testng.org/), so it's
+ 			recommended.
+ 		-->
+ 		<dependency>
+ 			<groupId>org.testng</groupId>
+ 			<artifactId>testng</artifactId>
+ 			<version>5.1</version>
+ 			<classifier>jdk15</classifier>
+ 			<scope>test</scope>
+ 		</dependency>
+ 	</dependencies>
+ 	<build>
+ 		<finalName>myapp</finalName>
+ 		<resources>
+ 			<resource>
+ 				<directory>src/main/resources</directory>
+ 				<includes>
+ 					<include>**</include>
+ 				</includes>
+ 				<excludes>
+ 					<exclude>hibernatecfg/*</exclude>
+ 					<exclude>hibernate.cfg.xml</exclude>
+ 					<exclude>log4j.properties</exclude>
+ 					<exclude>spy.properties</exclude>
+ 					<exclude>version.properties</exclude>
+ 					<exclude>**/.svn/**</exclude>
+ 				</excludes>
+ 			</resource>
+ 			<resource>
+ 				<directory>src/main/java</directory>
+ 				<includes>
+ 					<include>**/*</include>
+ 				</includes>
+ 				<excludes>
+ 					<exclude>**/*.java</exclude>
+ 					<exclude>**/.svn/**</exclude>
+ 				</excludes>
+ 			</resource>
+ 		</resources>
+ 		<plugins>
+ <!--  configure the GWT-Maven plugin -->
+ 			<plugin>
+ 				<groupId>com.totsp.gwt</groupId>
+ 				<artifactId>maven-googlewebtoolkit2-plugin</artifactId>
+ 				<version>2.0-beta26</version>
+ 				<configuration>
+ 					<logLevel>INFO</logLevel>
+ 					<compileTargets>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.Sample</value>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.ComplexSample</value>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.StockWatcher</value>
+ 					</compileTargets>
+ 					<runTarget>/myapp/Start</runTarget>
+ 					<style>DETAILED</style>
+ 					<noServer>false</noServer>
+ 					<extraJvmArgs>-Xmx512m</extraJvmArgs>
+ 					<!--
+ 						this parameter is VERY important with automatic mode - has to
+ 						match the version in your declared deps
+ 					-->
+ 					<!--
+ 						if this is set incorrect, or left out and default does not match
+ 						(default is 1.5.3) you will have mysterious errors
+ 					-->
+ 					<gwtVersion>${gwtVersion}</gwtVersion>
+ 					<!-- This puts the GWT output (javascripts) into the source tree -->
+ 					<output>src/main/webapp</output >
+ 				</configuration>
+ 				<executions>
+ 					<execution>
+ 						<goals>
+ 							<!--<goal>mergewebxml</goal>
+ 							--><!--<goal>i18n</goal>
+ 							-->
+ 							<goal>compile</goal>
+ 							<!--<goal>test</goal>
+ 						-->
+ 						</goals>
+ 					</execution>
+ 				</executions>
+ 			</plugin>
+ 			<!--  Use the dependency plugin to unpack gwt-dev-PLATFORM-libs.zip -->
+ 			<!--
+ 				(this is a replacement for the old "automatic" mode - useful if you
+ 				don't have GWT installed already, or you just want a maven way to
+ 				handle gwt deps)
+ 			-->
+ 			<plugin>
+ 				<groupId>org.apache.maven.plugins</groupId>
+ 				<artifactId>maven-dependency-plugin</artifactId>
+ 				<executions>
+ 					<execution>
+ 						<id>unpack</id>
+ 						<phase>compile</phase>
+ 						<goals>
+ 							<goal>unpack</goal>
+ 						</goals>
+ 						<configuration>
+ 							<artifactItems>
+ 								<artifactItem>
+ 									<groupId>com.google.gwt</groupId>
+ 									<artifactId>gwt-dev</artifactId>
+ 									<version>${gwtVersion}</version>
+ 									<classifier>${platform}-libs</classifier>
+ 									<type>zip</type>
+ 									<overWrite>false</overWrite>
+ 									<outputDirectory>${settings.localRepository}/com/google/gwt/gwt-dev/${gwtVersion}</outputDirectory>
+ 								</artifactItem>
+ 							</artifactItems>
+ 						</configuration>
+ 					</execution>
+ 				</executions>
+ 			</plugin>
+ 			<!--
+ 				If you want to use the target/web.xml file mergewebxml produces,
+ 				tell the war plugin to use it. Also, exclude what you want from the
+ 				final artifact here.
+ 			-->
+ 			<plugin>
+ 				<groupId>org.apache.maven.plugins</groupId>
+ 				<artifactId>maven-war-plugin</artifactId>
+ 				<configuration><!--
+ 					<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
+ 					--><warSourceExcludes>.gwt-tmp/**</warSourceExcludes>
+ 				</configuration>
+ 			</plugin>
+ 			<!--  tell the compiler we can use 1.5 -->
+ 			<plugin>
+ 				<groupId>org.apache.maven.plugins</groupId>
+ 				<artifactId>maven-compiler-plugin</artifactId>
+ 				<configuration>
+ 					<source>1.5</source>
+ 					<target>1.5</target>
+ 				</configuration>
+ 			</plugin>
+ 		</plugins>
+ 	</build>
+ <!--  profiles (with activation per platform) -->
+ 	<profiles>
+ 		<profile>
+ 			<id>gwt-dev-windows</id>
+ 			<properties>
+ 				<platform>windows</platform>
+ 			</properties>
+ 			<activation>
+ 				<activeByDefault>true</activeByDefault>
+ 				<os>
+ 					<family>windows</family>
+ 				</os>
+ 			</activation>
+ 		</profile>
+ 		<profile>
+ 			<id>gwt-dev-mac</id>
+ 			<properties>
+ 				<platform>mac</platform>
+ 			</properties>
+ 			<activation>
+ 				<activeByDefault>false</activeByDefault>
+ 				<os>
+ 					<family>mac</family>
+ 				</os>
+ 			</activation>
+ 		</profile>
+ 		<profile>
+ 			<id>gwt-dev-linux</id>
+ 			<properties>
+ 				<platform>linux</platform>
+ 			</properties>
+ 			<activation>
+ 				<activeByDefault>false</activeByDefault>
+ 				<os>
+ 					<name>linux</name>
+ 				</os>
+ 			</activation>
+ 		</profile>
+ 	</profiles>
+ 	<reporting>
+ 		<!--
+ 			Adds a report detailing the components, mixins and base classes
+ 			defined by this module.
+ 		-->
+ 		<plugins>
+ 			<plugin>
+ 				<groupId>org.apache.tapestry</groupId>
+ 				<artifactId>tapestry-component-report</artifactId>
+ 				<version>${tapestry-release-version}</version>
+ 				<configuration>
+ 					<rootPackage>org.example.myapp</rootPackage>
+ 				</configuration>
+ 			</plugin>
+ 		</plugins>
+ 	</reporting>
+ 	<repositories>
+ 		<!--
+ 			This can be commented out when the tapestry-release-version is a not
+ 			a snapshot. The non-snapshot Tapestry artifacts are distributed
+ 			through the central repository at ibiblio.
+ 		-->
+ 		<repository>
+ 			<id>tapestry-snapshots</id>
+ 			<url>http://tapestry.formos.com/maven-snapshot-repository/
+ 			</url>
+ 		</repository>
+ 		<repository>
+ 			<id>codehaus.snapshots</id>
+ 			<url>http://snapshots.repository.codehaus.org
+ 			</url>
+ 		</repository>
+ 		<repository>
+ 			<id>OpenQA_Release</id>
+ 			<name>OpenQA Release Repository</name>
+ 			<url>http://archiva.openqa.org/repository/releases/
+ 			</url>
+ 		</repository>
+ 		<repository>
+ 			<id>gwt-maven</id>
+ 			<url> http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
+ 		</repository>
+ 	</repositories>
+ 	<pluginRepositories>
+ 		<!--
+ 			As above, this can be commented out when access to the snapshot
+ 			version of a Tapestry Maven plugin is not required.
+ 		-->
+ 		<pluginRepository>
+ 			<id>tapestry-snapshots</id>
+ 			<url>http://tapestry.formos.com/maven-snapshot-repository/
+ 			</url>
+ 		</pluginRepository>
+ 		<pluginRepository>
+ 			<id>gwt-maven-plugins</id>
+ 			<url> http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url>
+ 		</pluginRepository>
+ 	</pluginRepositories>
+ 	<properties>
+ 		<gwtVersion>1.5.3</gwtVersion>
+ 		<tapestry-release-version>5.0.18</tapestry-release-version>
+ 	</properties>
+ </project>
+ }}}
  
- Source code link!  The project exists already!
  
+ For now, I manually make additions to the web.xml if a servlet mapping is needed.  So far
this example only uses one, for the Stock Prices.
+ 
+ '''web.xml'''
+ {{{ 
+ <?xml version="1.0" encoding="UTF-8"?>
+ <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
+ 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ 	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ 	<session-config>
+ 		<session-timeout> 30 </session-timeout>
+ 	</session-config>
+ 	<welcome-file-list>
+ 		<welcome-file>Start</welcome-file>
+ 	</welcome-file-list>
+ 	<display-name>Tapestry 5 With GWT</display-name>
+ 	<context-param>
+ 		<param-name>tapestry.app-package</param-name>
+ 		<param-value>se.pmdit.tutorial.t5gwt.tapestry</param-value>
+ 	</context-param>
+ 	<filter>
+ 		<filter-name>app</filter-name>
+ 		<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
+ 	</filter>
+ 	<filter-mapping>
+ 		<filter-name>app</filter-name>
+ 		<url-pattern>/*</url-pattern>
+ 	</filter-mapping>
+ 	<servlet>
+ 		<servlet-name>stock</servlet-name>
+ 		<servlet-class>se.pmdit.tutorial.t5gwt.gwt.server.StockPriceServiceImpl</servlet-class>
+ 	</servlet>
+ 	<servlet-mapping>
+ 		<servlet-name>stock</servlet-name>
+ 		<url-pattern>/se.pmdit.tutorial.t5gwt.gwt.StockWatcher/stockPrices</url-pattern>
+ 	</servlet-mapping>
+ </web-app>
+ }}}
+ 
+ 
+ 
+ === Adding GWT Targets in the POM ===
+ Notice that for each entrypoint you want to have compiled, you add it here.
+ {{{
+ ...
+   					<compileTargets>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.Sample</value>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.ComplexSample</value>
+ 						<value>se.pmdit.tutorial.t5gwt.gwt.StockWatcher</value>
+ 					</compileTargets>
+ ...
+ }}}
+ 
+ 
+ === The StockWatcher Entrypoint ===
+ {{{
+ package se.pmdit.tutorial.t5gwt.gwt.client;
+ 
+ import com.google.gwt.core.client.EntryPoint;
+ import com.google.gwt.i18n.client.Dictionary;
+ import com.google.gwt.user.client.Timer;
+ import com.google.gwt.user.client.ui.RootPanel;
+ /**
+  * 
+  * @author djue
+  *
+  */
+ public class StockWatcher implements EntryPoint {
+ 
+ 	private static final int REFRESH_INTERVAL = 5000; // ms
+ 
+ 	public void onModuleLoad() {
+ 
+ 		// Find all the instances in this DOM where this entry point should be
+ 		// created.
+ 		// The dictionary is created by
+ 		Dictionary gwtComponents = Dictionary.getDictionary("gwtComponents");
+ 		if (gwtComponents != null) {
+ 			String str[] = gwtComponents.get("stockwatcher").split(",");
+ 			for (int i = 0; i < str.length; i++) {
+ 				createUniqueModule(str[i]);
+ 			}
+ 		}
+ 
+ 	}
+ 
+ 	/**
+ 	 * @param string
+ 	 */
+ 	private void createUniqueModule(String string) {
+ 
+ 		// // add the main panel to the HTML element with the id "stockList"
+ 		// RootPanel.get("stockList"+string).add(mainPanel);
+ 
+ 		final StockWatcherPanel swp = new StockWatcherPanel();
+ 		// add the main panel to the HTML element with the id "stockList"
+ 		RootPanel.get("stockList" + string).add(swp);
+ 
+ 		// setup timer to refresh list automatically
+ 		Timer refreshTimer = new Timer() {
+ 			public void run() {
+ 				swp.refreshWatchList();
+ 			}
+ 		};
+ 		refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
+ 
+ 		// move cursor focus to the text box
+ 		swp.newSymbolTextBox.setFocus(true);
+ 
+ 	}
+ 
+ }
+ 
+ }}}
+ 
+ 
+  === The StockWatcherComponent ===
+ {{{
+ /*
+  * To change this template, choose Tools | Templates
+  * and open the template in the editor.
+  */
+ 
+ package se.pmdit.tutorial.t5gwt.tapestry.components;
+ 
+ import org.apache.tapestry5.Asset;
+ import org.apache.tapestry5.ComponentResources;
+ import org.apache.tapestry5.RenderSupport;
+ import org.apache.tapestry5.annotations.Environmental;
+ import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary;
+ import org.apache.tapestry5.annotations.Path;
+ import org.apache.tapestry5.annotations.Property;
+ import org.apache.tapestry5.ioc.annotations.Inject;
+ 
+ /**
+  * 
+  * @author djue
+  */
+ @IncludeJavaScriptLibrary("context:se.pmdit.tutorial.t5gwt.gwt.StockWatcher/se.pmdit.tutorial.t5gwt.gwt.StockWatcher.nocache.js")
+ public class StockWatcherComponent extends GWTEntryPointComponent {
+ 	@Environmental
+ 	private RenderSupport renderSupport;
+ 	@Inject
+ 	private ComponentResources resources;
+ 
+ 	@Inject
+ 	@Path("context:se.pmdit.tutorial.t5gwt.gwt.StockWatcher/images/GoogleCode.png")
+ 	@Property
+ 	private Asset banner;
+ 
+ 	void setupRender() {
+ 		renderSupport.addScript("GWTComponentController.add('stockwatcher','" + resources.getCompleteId()
+ "')");
+ 	}
+ 	// If you wanted you could output the DIV from here, then you would not
+ 	// need the template file.
+ }
+ }}}
+ 
+ Make special note of this line:
+ 
+ {{{
+ ...
+ renderSupport.addScript("GWTComponentController.add('stockwatcher','" + resources.getCompleteId()
+ "')");
+ ...
+ }}}
+ It's kind of like adding it to a HashMap<String,String>.  (It's not really a HashMap,
but later your Entrypoint will look up values associated with a key;  The key will be 'stockwatcher',
and the values will be the T5 generated ids)
+ 
+  === The StockWatcherComponent.tml ===
+ Notice the div where the id becomes stockList+component id.  This allows a unique and independent
stock list to be created.  
+ {{{
+ <div xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+ Stock Watcher Component
+ <div id="${componentResources.completeId}"></div>
+ <img src="${banner}" />
+ <h1>Stock Watcher</h1>
+ <div id="stockList${componentResources.completeId}"></div>
+ </div>
+ }}}
+  Note that this:
+ {{{
+ ...
+ <div id="${componentResources.completeId}"></div>
+ ...
+ }}}
+ Is the same id that you added in the "HashMap" above.
+ 
+ 
+ == General Tips ==
+ 
+ In general it can be very easy to get GWT working with Tapestry.  The complexity comes in
when you want GWT to be a component, and you consider that a component may exist many times
on one page.  (think of dialog boxes).  In order for the components to behave properly, you
must somehow provide a unique ID to the Javascript object that GWT will create.
+ 
+ In your GWT code, make the Entrypoint class do as little as possible.  I've read this elsewhere
as a GWT mini-pattern, but it helps alot here!  Even references to your GWT services can be
put into the separate class that your Entrypoint will instantiate.  In fact the Entrypoints
I show here do pretty much the same thing:
+  * They load a dictionary and find all the values for a certain "key"
+  * For each value, a new instance of something is created
+ 
+ For example, there will be a String like this:
+ {{{
+ mydialog,mydialog1,mydialog2
+ }}}
+ These are the unique id's that Tapestry will create for you.  Some included Javascript (from
the other GWT tutorial) will copy these unique id's into a Javascript variable.  The compiled
GWT Javascript will then read that list of id's in your Entrypoint (as shown later)
+ 
+ So instead of having all kinds of code in your entrypoint class, refactor it into a separate
class that your entrypoint will add to the RootPanel.
+ 
+ == Some unusual things about this ==
+ 
+ The GWT is configured in the POM to output it's compiled directories into your src/webapp.
+ (If someone knows a way to use Maven Assembly or an Ant copy that will work better, please
add it to this wiki)
+ This will require a refresh of your source dir after compilation, or Eclipse won't see the
GWT compiled code.
+ If Eclipse does not see the new files, then your Tomcat instance won't see it either if
you are launching Tomcat from Eclipse.
+ 
+ I have not included the gwt compiled directories in the Zip file, because they should be
generated for you when you run:
+ {{{
+ mvn clean compile gwt:compile
+ }}}
+ 
+ clean will delete the Target directory
+ compile will take care of Java compilation like your T5 code
+ gwt:compile will take care of your GWT generated code (the Javascript)
+ 
+ You could also launch tomcat afterwards using Maven, but I find this less thank friendly.
+ 
+ You can leave "Build Automatically" checked in your Eclipse project settings, and Tomcat
should restart when you make changes on the Tapestry side.  But you'll need to restart Tomcat
otherwise.
+ 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org


Mime
View raw message