News from May, 2008

  2008/05/07
SpringSource Application Platform
Labels: spring, springsource

let's watch this OSGi based platform.

posted in response of Timurs forwarded springsource.com newsletter 01.05.2008:

-----------------------------
SpringSource Application Platform
-----------------------------
Yesterday was a very big day for Spring and for the Java community. The attached press release describes the launch of the SpringSource Application Platform. The SpringSource Application Platform is a next-generation, completely module-based application server which provides vastly improved capabilities for both developers and for operations staff. The SpringSource Application Platform adheres to the Spring principles of power through simplicity and harnesses the power of Spring, Tomcat and OSGi to provide a next generation server architecture.

We hope you will share in our excitement. Please stay tuned to the press and blogosphere over the next few days as this new chapter in Enterprise Java unfolds.
Please download the Application Platform beta at: http://www.springsource.com/beta/s2ap/membershipform.php

More information can be found here:

Posted at 07 May @ 11:49 AM by Oliver Wihler | 0 Comments
  2008/05/09
Spring MVC 2.5, binding collection elements and a bottle of Bud in hand
Last changed: Jul 29, 2008 13:51 by Oliver Wihler
Labels: spring, mvc, binding

Okay, I finally got to write this — it's really been a while since I actually faced this problem, a couple of months or so. And it's also been a while since me posting any furious rant in the blog, so here you go .

WARNING 1: This column describes a probably uncommon pitfall when binding collection elements in Spring MVC 2.5, but a rather nasty one, so you are better off reading it, trust me.
WARNING 2: A whole bunch of code examples follows!
WARNING 3: This might be a bit too much for an unprepared reader, so go get your sandwich first

I hope everyone who has worked with Spring MVC has succeeded in binding collection elements at one point. Let's jump straight to an example — suppose, you have the following class which you use to construct your command object for a form controller:

public final class Thing extends AbstractEntity {

  private static final long serialVersionUID = 1L;

  @SuppressWarnings("unchecked")
  public Thing() {
    // let's pretend we have an implementation of the ElementFactory interface
    // which constructs Stuff objects and sets the Thing reference to this
    stuff = new AutoPopulatingList(new StuffFactory(this));
  }
  
  private List<Stuff> stuff;

  public List<Stuff> getStuff() {
    return stuff;
  }

  public void setStuff(final List<Stuff> stuff) {
    this.stuff = stuff;
  }

  // some extra valuable fields and methods reside here

}

And now for the Stuff class:

public final class Stuff extends AbstractEntity {

  private static final long serialVersionUID = 1L;

  private Thing thing;

  private String value;

  public Thing getThing() {
    return thing;
  }

  public void setThing(final Thing thing) {
    this.thing = thing;
  }

  public String getValue() {
    return value;
  }

  public void setValue(final String value) {
    this.value = value;
  }

}

Damn, why is there no code auto-completion in Confluence?

Let's say, we have your plain vanilla ManageThingsController which you use to both add and edit Thing objects.

A part of the JSP view for this controller could look something like this:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<div class="form">
  <form:form commandName="thing" method="post">
    <div>
      <span class="label">Stuff #1</span>
      <span class="field">
        <form:input path="stuff[0].value"/>
      </span>
    </div>
    <div>
      <span class="label">Stuff #2</span>
      <span class="field">
        <form:input path="stuff[1].value"/>
      </span>
    </div>
    <div>
      <span class="label">Stuff #3</span>
      <span class="field">
        <form:input path="stuff[2].value"/>
      </span>
    </div>
  </form:form>
</div>

<c:if test="${not empty things}">
  <c:forEach var="t" items="${things}">
    <div>
      <td><a href="?id=${t.id}">Edit thing with id #${t.id}</a></td><!-- Do not try this at home -->
    </div>
  </c:forEach>
</c:if>

Phew, I'm tired of writing code here. Anyway, so far so good. Now let's have a look at our controller implementation:

@Controller
public final class ManageThingsController {

  private static final String COMMAND_NAME = "thing";

  // for simplicity's sake I'll just define views here manually,
  // normally you wouldn't do that

  private final String formView = "manageThings";

  private final String successView = "redirect:manageThings";

  private final ThingService thingService;

  @Autowired
  public ManageThingsController(final ThingService thingService) {
    this.thingService = thingService;
  }

  @SuppressWarnings("unused")
  @RequestMapping(method = RequestMethod.GET)
  public String setupForm(@ModelAttribute(COMMAND_NAME) final Thing thing) {
    return formView;
  }

  @RequestMapping(method = RequestMethod.POST)
  public String processSubmit(@ModelAttribute(COMMAND_NAME) final Thing thing) {
    thingService.save(thing);
    return successView;
  }

