Using GWT - Atmosphere/atmosphere-extensions GitHub Wiki

Setting up your pom.xml

You will need the following dependencies to get started:

    <dependencies>
        <dependency>
            <groupId>org.atmosphere</groupId>
            <artifactId>atmosphere-gwt-client</artifactId>
            <version>{version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.atmosphere</groupId>
            <artifactId>atmosphere-gwt-server</artifactId>
            <version>{version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-user</artifactId>
            <version>2.4.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-servlet</artifactId>
            <version>2.4.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>

The atmosphere-gwt-client has scope provided because these Java classes will be transformed to javascript and are included into the resulting war package.You should select the slf4j package for the logging framework that you will use. Here we selected the jdk14 bridge for java.util.logging. You can define the following properties for convenience and we will refer to them in this document:

    <properties>
        <gwtModule>org.atmosphere.samples.GWTDemo</gwtModule>
        <gwt.compiler.force>false</gwt.compiler.force>
        <gwt.draftCompile>false</gwt.draftCompile>
        <gwt.style>OBF</gwt.style>
        <outputDir>${war.target}/WEB-INF/classes</outputDir>
    </properties>

<gwtModule> defines the basename and package of your main .gwt.xml file. So in the case of the gwt-demo it is located in src/main/resources/org/atmosphere/samples/GWTDemo.gwt.xml

Next you will need to define and configure the maven-gwt-plugin. This can be done in multiple ways, but what has worked well for the samples is the following:

    <build>
        <outputDirectory>${outputDir}</outputDirectory>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <version>${gwt-version}</version>
                <configuration>
                    <module>${gwtModule}</module>
                    <gwtVersion>${gwt-version}</gwtVersion>
                    <runTarget>http://localhost:8888/gwtDemo/gwtDemo.jsp</runTarget>
                    <noServer>false</noServer>
                    <sourcesOnPath>true</sourcesOnPath>
                    <hostedWebapp>${war.target}</hostedWebapp>
                </configuration>
                <executions>
                    <execution>
                        <configuration>
                            <extraJvmArgs>-Xmx512m</extraJvmArgs>
                        </configuration>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>${outputDir}</directory>
                        </fileset>
                        <fileset>
                            <directory>${war.target}/gwtDemo</directory>
                        </fileset>
                        <fileset>
                            <directory>${war.target}/WEB-INF/lib</directory>
                            <includes>
                                <include>*.jar</include>
                            </includes>
                        </fileset>
                        <fileset>
                            <directory>${war.target}/WEB-INF/deploy</directory>
                        </fileset>
                        <fileset>
                            <directory>${basedir}/src/main</directory>
                            <includes>
                                <directory>gwt-unitCache/**</directory>
                            </includes>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>

        </plugins>
    </build>

You will need to adapt this to your own project specifics.

Setting up your AtmosphereServlet

After setting up your AtmosphereServlet in your web.xml you will need to add the following init parameter to you servlet:

<init-param>
    <!-- prevent deadlocks -->
    <param-name>org.atmosphere.disableOnStateEvent</param-name>
    <param-value>true</param-value>
</init-param>

Which is described here Configuring Atmosphere using the web.xml Simply put: you are in trouble if you dont use this parameter :-)

Setting up your Handler

In order for the server to communicate with the GWT client properly you will need to install an AtmosphereHandler which is or derives from AtmosphereGwtHandler

Setting up your .gwt.xml

You will need to add the following to your .gwt.xml file apart from the usual stuff you need in there

<inherits name="org.atmosphere.gwt.Client"/>
<inherits name="com.google.gwt.logging.Logging"/>
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.popupHandler" value="DISABLED"/>

Of course you are free to setup the GWT logging differently.

Setting up your client code

To use the client you need to provide two classes. One is the serializer and the other is your listener. Lets start with the serializer. You basically inherit this one from AtmosphereGWTSerializer and use annotation to specify your needs.

@SerialTypes(value = {MyEvent.class})
public abstract class MySerializer extends AtmosphereGWTSerializer {
}

To create it for use in your client you do:

AtmosphereGWTSerializer s = GWT.create(MySerializer.class);

Next you will need to implement an AtmosphereListener and construct the url you need to connect to the AtmosphereServlet. These three, serializer, listener and url, allow you to construct the AtmosphereClient. Now all you need to do is call start() and you are on your way to receive events on the listener.

Where to go from here

Well you could explore the Javadoc and the Samples. Especially the samples will give you a better idea of what is possible.

It is possible to share connections between browser windows using AtmosphereProxy and there is a project atmosphere-gwt-js that allows you to use the generated GWT javascript in your own pure javascript application without having a dependeny on GWT. See the atmosphere-gwt-jsdemo for an example implementation.

Running the GWT shell while deployed in a JavaEE container of your choice

What you should do is specify true in the configuration of the maven-gwt-plugin and deploy the war to your tomcat server. After the war is deploy you should run "mvn gwt:run" and the shell will start without starting the build-in jetty. Now you type the url of your page that is hosted by tomcat and add "?gwt.codesvr=127.0.0.1:9997" to the url. This will redirect the javascript to the gwt shell.

Read more about the GWT Maven Plugin

Tips & Tricks

Spinning cursor in Chrome (Webkit) browsers

Try and start the client (AtmosphereClient.start()) [scheduleDeferred](http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/core/client/Scheduler.html#scheduleDeferred(com.google.gwt.core.client.Scheduler.ScheduledCommand\))

IE is not working properly

When you are using IE 8 or IE 9 the client code is setup by default to use the XDomainRequest Object. This can sometimes give problems. For instance cookies are not send so the client tries to put the session ID in the url. If you continue to have problems with IE 8 or IE 9 you could try to use the older transport mechanism based on the IFrame Comet technique for IE 6. To enable this transport you need to put this in your Module.gwt.xml:

<replace-with class="org.atmosphere.gwt.client.impl.IEHTMLFileCometTransport">
    <when-type-is class="org.atmosphere.gwt.client.impl.CometTransport"/>
    <any>
        <when-property-is name="user.agent" value="ie6"/>
        <when-property-is name="user.agent" value="ie8"/>
        <when-property-is name="user.agent" value="ie9"/>
    </any>
</replace-with>

Problems connecting with the Avira virus scanner

The problem is the avira antivir browser protection. This antivirus tool tries unsuccessfully to unpack the datastreams, whereupon the connection seems to be closed. The avira problem can be solved by either closing the browser protection tool of the virus software or there is possibility to exclude domains in the tool preferences settings. (Thanks to Sam Reciter)

Using a BroadcasterCache

As you can see in issue #14 the HeaderBroadcasterCache is not supported (yet) by the GWT module unfortunately. I think its probably easy, I just have not had time to do it. However other BroadcasterCache methods can work, like the SessionBroadcasterCache. We had build a custom BroadcasterCache on top of Atmosphere/GWT in our application which is able to filter and route information channels based on the class type of the objects that are sent. What we did was to give each message a unique number (which was just a serverside atomic integer) and this number would always increase not decrease. Then the client would store the number of each last message received. Whenever a new connection needed to be reestablished the lastMessageId would be send as an url parameter. Our custom cache would pick this up and send all the messages in the cache that have a message id higher than the lastMessageId.

TODO

  • Document the AtmosphereProxy
  • Document atmosphere-gwt-js
⚠️ **GitHub.com Fallback** ⚠️