GWT, Spring when projects are split apart (client, services, persistence)

799 views
Skip to first unread message

Christien Lomax

unread,
May 9, 2012, 9:15:29 AM5/9/12
to google-we...@googlegroups.com
Hi All,

We could use a bit of insight and help if anyone has a moment.

We currently have a project that is quite huge (thousands of classes) including the GWT client, a spring service layer and hibernate persistence layer.

We are trying to split up the project into more manageable pieces including:
  • client project (contains our GWT widgets, RequestFactories, etc, Spring servlets)
  • service project (contains the spring service layer, web services (REST, SOAP))
  • persistence project (contains the domain beans - hibernate mapped objects, persistence code, etc)
  • shared project (classes that can be used on both the client (gwt compiled) and server side.
Everything compiles and works (unit tests, etc) until we hit GWT's compile.  At this point, we get complaints about GWT not being able to see items in the service layer (which makes sense, it is trying to compile references to the beans, services, etc).
We've tried a number of approaches, including using @ServiceName instead of @Service and using the <source .../> specifications on the modules.  Right now we a few errors we are unable to resolve:

1 - we get this one for every Adapte:)
      [ERROR] Errors in 'file:/C:/workspace/client/src/main/java/com/mycompany/adapter/alert/AlertBeanGwtAdapter.java'
         [ERROR] Line 14: No source code is available for type com.mycompany.service.alerts.IAlertService; did you forget to inherit a required module?

2 - if we omit the "-strict" parameter when compiling GWT, we get this:
     [ERROR] An internal compiler exception occurred
     com.google.gwt.dev.jjs.InternalCompilerException: Failed to get JNode
     ...
     [ERROR] <no source info>: public interface com.mycompany.service.alerts.IAlertService
     ...
     org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding
     [ERROR] at AlertBeanGwtAdapter.java(14): private IAlertService getService() {
           return (IAlertService) EcmLocator.getApplicationContext().getBean(IAlertService.TYPE);
     }
     org.eclipse.jdt.internal.compiler.ast.MethodDeclaration

Can anyone shed any light on what we may be doing wrong?  When it is all in one project, everything works fine, but splitting it into multiple projects (that are references via maven) it fails.

Example source (some code is omitted):

Client Layer:

...client.alerts.request.IAlertRequest.java
@ServiceName(value = "com.mycompany.service.alerts.IAlertService.class", locator = "SpringServiceLocator.class")
public interface IAlertRequest extends RequestContext
{
Request<Long> countAlerts(String eventClass, Date dateLimit);
Request<List<IAlertTypeProxy>> listAlertTypes();
Request<List<IAlertBeanProxy>> listUnviewedAlerts();
}

...web.SpringServiceLocator.java
public class SpringServiceLocator implements ServiceLocator
{
public Object getInstance(Class<?> clazz)
{
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestFactoryServlet
.getThreadLocalServletContext());
return context.getBean(clazz);
}
}

OurProject.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='Oris4'>

<inherits name='com.google.gwt.editor.Editor' />
<inherits name='com.google.gwt.json.JSON' />
<inherits name='com.google.gwt.logging.Logging' />
<inherits name='com.google.gwt.resources.Resources' />
<inherits name='com.google.web.bindery.requestfactory.RequestFactory' />
<inherits name='com.google.gwt.user.User' />
<inherits name="com.google.gwt.i18n.I18N" />

<inherits name='com.mycompany.theme.clean.Clean' />
<inherits name='com.mycompany.Persistence' />

<entry-point class='com.mycompany.client.OurEntryPoint' />

<set-configuration-property name="UiBinder.useSafeHtmlTemplates" value="true" />

<source path='client' />
<source path='web' />
<source path='adapter' />
</module>

Service Layer:

...services.alerts.IAlertService.java
public interface IAlertService
{
String TYPE = "AlertService";
Long countAlerts(String eventClass, Date dateLimit);
List<AlertType> listAlertTypes();
List<AlertBean> listUnviewedAlerts();
}

