Deploy Tomcat Applications in Custom Directory

I have already written about how to change the directory of applications deployed in tomcat 7 by configuring the server.xml. However, there is an easier way to change the deployment directory using the tomcat manager.

  1. Deploy the WAR file using tomcat manager’s web upload feature (make sure to change the manager’s web.xml if you are deploying large applications in tomcat 7).

  1. Use the function “Deploy directory or WAR file located on server” to specify the desired context path for your application.

For this, you need to know the path of the ‘webapps’ directory, to which tomcat deploys applications by default.

Be sure to start the context path with a slash: eg /path/mydir rather than path/mydir

  1. Undeploy the original WAR file you have uploaded.

 

 

IdentityHashMap in Google Web Toolkit (GWT): String Identity

Problem

IdentityHashMap in Google Web Toolkit (2.2.0) JavaScript applications does not seem to work correctly, if String objects are used as key.

Source Code:

final IdentityHashMap<Object, List<String>> idsFromObjects = new IdentityHashMap<Object, List<String>>();

final String node1 = “Node 1”;

final String id = “value”;

final ArrayList<String> ids = new ArrayList<String>();

ids.add(id);

idsFromObjects.put(node1, ids);                    

final String node1b = new String(“Node 1”);

GWT.log(“Values: “+idsFromObjects.get(node1b));

GWT.log(“Contains key?: “+idsFromObjects.containsKey(node1b));

GWT.log(“Equals?: “+String.valueOf(node1b == node1));

Output (Hosted Mode):

Values: null

Contains Key?: false

Equals?: false

Output (Compiled JavaScript):

Values: [value]

Contains Key?: true

Equals?: true

Note: This problem does not exist in hosted mode.

Solution

It seems there is no direct solution. Since the identity test node1b == node1 shows that the two Strings are actually identical for JavaScript, this might be a feature of JavaScript. Maybe JavaScript is keeping track of all the strings created, and does not allocate new memory, when an identical string is created; unlike Java when using the constructor new String(…).

It also appears the Google Web Toolkit JRE emulation, keeps a kind of cache for String hash codes (see the class String.HashCache). A cache is even for their identity hash maps – see System.identityHashCode() in this commit). This might be a result on JavaScripts handling of strings.

However, it is unfortunate that in this scenario running code in GWT’s hosted mode leads to different results than running the compiled JavaScript.

A possible workaround is to wrap strings in a simple proxy.

public class StringNode {

private final String value;

public StringNode(String value) {

this.value = value;

}

}

Note: This class is not serializable for GWT RPC. See this post for possible workarounds for serialization for immutable objects.

Resources

Google Groups ‘IdentityHashMap emulation

SVN trunk IdentityHashMap

Commit Message Google Web Toolkit Trunk, Stable identity hash values for strings?

String.HashCache JavaDoc

String.HashCache Source (as part of class String)

GWT Issue 631: adding String “watch” to HashSet will break GWT application in Firefox

GWT Script does not load in Chrome and Internet Explorer

The Problem

GWT (Google Web Toolkit) allows compiling Java into JavaScript source. I like to use it to create client-only JavaScript applications (this can be very useful for testing purposes). The GWT compiler will place all the compiled JavaScript sources in your project directory and the applications can be tested by loading the created JavaScript in a web browser.

The path in the browser in this scenario will possibly look like: file://[path to your app]/[your app name].html

Unfortunately, in some instances such a local test might not work as expected.

In particular, one GWT script of mine worked fine in Firefox but would not work in Internet Explorer and Chrome. Internet Explorer warned “To help protect your security, Internet Explorer has restricted this webpage from running scripts”.

Chrome would simply only load the page HTML but none of the associated JavaScript scripts. Chrome’s JavaScript error console reported the error:

Unsafe JavaScript attempt to access frame with URL file:///M:/Eclipse/appGwtDemos/src/main/webapp/Demo01.html from frame with URL file:///M:/Eclipse/appGwtDemos/src/main/webapp/demo01/677DB6A2A0F1BFA4279679C7B43BEBEF.cache.html. Domains, protocols and ports must match.

The Solution

It appears that this error occurs due to special security restrictions imposed on webpages accessed as local files. Possible solutions are:

  • Deploy the application to a web server and access the script there.
  • Change the Chrome browsers security settings (I don’t know if there is a similar setting for Internet Explorer) (The flag is –allow-file-access-from-files)
  • Host a webserver on your local machine and dynamically link the contents of the folders, in which GWT compiles the JavaScript

Resources

“xsl stylesheet wrongly blocked, all on local drive” http://code.google.com/p/chromium/issues/detail?id=70088

