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.

    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!