20 Sep 2012, 1:32pm
gwt java:

13 comments




  • Anzeige
  • Using GWT’s DateTimeFormat in Server-Side Code

    I was work­ing on some util­ity class to for­mat dates. As the for­mat­ting is the same on server and client the same class should be used on both, server and client. Within the GWT frame­work there is the DateTimeFormat class which seems to be sup­posed to do exactly that.

    But despite being in the shared pack­age (com.google.gwt.i18n.shared.DateTimeFormat) using it in the server-side code causes

    java.lang.UnsupportedOperationException: ERROR: GWT.create() is only usable in client code!  It cannot be called, for example, from server code. If you are running a unit test, check that your test case extends GWTTestCase and that GWT.create() is not called from within an initializer or constructor.

    Hav­ing a look into the code of the DateTimeFormat class (which is part of the shared pack­age of the GWT frame­work, thus can be used on server and client) reveals there is an import of com.google.gwt.i18n.client.LocaleInfo. But this class is part of the client pack­age — thus, it can not be used in the server-side code. It’s unclear to me why this was done like that because it sim­ply can not work by definition…

    Going down a bit fur­ther in the code of the DateTimeFormat class shows that the client pack­age class LocaleInfo is used only once like this:

    private static DateTimeFormatInfo getDefaultDateTimeFormatInfo() {
      // MUSTFIX(jat): implement
      return LocaleInfo.getCurrentLocale().getDateTimeFormatInfo();
    }

    The line is marked as “MUSTFIX” but for some rea­son it has not been fixed yet.
    There is a way to fix this issue that worked for me:

    • Copy the con­tent of DateTimeFormat to a new file in your own code
    • Remove the import of LocaleInfo
    • Chang­ing the fol­low­ing method (start­ing in line 656) like this:
    private static DateTimeFormatInfo getDefaultDateTimeFormatInfo() {
      return new DefaultDateTimeFormatInfo();
    }
    • And use this newly cre­ated class from now on in all your code.

    The fix does not seem to cause any major harm, but as John A. Tam­plin (cf. his com­ment below) clearly pointed out, apply­ing this fix will ren­der all dates using the default locale instead of using the user’s locale. Thus, this fix should be con­sid­ered a hack rather than a patch — but it does the trick until the bug has been fixed officially.

    The hack can be applied quickly — or sim­ply down­load the fixed class here.

    p.s. Unfor­tu­nately, it is not pos­si­ble to just over­write the method in a derived class because it’s a sta­tic method and pri­vate any­way.
    p.p.s. As sug­gested in the com­ments, you might also ini­tial­ize the DateTimeFormat with a new DefaultDateTimeFormatInfo() as the sec­ond para­menter. (Please note that I did not ver­ify this sug­ges­tion) In gen­eral, both ways of fix­ing this issue will cause that the date and time to be for­mated using the default locale rather than the user’s cur­rent locale, unfortunately.

    15 May 2012, 12:08pm
    gwt java:

    3 comments




  • Anzeige
  • JUnit-Testing and GAE APIs

    Some issues I encoun­tered when test­ing a new Java library for load­ing mul­ti­ple URLs in par­al­lel on the Google Apps Engine (GAE) (more about that library in another post).

    Here are some of the typ­i­cal errors you might encounter:

    Miss­ing time­out class

    java.lang.NoSuchMethodError: org.mortbay.thread.Timeout

    Con­text menu on project: Prop­er­ties -> Build Path -> Order and Export: move GWT SDK *above* App Engine SDK (cf. here)

    Com­pi­la­tion unit was not seen

    com.google.gwt.junit.JUnitFatalLaunchException: The test class 'com.test.client.MyTest' was not found in module 'com.text.Module'; no compilation unit for that type was seen

    • The test class needs to be within a pack­age that is con­fig­ured in the mod­ule file (*.gwt.xml). You should cre­ate a new source folder (Con­text menu on project -> New -> Source Folder) and cre­ate the whole pack­age struc­ture you use within your project up to client, e.g. com.company.client, and put your GWT tests in it. This way you make sure that the tests are not going to be deployed to GAE later on.
    • If you are test­ing client-side code, your test class needs imple­ment GWTU­nit *and* be run as GWTU­nitTest *not* as JUnitTest ;)

    API pack­age not found

    java.util.concurrent.ExecutionException: com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'urlfetch' or call 'Fetch()' was not found.

    The GAE envi­ron­ment has not been initialized.

    • Set up the required libraries for testing:
      • Con­text menu on project -> Prop­er­ties -> Build Path -> Libraries -> Add Vari­able -> Con­fig­ure Vari­ables -> New…: Set “SDK_ROOT” as name and search you disk for “appengine-api-stubs.jar” and copy the part before “/lib/impl” into the text box named “Path”
      • Select “SDK_ROOT” from the pre­vi­ous dia­log, click “Extend…”, unfold lib and impl and select “…labs.jar”, “…stubs.jar”, and “…api.jar”; unfold “lib/testing” and select “…testing.jar” — done, whew.
    • Add fol­low­ing lines to your test class:
      private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalURLFetchServiceTestConfig());
      @Before public void setUp() { helper.setUp(); }
      @After public void tearDown() { helper.tearDown(); }
    • Have a look in com.google.appengine.tools.development.testing to see all the services/APIs avail­able for test­ing and replace LocalURLFetchServiceTestConfig with the one you need.

    I tried to keep it as brief as pos­si­ble, for more details have a look at this page.

    26 Apr 2012, 9:58am
    gwt java:

    leave a comment




  • Anzeige
  • Multiple Projects and GWT

    When work­ing on sev­eral large scale projects (in Eclipse), it’s con­ve­nient and of course more effi­cient to share and reuse code via com­mon libraries. While those are in an early stage they need to be changed a lot and there­fore it’s handy to link projects in instead of cre­at­ing new jars each time the library has been updated.
    Unfor­tu­nately, this stan­dard approach for Java devel­op­ment in Eclipse does not work that straight for­ward as with plain old Java projects, it requires three steps in total:

    1. Link the library project to all rel­e­vant projects (“Project Pref­er­ences” -> “Java Build Path” -> “Projects” -> “Add…”)
    2. Then, add the client-side code of the library (by adding it as a mod­ule.) There­fore, edit the gwt.xml of your appli­ca­tion and add for exam­ple <inherits name="net.svenbuschbeck.gwt.lib.SuperLib "/> where Super­Lib is the file name of the gwt.xml file in you library project and before that is the pack­age it lies in.
    3. Add the code to the project by link­ing a source folder. Unfor­tu­nately, this is required if you do not want to write an Ant script to com­pile your appli­ca­tion. (If you pre­fer Ant check this out) I don’t like the idea of using such a script because if you for­get to run it each time you make changes, you will end up in confusion—let’s go for the con­ve­nient, auto­matic way then.
      1. Add a folder to your appli­ca­tion project; open the “advanced” sec­tion in the folder cre­ation dia­log, select “Link to alter­nate loca­tion” and pick the source folder (usu­ally “src”) of your library project. (Hint: if you work within a team using a ver­sion­ing sys­tem, you can cre­ate a vari­able for that folder and use this instead. This way, each of your col­leagues can put the library project in a dif­fer­ent folder and accom­mo­date for that by adjust­ing the vari­able :) )
      2. Right click the folder, “Build Path” -> “Use as Source Folder”. Done.

    Sur­pris­ingly, the GWT plu­gin for Eclipse does not honor the project link­ing, thus all the ref­er­ences need to be made explicit or you will end up with lots of the fol­low­ing: ClassNotFoundException.

    31 Jan 2012, 10:53am
    gwt java javascript:

    leave a comment




  • Anzeige
  • An invalid or illegal string was specified” Exception in GWT

    While work­ing with can­vas (draw­ing stuff on it) in GWT, sud­denly and in a seem­ingly unpre­dictable man­ner I got fol­low­ing error mes­sage now and then from within the GWT frame­work code:

    com.google.gwt.core.client.JavaScriptException: (NS_ERROR_DOM_SYNTAX_ERR): An invalid or illegal string was specified;

    Again, GWT tricked me into think­ing I am writ­ing Java code and made me for­get about that it is going to be com­piled into Javascript. And because of the lat­ter, a divi­sion by zero does not throw an Devi­sion­ByZe­roEx­cep­tion, no, it returns NaN even for native data types (there is no dif­fer­en­ti­a­tion between dou­ble and Dou­ble in Javascript — there is only the object-version of dou­ble, which can be of value Double.NaN).

    But also GWT was not pre­pared to han­dle Double.NaN. When call­ing canvas.getContext().drawImage(image,x,y) and one of x and y or both were Double.NaN I got the error mes­sage shown above. If you got the same… you know what to do now: check all devi­sions in your code for poten­tial devi­sions by zero!!

    18 Jan 2012, 10:50am
    gwt java:

    leave a comment




  • Anzeige
  • Sorting Lists in GWT

    Quick one:
    Lists.sort(list, comparator) is not imple­mented in the GAE JVM.
    But, as a replacement/alternative, Collections.sort(list, comparator) is.

    28 Feb 2011, 11:10pm
    gwt java:

    leave a comment




  • Anzeige
  • How to Execute Code When the GWT Application Is Going Down

    My goal was to store the UI state of my appli­ca­tion just before it gets ter­mi­nated to be able to restore it next time the way the user left it the other day.

    I tried to add an addAttachHandler to the RootPanel to get informed about the root panel get­ting detached from the DOM so that I can final­ize my appli­ca­tion. Sur­pris­ingly, that does not work in Chrome (tested Chrome and Fire­fox only).

    But besides that this sounds like a bug to me, I found the “proper” way of doing things before the appli­ca­tion ends:

    Window.addWindowClosingHandler(new Window.ClosingHandler() {
    	@Override public void onWindowClosing(ClosingEvent event) { ... } 
    });

    In the end, I think some­thing like Document.addUnloadHandler would be more sug­ges­tive… clos­ing the win­dow or reload­ing a page is both exit­ing the appli­ca­tion by unload­ing the DOM — not clos­ing the window.

    7 Feb 2011, 2:58pm
    java:

    leave a comment




  • Anzeige
  • Java Cookies from the Future Past

    While work­ing with cook­ies in Java/GWT and thus—to set the expire date—with Date, I found a doubt­ful Java behavior.

    My goal was to set a cookie to expire in about one month from today like this:

    Date expires = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 30);
    Cookies.setCookie("myCookie", "myData", expires);

    And kept won­der­ing why the cookie never got stored.

    And finally cre­ated a sim­ple test case like this:

    Date today = new Date();
    Date tomorrow = new Date(today.getTime() + 1000 * 60 * 60 * 24);
    Date nextMonth = new Date(today.getTime() + 1000 * 60 * 60 * 24 * 30);

    And got fol­low­ing dates:

    today=Mon Feb 07 14:27:50 CET 2011
    tomorrow=Tue Feb 08 14:27:50 CET 2011
    nextMonth=Tue Jan 18 21:25:02 CET 2011

    Accord­ing to Java’s cal­cu­la­tion, the cookie was expired already before even being set.

    Took me a bit to under­stand why:
    1000 * 60 * 60 * 24 * 30 = 2,592,000,000 = 0x9A7EC800
    Thus, the first bit got set to one… a clas­si­cal over­flow caus­ing the inte­ger value to become neg­a­tive — just try:

    System.out.println(1000 * 60 * 60 * 24 * 30);

    It will print out -1702967296.

    Fix: Add a lit­tle L will solve the issue by forc­ing the com­piler to cal­cu­late using the scope of long:

    Date nextMonthLong = new Date(today.getTime() + 1000L * 60 * 60 * 24 * 30);

    I guess I will fall for that one again some­time as the error is not obvi­ous in my opin­ion — espe­cially because getTime() returns a long and still, the com­piler sticks with an int for the mul­ti­pli­ca­tion part.

    2 Feb 2011, 11:41pm
    java projects:

    leave a comment




  • Anzeige
  • Authentication with FlickrJ

    When you know about user­name and pass­word logins, the whole Flickr authen­ti­ca­tion process for web appli­ca­tions seems a lit­tle weird on first sight, nev­er­the­less it is log­i­cal and nec­es­sary after you have done some read­ing (for exam­ple the offi­cial Flickr WebApp Auth HowTo).
    To get started and into cod­ing quickly (using FlickrJ and Java) I rec­om­mend this page. Espe­cially the code exam­ple is excel­lent in my opin­ion! Thanks Andy Sacher!

    14 Dec 2010, 11:49am
    java:

    leave a comment




  • Anzeige
  • Casting collections in Java

    Assum­ing two classes A and B as

    class A {}
    class B extends A {}

    It is just log­i­cal that cast­ing B to A works fine:

    A anObjectOfClassA = new B();

    But when it comes to col­lec­tions of As and Bs, a strange phe­nom­e­non appears in Java:

    Collection<B> collectionOfBs = new LinkedList<B>();
    Collection<A> collectionOfAs = (Collection<A>)collectionOfBs; // this line does not compile!

    That is, though the col­lec­tion wrap­per (the java.util.Collection class) is the same and B extends A, cast­ing a col­lec­tion of objects of class B to a col­lec­tion of objects of class A throws an compile-time error.

    But it works using gener­ics (the whole class for the sake of com­plete­ness and reusability):

    import java.util.Collection;
    import java.util.LinkedList;
    
    public class CollectionCastingExample {
    
      class A {}
      class B extends A {}
    	
      Collection<B> collectionOfBs = new LinkedList<B>();
    //  Collection<A> collectionOfAs = (Collection<A>)collectionOfBs;
    	
      Collection<A> collectionOfAs = downCastCollection(collectionOfBs, A.class);
    	
      /**
       * Casts a collection of objects of class B where B extends A to a collection of objects of class A.
       * 
       * @param <T> Base class
       * @param collection Collection of objects of a class extending T 
       * @param aClass Representation of T
       * @return Collection of objects of T casted from given collection of objects of a class extending T.
       */
      @SuppressWarnings("unchecked")
      public static <T> Collection<T> downCastCollection(Collection<? extends T> collection,
          Class<T> aClass) {
        return (Collection<T>) collection;
      }
    }

    Despite the fact that a @SuppressWarnings("unchecked") is required, it avoids iter­at­ing over the whole col­lec­tion of Bs and cast­ing each of them from B to A plus adding them to a new col­lec­tion of As.

    17 Sep 2010, 3:49pm
    gwt java:

    leave a comment




  • Anzeige
  • Uploading File to Server: Access Denied

    Sim­ple task: upload a file to the server. Achieved so far: upload form works and the file gets trans­ferred to the server.
    But as soon as the file is writ­ten, I get one of that:
    “java.security.AccessControlException: access denied (java.io.FilePermission /some/folder/upload__71c20601_12b1b66bc39__7ffa_00000000.tmp write)“
    I am amazed how much search­ing is required to find some infor­ma­tion about how to mod­ify the file per­mis­sions for the local app engine! And in the end, it turns out that there is an issue with the GAE on Mac but with­out a way to con­fig­ure the local Jetty server to allow write access. :(
    As soon as I deploy the app to a Tom­cat on Linux, it works like a charm!