...services.alerts.AlertService.java
@Service("AlertService")
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class AlertService extends EcmService implements IAlertService
{
public Long countAlerts(String eventClass, Date dateLimit) {...};
public List<AlertType> listAlertTypes() {...};
public List<AlertBean> listUnviewedAlerts() {...}; 
}

Persistence Layer:

...domain.alerts.AlertBean.java
@Entity
@Immutable
@Table(name = "alertdisplayview")
public class AlertBean implements Serializable
{
 ...
}

...domain.alerts. AlertType.java
@Entity
@Immutable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Table(name = "alerttype")
@NamedQueries({
@NamedQuery(name = "alertType.findByName", query = "select alt from AlertType alt where alt.name =:name or alt.internalName =:name")
})
public class AlertType implements Serializable
{
 ...
}

Persistence.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='Persistence'>
<source path="domain" />
</module>

Jens

unread,
May 9, 2012, 9:46:37 AM5/9/12
to google-we...@googlegroups.com
How do you compile your app? Maven? Ant? In Eclipse using GPE?

You have to make sure that the GWT compiler's classpath contains all needed source files (= add src/main/java of all projects that need to be compiled by GWT to the compilers classpath).

-- J.

Thomas Broyer

unread,
May 9, 2012, 10:02:08 AM5/9/12
to google-we...@googlegroups.com


On Wednesday, May 9, 2012 3:15:29 PM UTC+2, Christien Lomax wrote:
Hi All,

We could use a bit of insight and help if anyone has a moment.

We currently have a project that is quite huge (thousands of classes) including the GWT client, a spring service layer and hibernate persistence layer.

We are trying to split up the project into more manageable pieces including:
  • client project (contains our GWT widgets, RequestFactories, etc, Spring servlets)
  • service project (contains the spring service layer, web services (REST, SOAP))
  • persistence project (contains the domain beans - hibernate mapped objects, persistence code, etc)
  • shared project (classes that can be used on both the client (gwt compiled) and server side.
Everything compiles and works (unit tests, etc) until we hit GWT's compile.  At this point, we get complaints about GWT not being able to see items in the service layer (which makes sense, it is trying to compile references to the beans, services, etc).
We've tried a number of approaches, including using @ServiceName instead of @Service and using the <source .../> specifications on the modules.  Right now we a few errors we are unable to resolve:

1 - we get this one for every Adapte:)
      [ERROR] Errors in 'file:/C:/workspace/client/src/main/java/com/mycompany/adapter/alert/AlertBeanGwtAdapter.java'
         [ERROR] Line 14: No source code is available for type com.mycompany.service.alerts.IAlertService; did you forget to inherit a required module?

You ahve to produce a source JAR for your artifacts, and then reference them as dependencies in your GWT project.
See https://github.com/tbroyer/gwt-maven-archetypes/tree/master/modular-requestfactory/src/test/resources/projects/basic-rf/reference for an example (here, the GWT client-side, server-side, and shared code –RequestFactory interfaces– are separated into 3 distinct modules; the client module depends on the shared module's <classifier>sources</classifier> to bring its sources in the GWT compiler classpath.
 
2 - if we omit the "-strict" parameter when compiling GWT, we get this:
     [ERROR] An internal compiler exception occurred
     com.google.gwt.dev.jjs.InternalCompilerException: Failed to get JNode
     ...
     [ERROR] <no source info>: public interface com.mycompany.service.alerts.IAlertService
     ...
     org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding
     [ERROR] at AlertBeanGwtAdapter.java(14): private IAlertService getService() {
           return (IAlertService) EcmLocator.getApplicationContext().getBean(IAlertService.TYPE);
     }
     org.eclipse.jdt.internal.compiler.ast.MethodDeclaration

Can anyone shed any light on what we may be doing wrong?  When it is all in one project, everything works fine, but splitting it into multiple projects (that are references via maven) it fails.

Example source (some code is omitted):

Client Layer:

...client.alerts.request.IAlertRequest.java
@ServiceName(value = "com.mycompany.service.alerts.IAlertService.class", locator = "SpringServiceLocator.class")

