mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

  • Sunday, 8 September, 2013

    Grails: Using templates instead of Taglibs for rendering Views

    Assume we want to render a small box in HTML which can be closed with a button and contains some kinds of content. We could start with something like this:

    <div class='closeableBox'>
      <a class='closeButton' href='#'>close</a>
      <div class='content'>
        <ul>
          <li>first</li>
          <li>second</li>
        </ul>
      </div>
    </div>

    The content in this case is a simple list with two elements. However, we might want to use the box with the close button later for showing some other content. Obviously we don't want to repeat the code for the box in this case. The Grails way for doing this would be to write a TagLib function for this:

    class MyTagLib {
      
      static namespace = "my"
    
      def closeableBox = { attrs, body ->
        out <<   """ 
          <div class='closeableBox'>
            <a class='closeButton' href='#'>close</a>
            <div class='content'>
              ${ body() }
            </div>
          </div>
        """
      }
    }

    This tag could be used in the following way:

    <my:closeableBox>
      <ul>
        <li>first</li>
        <li>second</li>
      </ul>
    </my:closeableBox>

    Even with Groovy's multiline strings the mix of HTML and Groovy code in the TagLib is very ugly.
    To avoid HTML code within the TagLib the grails documentation suggests using a template:

    def closeableBox = { attrs, body ->
      out << render(template: "closeableBox", model: [content: body()])
    }
    

    The HTML part is moved into a template named _closeableBox.gsp. The body content is passed by the model variable content. The template code is shown in the following snippet:

    <div class='closeableBox'>
      <a class='closeButton' href='#'>close</a>
      <div class='content'>
        ${ content }
      </div>
    </div>
    

    This works fine. But wouldn't it be nice to do this without the TagLib function? There is indeed a way for doing this!

    With the <g:render /> tag it is possible to include templates within a GSP page. This is generally useful for partitioning a view into multiple smaller parts. Our example template can be included in another GSP file with the following line:

    <g:render template="closeableBox" model="${ [content: '...'] }" />

    The content that should be displayed in our box can be passed by using the model attribute of the <g:render /> tag. The obvious problem is that this way of passing data is very unhandy for passing larger pieces of HTML code.

    What the grails documentation doesn't tell you is that <g:render /> tags can have a body:

    <g:render template="closeableBox">
      <ul>
        <li>first</li>
        <li>second</li>
      </ul>
    </g:render>
    

    To render the body content in our template we can use the (unfortunately undocumented) body() function like in the TagLib. So, we have to modify the template like this:

    <div class='closeableBox'>
      <a class='closeButton' href='#'>close</a>
      <div class='content'>
        ${ body() }
      </div>
    </div>
    

    Finaly we no longer need the TagLib function for embedding body content to templates.

    An alternative way of rendering the template is using the tmpl namespace provided by Grails:

    <tmpl:closeableBox>
      <ul>
        <li>first</li>
        <li>second</li>
      </ul>
    </tmpl:closeableBox>
    

    This way also supports body content and is an equivalent solution to using the <g:render > tag.

  • Wednesday, 4 September, 2013

    Java Exceptions and generic types

    In this post I want to talk a bit about Java exception in combination with generic type parameters.The post is divided in two sections. The first one is about generic exceptions, the second one is about passing and throwing exceptions as generic type parameters.

    Generic classes are not allowed to subclass Throwable

    Let's look at the following code

    public class MyException<T> extends RuntimeException { // won't compile
    
    }
    

    This code won't compile because subclasses of Throwable cannot have a generic type parameter. RuntimeException subclasses Exception which again is a subclass of Throwable. So the compiler rejects this code.

    If you think a bit about this it makes sense. I cannot think of a useful way of catching generic exception.

    Let's assume for the moment the exception definition from above would be valid Java code. How would you throw and catch this exception?

    public void catchIt() {
      try {
        throwIt();
      } catch (MyException<String> e) {
        ..
      } catch (MyException<Integer> e) {
        ..
      } catch (MyException<?> e) {
        ..
      }
    }
    

    In order to make the generic type on the exception class useful it should be possible to create different catch blocks for different generic types. This however, is not possible because of type erasure. At runtime all the generic type information will be lost and MyException<String> will just be MyException. So there is no way for the Java runtime to decide which catch block should be executed.

    Additionally it would not be possible to generalize the type parameter in the catch block because Generics in Java are invariant. This means that MyException<Integer> cannot be assigned to MyException<Number> although Integer is a subclass of Number. Therefore, a MyException<Integer> could not be caught by defining a catch block with MyException<Number>.

    Be aware that this limitation also effects inner classes. The following code will produce a compile error:

    public class MyClass<T> {
      private class MyInnerException extends Exception { // won't compile    
        ..
      }
    }
    

    It is not possible to define a (non generic) exception class inside a generic class. This is a bit strange because the exception itself has no generic type parameter. I cannot think of a reason why this should cause problems (if you can, please tell me!). Making the inner class static solves the compile error.

    Generic type parameters can be thrown

    While exception are not allowed to contain generic type parameters it is perfectly fine to throw generic types (if they extend Throwable). The following code compiles fine:

    public <T extends Exception> void throwIt(T t) throws T {
      throw t;
    }  
    
    public void catchIt() {
      try {
        throwIt(new Exception());
      } catch (Exception e) {
        ..
      }
    }
    

    However, it is not possible to use generic type parameters in catch blocks. So the next snippet won't compile:

    public <T extends Exception> void throwIt(T t) throws T {
      throw t;
    }  
    
    public <T extends Exception> void catchIt(T t) {
      try {
        throwIt(t);    // fine
      } catch (T e) {  // compile error
        ..
      }
    }
    

    The reason for this is again type erasure.

  • Saturday, 31 August, 2013

    MongoDB: GridFS remove method deletes all files in bucket

    Some time ago we ran into strange behaviour of MongoDB's GridFS which caused me creating a Bug Ticket for the MongoDB Java driver.

    Today I found the link to the bug ticket in my browser bookmarks. The ticket isn't solved at the current time so I thought it would be worth a short blog post in case someone else runs into this problem.

    Let's look at the following simplified Java service:

    public class GridFsService {
    
      private GridFS gridFs;
      
      public void connect(String mongoDbHost, String databaseName) throws UnknownHostException {
        DB db = Mongo.connect(new DBAddress(mongoDbHost, databaseName));
        this.gridFs = new GridFS(db, "myBucket");
      }
      
      public void removeGridFsFile(String id) {
        GridFSDBFile file = this.gridFs.findOne(new ObjectId(id));
        this.gridFs.remove(file);
      }
      
      // .. other methods to create and update files
    }
    

    This service uses the MongoDB Java driver to create, update and remove files from GridFS.
    However, there is a serious flaw in the removeGridFsFile() method.
    Guess what happens if an invalid id is passed to removeGridFsFile().
    gridFs.findOne() returns null for non existent ids. So null is passed to gridFs.remove() which then removes all files in the current bucket.

    Fixing this is easy. Just add a null check or use another GridFS remove() method that takes an ObjectId instead of a GridFsDBFile:

    public void removeGridFsFile(String id) {
      this.gridFs.remove(new ObjectId(id));
    }

    Using this way everything works fine if an invalid id is passed to removeGridFsFile() (no file is removed).

    To make sure this won't happen again I tested what happens if null is passed to any of the three different remove() methods:

    gridFs.remove((String)null);      // nothing happens
    gridFs.remove((ObjectId)null);    // nothing happens
    gridFs.remove((DBObject)null);    // all files from bucket are removed

    I don't know if this is intended behaviour. The Javadoc comment for gridFs.remove(DBObject query) tells me that it removes all files matching the given query. However, if it is intended I think it should be clearly stated in the javadoc comment that passing null removes all files in the bucket.

  • Wednesday, 28 August, 2013

    Assigning boolean values in Groovy Server Pages (GSP)

    In my first blog post I want to point out a common pitfall for developers who are new to Groovy Server Pages (GSP).

    Today I found the following code construct within a GSP file:

    <g:set var="isAnchor" value="false" />
     ...
    <g:if test="${ isAnchor }">
     ...
    </g:if>

    Other than expected the condition of the <g:if /> tag always evaluates to true.
    The reason for this is that

    <g:set var="isAnchor" value="false" />

    assigns the string "false" to isAnchor and not the boolean value false. In Groovy a string (and GString) evaluates to true if it is not empty. "false" is not empty so the if condition always evaluates to true.
    This issue can easily be fixed by assigning a boolean value to isAnchor instead of a string:

    <g:set var="isAnchor" value="${ false }" />

    An alternative (but not so clean) solution would be to change the condition to

    <g:if test="${ isAnchor.toBoolean() }">

    The groovy string method toBoolean() converts the string value to a boolean value.

    The toBoolean() documentation says: If the trimmed string is "true", "y" or "1" (ignoring case) then the result is true otherwise it is false.

  • Tuesday, 13 August, 2013

    Yay, its live.. :-)

    I finally managed to setup my personal blog :-)
    In this blog I will write about programming topics mainly focused on Java (including JEE and Spring) and Groovy (including Grails).