“Unsafe JavaScript attempt to access frame with URL” http://code.google.com/p/chromium/issues/detail?id=31068

GWT setSize(): Do not use “inherit”

Widgets in GWT are essentially elements in the DOM tree of a web document. GWT widgets enable convenient control over these elements. For instance, a call of the widget method setSize(String width, String height) will set the dimensions of the HTML element underlying the widgets. Values to define the size can be anything allowed in HTML and CSS.

Possible values are:

  • “100px”
  • “50%”
  • “15em”
  • “auto”
  • “inherit”
  • Etc.

However, using convenience methods such as Widget.setSize() mindlessly can easily lead to serious bugs.

In particular, the code widget.setSize(“inherit”, “inherit”) will compile without errors or warnings. However, when loading the compiled JavaScript in Internet Explorer, a cryptic JavaScript error will occur. This is caused by Internet Explorer’s lack of support for the inheritance of attributes (also for font-size etc.).

Resources

How-to inherit CSS width attributes for Internet Explorer“, Kevin Deldycke’s blog

IE7 CSS inherit problem“, stackoverflow.com

Google I/O 2011 Google Web Toolkit (GWT) Sessions

It seems in the Session List for Google I/0 2011 there is no easy way to see all the Google Web Toolkit (GWT) sessions in one glance. So here is a quick overview:

GWT and Ui

GWT + HTML5: A web developers dream!, John Labanca

GWT + UI Designer: Enterprise Web UIs Made Easy!, Eric Clayberg

GWT Performance

High-performance GWT: best practices for writing smaller, faster apps, David Chandler

GWT Tooling

Fireside Chat with the GWT and Cloud Tooling Team, Ray Ryan, John Tamplin, Jaime Wren, Jason Rosenberg, Phil Quintslund, Stephanie Brubaker, Unnur Gretarsdottir, Bruce Johnson

Using GWT and Eclipse to Build Great Mobile Web Apps, Chris Ramsdale

Highly Productive GWT: Rapid Development with App Engine, Objectify, RequestFactory, and gwt-platform, David Chandler, Philippe Beaudoin, Jeff Schnitzer

GWT and Game Development

Kick-ass Game Programming with Google Web Toolkit, Ray Cromwell, Philip Rogers

Building Game Development Tools with App Engine, GWT, and WebGL, Lilli Thompson

 

Change the path of applications in Tomcat

Problem

It is quite easy to deploy application to a Tomcat instance using the Tomcat manager (usually accessible under the url /manager). However, by default the applications are available under a path equal to their WAR file name: e.g. an application ‘test_application.war’ would be available under the url ‘www.yourserver.com/test_application/’ (if your tomcat instance is hosted at the domain http://www.yourserver.com).

However, sometimes it is desirable to have more flexibility in the path under which applications can be accessed. For instance, if all test application should be grouped in the folder ‘test’ so be accessible at the addresses:

http://www.yourserver.com/test/test_application1/

http://www.yourserver.com/test/test_application2/

Best Solution

1. Use the WAR deployment function to upload the war file for your application to a non customized path (eg. myApp_0.2.1)

2. Use the Deploy Directory function (located above deploy war) to re-deploy your application. For this you need to know the path to your Tomcat webapps folder on your server (e.g. /usr/share/tomcat7/webapps)

Context Path: [your custom path] eg ‘/custom/myApp_0.2.1’

XML Configuration File: [Leave empty]

WAR or Directory URL: [path to your tomcat webappsfolder + name of initially deployed war] eg ‘/usr/share/tomcat7/webapps/myApp_0.2.1’

Another Solution

One quite simple solution is to define manual entries in tomcat’s server.xml for the applications, which should be accessible under custom paths. The following steps describe this solution:

  • Manually copy your applications to a location in your local driver other than a sub-directory of {yourtomcat}/webapps: e.g. copy from usr/share/tomcat/webapps/test_application1 to /var/www/test_application1
  • Open the server.xml in the tomcat/conf directory
  • Add the following statement within an appropriate <Host> element (e.g. the virtual host for http://www.yourserver.com)

<Context path=”/tests/test_application1″ docBase=”/var/www/test_application1/”

debug=”0″ reloadable=”true” crossContext=”false”>

</Context>

Alternative Solutions

Alternatively, you can define a proxy or url rewrite in an Apache server instance.

Test Environment

Tomcat 7.0.12

Resources

Apache Tomcat Configuration Reference: The Context Container

Tutorial “Change the context path of your web application

JavaRanch “How to change url(context-root) of a web application?