Don't include the ".class", it's not part of the name of the class.
 
public interface IAlertRequest extends RequestContext
{
Request<Long> countAlerts(String eventClass, Date dateLimit);
Request<List<IAlertTypeProxy>> listAlertTypes();
Request<List<IAlertBeanProxy>> listUnviewedAlerts();
}

...web.SpringServiceLocator.java
public class SpringServiceLocator implements ServiceLocator
{
public Object getInstance(Class<?> clazz)
{
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestFactoryServlet
.getThreadLocalServletContext());
return context.getBean(clazz);
}
}

OurProject.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='Oris4'>

<inherits name='com.google.gwt.editor.Editor' />
<inherits name='com.google.gwt.json.JSON' />
<inherits name='com.google.gwt.logging.Logging' />
<inherits name='com.google.gwt.resources.Resources' />
<inherits name='com.google.web.bindery.requestfactory.RequestFactory' />
<inherits name='com.google.gwt.user.User' />
<inherits name="com.google.gwt.i18n.I18N" />

<inherits name='com.mycompany.theme.clean.Clean' />
<inherits name='com.mycompany.Persistence' />

<entry-point class='com.mycompany.client.OurEntryPoint' />

<set-configuration-property name="UiBinder.useSafeHtmlTemplates" value="true" />

This is the default in GWT 2.4 AFAIK (or will it only be starting with 2.5?)

Christien Lomax

unread,
May 9, 2012, 2:09:56 PM5/9/12
to google-we...@googlegroups.com
Hi Thomas,

First, I want to say that your examples and blogs have helped us a lot over the last year!  Thanks!

Secondly, thanks for the super quick reply!

I added the sources generation to the POMs for the Shared, Persistence and Services projects, and fixed the ".class" issues.  However, we are still getting issues with GWT not being able to find classes/sources...  they (at the moment) seem to be around classes specified via @ExtraTypes which we have specified in our IAppRequestFactory interface.

eg:

@ExtraTypes({
IAlertProxy.class, IAlertOptionsProxy.class, IAlertTypeProxy.class
})
public interface IOris4RequestFactory extends RequestFactory
{
IAlertRequest alertRequest();

...
}

The specific error is:
   Resolving com.mycompany.client.IAppRequestFactory
      Found type 'com.mycompany.client.IApp4RequestFactory'
         [ERROR] Annotation error: cannot resolve com.mycompany.client.alerts.proxy.IAlertProxy
   java.lang.ClassNotFoundException: com.mycompany.client.alerts.proxy.IAlertProxy
   ...
   [ERROR] Annotation error: expected class java.lang.Class, got null

It then eventually down the list starts complaining about the Adapters

Resolving com.mycompany.client.alerts.proxy.IAlertProxy
      Found type 'com.mycompany.client.alerts.proxy.IAlertProxy'
         [ERROR] Annotation error: cannot resolve com.mycompany.adapter.alert.AlertGwtAdapter
      java.lang.ClassNotFoundException: com.mycompany.adapter.alert.AlertGwtAdapter

The proxy classes are specified in the main client project, and the adapter classes are in the same project, but outside the client package (referenced via <source path="adapter" />)

Sorry to bother you again about this, but its had us stuck for a while now.

/c

Christien Lomax

unread,
May 9, 2012, 2:11:15 PM5/9/12
to google-we...@googlegroups.com
Eclipse, using m2e.  All our projects are maven based.  Source is specified as Thomas has outlined (source-jars added to POM).

/c

Joseph Lust

unread,
May 10, 2012, 11:06:09 AM5/10/12
to google-we...@googlegroups.com
Christien,

On our project which is about the size of yours, we have an Interfaces Maven project. Our GWT project makes no direct references to the Services project and visa versa. This way the issue of making the sources available is a non-issue. We use Spring4GWT to wireup GWT->Service RPC calls using the interfaces in the Interfaces project. Thus the build order is (1) Interfaces, (2) GWT, (3) Services.

So there is an interface for the service in the Interface project

