views:

1303

answers:

3

Trying to avoid re-inventing the wheel here. I have a Google Web Toolkit page that I'm preparing to deploy, but the webservice that I'm communicating with will have a different relative address on the deployed server than my local test machine.

As such, I'm looking for a simple way to deploy with some sort of easily editable configuration file that I can put basic settings in server side. I have a couple of ideas about how to do that, but they seem somewhat hacky and it seems to me like there must already be a solution for this kind of problem (after all, per-server settings are a VERY common thing!)

Any ideas?

Edit: Since this doesn't seem to be attracting much attention, let me outline my initial thoughts: Store a static file local to the GWT files that I query with an AJAX call before any other logic. When the file is returned I parse out my data and store them as globally accessible vars, then allow the page building logic to run. Seems clunky, and there's the big downside of waiting for the AJAX to return before any loading, but it would work. Any better suggestions? (Please?)

My Solution: I've found a solution on my own, but it's pretty specific to my exact scenario so I don't know how useful it would be to the general user. I'll post it here anyway on the off chance that someone finds it useful.

The page I am working on is actually a GWT control embedded in a ASP.net site. Taking advantage of this, and my discovery of the GWT Dictionary class, I put together a "settings" system like this:

First, the setting I want (in this case an address to a webservice) is set in the ASP.net Web.Config file

<appSettings>
    <add key="serviceUrl" value="http://mySite.com/myService.asmx"/&gt;
</appSettings>

In the ASP page that's embedding the GWT control, I add a "static" javascript object that contains the config settings I need:

<head runat="server">
    <title>Picklist Manager</title>

    <script type="text/javascript" language="javascript">
        var AppConfig = {
            serviceUrl: "<%= ConfigurationManager.AppSettings["serviceUrl"] %>"
        };
    </script>
    <script type="text/javascript" language="javascript" src="gwtcontrol.nocache.js"></script> <!-- Include my GWT control -->
</head>

Finally, in GWT I create a static "AppConfig" class that exposes this setting like so:

public class AppConfig {
    public static String serviceUrl = "defaultUrl";

    public static void Initialize() {
        Dictionary appConfig = Dictionary.getDictionary("AppConfig");
        if(appConfig == null) { return; }

        servicePath = appConfig.get("serviceUrl");
    }
}

From there I can call AppConfig.serviceUrl anywhere in my code to get the setting... whew! So yeah, that's a nice long complicated way of going about it but it works for me. Of the answers given Alexander's seems most inline with what I was looking for, so the bounty goes to him, but thank you to everyone who pitched in on my sticky little problem!

+1  A: 

The easiest way seems to be storing this configuration information someplace accessible to the server code, i.e. your ServiceImpl classes.

You have multiple options for that, typically:

  • set an environment variable;
  • set a system property;
  • place a property file in the classpath;
  • look up a JNDI bean.
Robert Munteanu
+1  A: 

Feel free to correct me but it doesn't seem like you require run-time server side configuration. In the case you really need that flexibility or you want to use a single .zip for all deployments you could use the technique given in Yahoo's Performance Rules - (see the section 'Add an Expires or a Cache-Control Header)' - far future expires headers. This means that the AJAX request would be cached heavily by the browser and only cause a minor slowdown on the first request.

Rather than doing this I'd actually suggest using compile time flags and the property system that GWT offers. To simplify doing this I've made a small package called auto-config available on github. Using this makes accessing per deployment configuration very simple. Add the following class:

public interface MyConfiguration extends AutoConfiguration {
    public String getFoobar();
}

To access the value from the GWT code add this simple helper:

private MyConfiguration getMyConfiguration() {
    return (MyConfiguration) GWT.create(MyConfiguration.class);
}

Create several different .gwt.xml files, one for each deployment server. Then minimize any duplication by using a parent .gwt.xml file. For more information on this topic read CompileOnePermutation on the GWT Wiki

In summary, add the following snippet to your per-deployment .gwt.xml's (and make sure to add the needed inherits line):

  • <set-configuration-property name="foobar" value="whee1234" />

Hope to have helped :)

Alexander Kellett
Your second link worked :) I think the first one is just formatted funny, but it gets the point across. I'll be looking into this method...
Toji
Wow... that IS a fairly complicated example. I'm not sure which part of it I should be looking at. I get that the PropertyOracle is something I get through a Generator, but what does the Generator do for me, and how would I use it? I'm normally pretty good with reading these things, but I feel like I'm lacking a lot of context in this case. :(
Toji
I need this anyway for a project so I'll dig into it now.
Alexander Kellett
All done. Cleaning up, will place on github shortly.
Alexander Kellett
Hey Toji. Have a repo up for the code now: http://github.com/zinf/gwt-autoconfig
Alexander Kellett
+1  A: 

I'm a little confused about what you're asking for.

If what you want is to compile once, and run the GWT app on different servers with different options, and have the options be used client-side during the GUI building, there are a bunch of options.

Get the info into your program using:

  • Environment variable
  • System property
  • Etc

Get the info to your client-side by:

  • AJAX call to file (as you specified)
  • Serve up your GUI from a JSP instead of a static HTML. Have the JSP embed the info in a JS variable, which your GUI can access using a JSNI call. This saves you a round-trip.
Steve Armstrong