Search code examples
javaeclipsemavengwtjrebel

How to configure mvn/Jrebel/wtp/gwt/eclipse to work smoothly with changes on the service interface


I started to investigate the guice-rf-activities artifact with the new maven gwt plugin from Thomas Broyer.

I played a little bit with the code and added a function on the GreetingService on the serverside. I followed down the path and added the required bits and bytes until the code was properly calling either the greetServer or insultServer method.

I found, that a simple SDM recompile did not make the method available on the server. Restarting the Tomcat did not help either. Saving a file in eclipse did not trigger the compile properly.

In the end, running a full module compile did the trick.

I see this as a problem, as any change on the service will potentially give you some time for coffee on large projects. Is there some "trick", I did not do, or is the complexity of RequestFactory code generation that heavy, that I cannot simply use the SDM + JRebel or server restart to change the service interfaces?

UPDATE: The way described by Thomas (thanks!) works, if you plan to start your tomcat with the maven tomcat target.

UPDATE2: Described the launcherDir approach to get the wtp/eclipse/mvn/Jrebel to run.

If you want to use the eclipse wtp tomcat launcher and, as I do, JRebel, to compile your server-classes on the fly, the JRebel reload will not catch the ofuscated RF service names.
To fix this, add the following JVM attribute to your wtp launch configuration (thanks, Thomas!):

-Dgwt.rf.ServiceLayerCache=false

When the server interface changes, the following happens
(eclipse Luna Service Release 2 (4.4.2), JRebel 6.x):

  • change your service and context classes as required
    • you see JRebel reloading the class
  • call mvn process-classes on the commandline
    • you see JRebel reloading the obfuscationfactory
  • SDM compile in the browser (F5 will do the trick)
    • Your service is now working in the client

Linking the gwt client code with the wtp server

To link the codeserver with the wtp environment, the src/main/webapp folder needs to contain your GWT code folder. To achieve this, the codeserver must be directed to generate the SDM stub at the right location. Add a property to the module/pom.xml as such:

<properties>    
    <gwt.launcherDir>${project.build.directory}/gwt/launcherDir</gwt.launcherDir>
</properties>

Additionally, configure the gwt maven plugin to use the property instead:

<build>
  <plugins>
    <plugin>
      <groupId>net.ltgt.gwt.maven</groupId>
      <artifactId>gwt-maven-plugin</artifactId>
      <inherited>false</inherited>
      <configuration>
        <launcherDir>${gwt.launcherDir}</launcherDir>
      </configuration>
    </plugin>
  </plugins>
  ...

To run the codeserver inside eclipse or on the commandline, give the proper definition for gwt.launcherDir to maven. I am using a small cmd to run the codeserver for eclipse:

mvn -Dgwt.launcherDir=module-app-server\src\main\webapp gwt:codeserver

This way, the "recompile on f5" works very nice and smooth. This is finally the full integration of GWT in eclipse with maven and JRebel. Wow. Kudos to @TBroyer :-)


Solution

  • The client side doesn't need anything special. The server side though requires the RequestFactory and all its RequestContext and proxies hierarchy to be processed by the validation tool.

    From the command line, in the context of the archetypes, that means launching the process-classes phase on the *-server module, e.g.

    mvn process-classes -pl *-server -am
    

    With the mvn tomcat7:run -Denv=dev running, Tomcat should detect the class changes and automatically reload the webapp.

    Then just refresh the page in the browser, and after authenticating again (reloading the webapp in Tomcat loses the session/authentication) you can see the changes end-to-end.

    Steps to reproduce:

    1. create the project
    2. in one terminal, launch mvn gwt:codeserver -pl *-client -am
    3. in another terminal, launch mvn tomcat7:run -pl *-server -am -Denv=dev
    4. open http://localhost:8080 in your browser, sign into the webapp and notice the client-side app compiling automatically (that's the new SDM in GWT 2.7)
    5. edit *-shared/src/main/java/**/GreetingContext.java and duplicate greetServer as insultServer
    6. similarly, edit *-server/src/main/java/**/GreetingService.java and duplicate greetServer and insultServer (change the Hello message into an insult to feel the change)
    7. edit *-client/src/main/java/**/GreetingActivity.java and replace the call to greetServer to a call to insultServer (or add another button and duplicate the code)
    8. in yet another terminal, run mvn process-classes -pl *-server -am; notice that Tomcat reloads the webapp
    9. Refresh the page in the browser, sign in again, and notice the client-side app recompiling. Hit the button and get insulted rather than greeted. QED.

    The validation tool can be configured as an annotation processor in your IDE; see https://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation for the details. Note that Eclipse is notoriously bad (broken?) wrt annotation processing; it might be better to not run the processor in the editor as they call it (i.e. incrementally) and instead trigger a project build when you're done (that should –hopefully– be equivalent to the mvn process-classes), or you could just launch the mvn process-classes from within Eclipse.

    Note that I advise against launching mvn gwt:codeserver and mvn tomcat7:run from within Eclipse, as Eclipse hard-kills processes, which generally causes the CodeServer to stay alive (it's a forked process), and won't run your JVM shutdown hooks or ServletContextListener's contextDestroyed.