@RemoteServiceRelativePath("springGwtServices/marketService")
public interface MarketService extends RemoteService {

MarketDTOContainer getMarketData(Date begin, Date end)
 

So a GWT module references an async interface seen below. Now you can access your service just fine from GWT.
This interface has all the methods of the above interface, but the return value is wrapped in an async callback.

public interface MarketRiskServiceAsync {
void getMarketData(Date begin, Date end, AsyncCallback<MarketDTOContainer> async);
 ..

The actual service uses an annotation to tell Spring where to find it for wireup with a name matching that in the interface.

@Service("marketService")
public class MarketServiceImpl implements MarketService { ...

There is a one off config to setup the servlet mappings:
    <servlet>
        <servlet-name>springGwt</servlet-name>
        <servlet-class>org.spring4gwt.server.SpringGwtRemoteServiceServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>springGwt</servlet-name>
        <url-pattern>springGwtServices/*</url-pattern>
    </servlet-mapping>

Clearly your project is well along, but you might find this pattern useful. While it looks like a lot of interfaces, in many cases we just add another method to a service interface and we're done. We also like the DTOContainer patter since we can pass another parameter along with an existing request by just adding it to the container class. 

Hope this helps you or others with similar issues.

Sincerely,
Joseph

Christien Lomax

unread,
May 10, 2012, 11:56:46 AM5/10/12
to google-we...@googlegroups.com
Hi Joseph,

We are using RequestFactory for most of our calls to the services layer.  We do use GWT-RPC for calls to our Solr/Lucene service, but that's it.  Our projects seems to be setup correctly (with the changes suggested by Thomas), but we still have a few hiccups (highlighted in my previous post).  We actually have a fork of our project doing just what you said, but with moving the interfaces into their own package which is referenced in a module instead of an entirely new project.  Both projects are at the same point however...

It is great to know there is another big project out there though!  Sometimes I wonder if we are alone ;)   I don't suppose you are also using aspectJ instead of proxy based transactions?  We've had a hell of a time with aspectj and it seems to have slowed our environments down a lot (around compiling).  Anyway, off-topic ;)


/c

Thomas Broyer

unread,
May 10, 2012, 12:36:35 PM5/10/12
to google-we...@googlegroups.com


On Wednesday, May 9, 2012 8:09:56 PM UTC+2, Christien Lomax wrote:
Hi Thomas,

First, I want to say that your examples and blogs have helped us a lot over the last year!  Thanks!

Secondly, thanks for the super quick reply!

I added the sources generation to the POMs for the Shared, Persistence and Services projects, and fixed the ".class" issues.  However, we are still getting issues with GWT not being able to find classes/sources...  they (at the moment) seem to be around classes specified via @ExtraTypes which we have specified in our IAppRequestFactory interface.

eg:

@ExtraTypes({
IAlertProxy.class, IAlertOptionsProxy.class, IAlertTypeProxy.class
})
public interface IOris4RequestFactory extends RequestFactory
{
IAlertRequest alertRequest();

...
}

The specific error is:
   Resolving com.mycompany.client.IAppRequestFactory
      Found type 'com.mycompany.client.IApp4RequestFactory'
         [ERROR] Annotation error: cannot resolve com.mycompany.client.alerts.proxy.IAlertProxy
   java.lang.ClassNotFoundException: com.mycompany.client.alerts.proxy.IAlertProxy
   ...
   [ERROR] Annotation error: expected class java.lang.Class, got null


Just to make sure: are your classes javac'd (maven-compiler-plugin) before being GWT-compiled (gwt-maven-plugin)?

Christien Lomax

unread,
May 10, 2012, 1:37:13 PM5/10/12
to google-we...@googlegroups.com
I believe so...  here is our POM for the client project:


<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany</groupId>
<artifactId>client</artifactId>
<version>1.3.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>client</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<gwt.version>2.4.0</gwt.version>
<slf4j.version>1.6.1</slf4j.version>
<log4j.version>1.2.16</log4j.version>
<junit.version>4.10</junit.version>
<spring.version>3.1.1.RELEASE</spring.version>
<spring-security.version>3.1.0.RELEASE</spring-security.version>
<surefire.version>2.12</surefire.version>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<cache.version>${maven.build.timestamp}</cache.version>
</properties>

<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>shared</artifactId>
<version>1.3.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>shared</artifactId>
<version>1.3.1-SNAPSHOT</version>
<classifier>sources</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>service</artifactId>
<version>1.3.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>service</artifactId>
<version>1.3.1-SNAPSHOT</version>
<classifier>sources</classifier>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>persistence</artifactId>
<version>1.3.1-SNAPSHOT</version>
<classifier>sources</classifier>
<scope>provided</scope>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
<scope>provided</scope>
</dependency>

<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-asm</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<optional>false</optional>
</dependency>

<!-- Spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>

<!-- GWT -->
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<version>${gwt.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwt.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code</groupId>
<artifactId>gwtsecurity</artifactId>
<version>1.1.1</version>
</dependency>

<!-- Miscellaneous -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<!-- Generate compiled stuff in the folder used for developing mode -->
<outputDirectory>${webappDirectory}/WEB-INF/classes</outputDirectory>
<finalName>ROOT</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.8</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>Version_template.properties</file>
<outputFile>Version.properties</outputFile>
<basedir>${basedir}/src/main/resources/com/mycompany/client</basedir>

<replacements>
<replacement>
<token>VERSION_TOKEN</token>
<value>${project.version}</value>
</replacement>
<replacement>
<token>BUILDNUMBER_TOKEN</token>
<value>${buildNumber}</value>
</replacement>
<replacement>
<token>JENKINS_TOKEN</token>
<value>${BUILD_NUMBER}</value>
</replacement>
<replacement>
<token>BUILDDATE_TOKEN</token>
<value>${maven.build.timestamp}</value>
</replacement>
</replacements>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>

<!-- GWT Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<goals>
<goal>clean</goal>
<goal>compile</goal>
<goal>test</goal>
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see gwt-maven-plugin 
documentation at codehaus.org -->
<configuration>
<runTarget>OurApp.jsp</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
<extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
</configuration>
<dependencies>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>2.4.0-4sight</version>
</dependency>
</dependencies>
</plugin>

<!-- Copy static web files before executing gwt:run -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>OurApp.jsp</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.7</version>
<configuration>
<sourceExcludes>
<sourceExclude>**/emul/**/*.java</sourceExclude>
</sourceExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.0.5</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<compilerArguments>-Averbose=false</compilerArguments>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.google.web.bindery</groupId>
<artifactId>requestfactory-apt</artifactId>
<version>${gwt.version}</version>
</dependency>
</dependencies>
</plugin>

<!-- Google Plugin for Eclipse (GPE) won't see the source generated above 
by requestfactory-apt unless it is exposed as an additional source dir -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/apt</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
</configuration>
</plugin>

</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings 
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>

<pluginExecution>
<pluginExecutionFilter>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<versionRange>[2.0.5,)</versionRange>
<goals>
<goal>process</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
com.google.code.maven-replacer-plugin
</groupId>
<artifactId>
maven-replacer-plugin
</artifactId>
<versionRange>
[1.3.8,)
</versionRange>
<goals>
<goal>replace</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-war-plugin
</artifactId>
<versionRange>
[2.1.1,)
</versionRange>
<goals>
<goal>exploded</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

Ümit Seren

unread,
May 11, 2012, 3:09:17 AM5/11/12
to google-we...@googlegroups.com
I have  a question to the people who are using multi-module maven projects instead of one (I am currently developing a Spring/GWT/RequestFactory project as one big maven projects). 
I do much of the debugging in eclipse by starting a WTP jetty instance and then starting the GWT development mode. By this I can debug both backend and frontend and whenever I change something in the client code it will work without me restarting development mode and when i change something on the backend WTP should re-publish it and it should also work fine (although some stuff doesn't). 

I am using eclipse m2eclipse for dependency management. ( I don't use mvn jetty:run or so but WTP) . 
Does the same workflow also work when I split up the one maven module into multiple? (shared, client, server) 
I guess it should as the m2 will probably make sure that everything is in the right place. 
But maybe somebody has already experience with debugging a multi maven module in eclipse and can give some feedback. 

Thomas Broyer

unread,
May 11, 2012, 3:48:07 AM5/11/12
to google-we...@googlegroups.com


On Friday, May 11, 2012 9:09:17 AM UTC+2, Ümit Seren wrote:
I have  a question to the people who are using multi-module maven projects instead of one (I am currently developing a Spring/GWT/RequestFactory project as one big maven projects). 
I do much of the debugging in eclipse by starting a WTP jetty instance and then starting the GWT development mode. By this I can debug both backend and frontend and whenever I change something in the client code it will work without me restarting development mode and when i change something on the backend WTP should re-publish it and it should also work fine (although some stuff doesn't). 

I am using eclipse m2eclipse for dependency management. ( I don't use mvn jetty:run or so but WTP) . 
Does the same workflow also work when I split up the one maven module into multiple? (shared, client, server) 
I guess it should as the m2 will probably make sure that everything is in the right place. 
But maybe somebody has already experience with debugging a multi maven module in eclipse and can give some feedback.

We've been doing it for more than 1½ year now, it works really well. I'd never used jetty:start or gwt:run before working on the gwt-maven-archetypes.
We only used WTP for a few months, and then switched to launching Jetty from a shell script, with a context dedicated to development where it reads classes and resources from our different projects: 'touch' the context file and Jetty redeploys the app in seconds. We had a few issues with WTP (not redeploying some JARs/classes, etc.)
As for GWT DevMode, you have to add the source folders of your dependencies (the 'shared' project, possibly others) to the classpath in your Eclipse launcher. Depending on the configuration of your servlet container / deployed app, you might have to use the 'server' project's project.build.outputDirectory or WTP's temporary folder as the -war folder for the DevMode.

Ümit Seren

unread,
May 11, 2012, 10:12:16 AM5/11/12
to google-we...@googlegroups.com
Thanks for the feedback Thomas, 
I was actually following the gwt_with_maven docs at the google developers page (tough only creating one maven war project). 
So I think it should be quite easy to split it up.
BTW. do these 3  (or 4 respectively) modules go into separate VCS repositories or do all go into one? 
I guess they could be checked into separate VCS repositories as the dependency is handled by maven anyways. 

How do you do deployment? Do you have a dedicated jetty instance on the production server and package the war and deploy it?

Thomas Broyer

unread,
May 11, 2012, 10:49:17 AM5/11/12
to google-we...@googlegroups.com


On Friday, May 11, 2012 4:12:16 PM UTC+2, Ümit Seren wrote:
Thanks for the feedback Thomas, 
I was actually following the gwt_with_maven docs at the google developers page (tough only creating one maven war project). 
So I think it should be quite easy to split it up.

Yes, very easy (provided you understand what you do and what you *need* to do).
 
BTW. do these 3  (or 4 respectively) modules go into separate VCS repositories or do all go into one? 
I guess they could be checked into separate VCS repositories as the dependency is handled by maven anyways.

These are all Maven modules under a "super-module", so we use a single VCS repo. It depends on your modules' lifecycle management; we always release the whole "package", so it makes no sense to have them as separate modules tracked independently (in independent VCS repos, with independently evolving version numbers, etc.)
 
How do you do deployment? Do you have a dedicated jetty instance on the production server and package the war and deploy it?

We have a quite specific setup, where we have a dedicated Jetty instance that's quite heavily tuned and adapted to our needs (many objects –including an HornetQ event-bus– instantiated in Jetty's XML files, and some of them passed to our app via JNDI). Our deliverable includes the Jetty configuration and startup scripts, WARs (we have several apps, only one using GWT) and shared libs.

For other projects with no/less specific needs, packaging as a WAR and deploying in whatever servlet container (or even EAR / application server) would Just Work™. In Maven, you could use Cargo <http://cargo.codehaus.org/> instead of jetty:start if you wanted.

JoseM

unread,
May 18, 2012, 11:32:59 AM5/18/12
to google-we...@googlegroups.com
Can you expand a bit more on how to get GWT DevMode to work by launching from within Eclipse? We are used to creating a GWT Application run configuration in eclipse but right now I am not sure how to get to work so that the HTML/webapp resources are available to the run configuration.

Thomas Broyer

unread,
May 18, 2012, 11:52:48 AM5/18/12
to google-we...@googlegroups.com


On Friday, May 18, 2012 5:32:59 PM UTC+2, JoseM wrote:
Can you expand a bit more on how to get GWT DevMode to work by launching from within Eclipse? We are used to creating a GWT Application run configuration in eclipse but right now I am not sure how to get to work so that the HTML/webapp resources are available to the run configuration.

The easiest is to Run as… → Web Application. It will fail because it's missing the source code for your other projects, but it'll have created the launcher. Edit it to add your other projects' src/main/java and src/main/resources (or whatever, if you'e not using Maven) to the classpath.
If you want to share the *.launch file with other devs (e.g. commit it to your VCS), then you can replace absolute file paths in the "arguments" tab with Eclipse variables.

JoseM

unread,
May 18, 2012, 5:37:20 PM5/18/12
to google-we...@googlegroups.com
So I am assuming I would do this on the client project right? I can't sem to get it to work though.  

No matter what settings I put for the war I get this message:

[WARN] No startup URLs supplied and no plausible ones found -- use -startupUrl

And when I go to the root of the jetty server the index.html file is not there.  

Thomas Broyer

unread,
May 19, 2012, 6:21:51 AM5/19/12
to google-we...@googlegroups.com


On Friday, May 18, 2012 11:37:20 PM UTC+2, JoseM wrote:
So I am assuming I would do this on the client project right? I can't sem to get it to work though.  

No matter what settings I put for the war I get this message:

[WARN] No startup URLs supplied and no plausible ones found -- use -startupUrl

Oh yeah, sure, I forgot to say that you have to add or update the -startupUrl argument: -startupUrl http://127.0.0.1:8080/foobar/index.html (where the URL is the one of your Jetty server), and uncheck "use embedded server" (or add the -noserver argument).

 

And when I go to the root of the jetty server the index.html file is not there.

Then you have to build your project, or whatever it takes to make your webapp work (i.e. copy index.html to the folder served by your jetty server); that goes beyond GWT usage though.

JoseM

unread,
May 19, 2012, 10:02:05 AM5/19/12
to google-we...@googlegroups.com
I didn't realize I had to still run the jetty server seperately before.  I got it to work now running the jetty server using mvn jetty:start -Ddev and I just needed to right-click Run As "Web Application (running on an external server)" and supply the url (something like http://localhost:8080/{projectName}-server-1.0-SNAPSHOT/ )and uncheck the "Select an HTML page" option.

Is there a way to have it all running from within in eclipse with one command? Maybe even with the embedded jetty? The reason I ask is to make it easier to use the eclipse debugger to debug both server side and client side code at the same time.

Or can I somehow startup the jetty server within eclipse so that I can run it in debug mode?

Joseph Lust

unread,
May 19, 2012, 1:43:38 PM5/19/12
to google-we...@googlegroups.com
Jose,

I see that you're using the mvn commandline param. Why not use a built in Eclipse run configuration? While I have not used your exact configuration, I think you should be able to achieve it with something like the below using the maven-gwt-plugin (or similar):

Goals: gwt:compile gwt:debug 



With a custom run configuration you should be able to get whatever custom launch steps you need at a single click from within Eclipse.

You'll also need to add all the desired parameters (I've added startupUrl as an example). I don't have a list on me, but use the same parameters that the Eclipse Web Application starter uses under the Arguments tab. (pictured for my GWT-Maps-V3-Api project build).

Still, I think you'll find it easier to use the Web Application launcher as it provides a nice UI for setting these parameters and generating the commandline string. My team uses the built-in server option of the Web Application configure and there is no need to startup Jetty in that case.

I hope that helps.


Sincerely,
Joseph

Reply all
Reply to author
Forward
0 new messages