  @ModelAttribute(COMMAND_NAME)
  public Thing createCommand(@RequestParam(value = "id", required = false) final Integer id) {
    return (id == null) ? new Thing() : thingService.find(id); // normally you wouldn't do this either, but rather 
delegate this to a facade or smth, but "normally" doesn't apply here, sorry
  }

  // one more method will be here shortly

}

So far so good. The only thing remaining is the method to find all Thing objects (so we could click the "edit" link on page). How could you do that? I guess, you would first load all Thing instances from the data storage. Then I would normally just check in the view for the "id" request parameter and not render the element being edited in the table which contains all elements. But for this example we'll do it (intentionally!) differently: we'll remove the Thing which is currently being edited (if indeed there is such an object, i.e. it's not a new instance being added) in the controller. Let's try it this way:

// let's conveniently pass our command object there as a parameter

@ModelAttribute("things")
public List<Thing> getThings(@ModelAttribute(COMMAND_NAME) final Thing thing) {
  List<Thing> things = thingService.findAll();

  if (!thing.isNew) {
    things.remove(thing); // this might even work ;D
  }

  return things;
}

Looks real enough. But is just won't work properly in this particular case, uh-uh, i.e. when we are to bind some collection elements like that. And you will wind up with a weird ArrayIndexOutOfBoundsException on submitting the form, that's right: when the form gets loaded, the collection elements will be present there, in the command object! But when submitting, they will just disappear (I don't remember the details of my debugging it, but they were not pleasant) and you will be screwed. This is really not the situation you would want to get yourself into, so just let me remain the only moron I know to have faced this problem and struggled with it for hours and just do it the right way from the beginning:

@ModelAttribute("things")
public List<Thing> getThings(@RequestParam(value = "id", required = false) final Integer id) {
  List<Thing> things = thingService.findAll();

  if (id != null) {
    for (Iterator<Thing> i = things.iterator(); i.hasNext();) {
      if (id.equals(i.next().getId())) {
        i.remove();
        break;
      }
    }
  }

  return things;
}

And now you are yet another one happy developer. The sun is shining and you can relax and ponder on something that matters, instead of debugging this <censored> crap.

By the way, if anyone can provide any insight on this, e.g. maybe my trying of using a @ModelAttribute inside another @ModelAttribute declaration was wrong from the beginning. The funny thing was that it works fine for any binding other than collection elements. Either my or Spring MVC bug? Don't know, but you might find out someday .

Posted at 09 May @ 11:44 PM by Timur Strekalov | 3 Comments
  2008/05/29
GWT JUnit tests + Linux server
Last changed: May 29, 2008 15:11 by Timur Strekalov
Labels: gwt, ant, testing, linux, cruisecontrol

I really feel like sharing this with the world, because it has been an excruciating pain in the butt to get these to work.

Anyone having downloaded a GWT package for Linux might have noticed that it includes the Mozilla browser — it seems that GWT needs a browser to run its tests, and while on a Windows machine it can safely assume IE is installed, on Linux it cannot. Hence the browser in the package. As of GWT 1.4.61, you need the following Linux-specific stuff (in addition to any other which is platform-independent) on your classpath to run GWT tests on a Linux machine:

  • gwt-dev-linux.jar;
  • the mozilla-* directory;
  • all libswt-*.so Linux shared libraries;
  • mozilla-hosted-browser.conf

All this comes with the package, but there are many things you don't need (e.g. docs), so it's your call whether to choose the needed files or just put the whole bunch on your classpath.

If you have troubles when running GWT unit tests with Ant, like, for example, a "[junit] Tests FAILED (crashed)" message, you might want to turn output on to see the details (by switching the showoutput attribute of the junit task to "true") — I had this off for quite a while, and it turned out that GWT had been outputting a message that I didn't see

GWT doesn't support 64-bit libraries yet, so forget about running those tests on a 64-bit Linux machine (we tried this on siil — believe me, you don't want to). Period.

There's another pitfall while executing GWT tests on a dedicated Linux server. GWT requires a display (don't ask) to be registered, thus while you will be safe with a workstation which does have a display by default, it's not the same with a server machine. Thus we have to emulate this behaviour, with an easy and efficient way of doing this being executing the following lines before launching the Ant target:

Xvfb :1 -ac -screen 0 1024x768x8 &
export DISPLAY=:1

For those who don't know what Xvfb is about, here's a link.

So if you're running CruiseControl, a good idea might be to put these lines in your cruisecontrol.sh file (don't forget to kill the Xvfb process if you shut CruiseControl down).

That's all, folks ©
Happy testing.

Posted at 29 May @ 2:52 PM by Timur Strekalov | 0 Comments
Integer.toString(i) vs "" + i

I must say I am surprised to see people using indirect conversion of integers to strings. Not only it looks bad to me, but simple tests show that it's inefficient.

In short: use Integer.toString(int), for God's sake!

Posted at 29 May @ 4:09 PM by Timur Strekalov | 0 Comments