10.25.2006

added: Emmanuel's Development References search engine

I've just created a new search engine using Google Coop. You can start using it on by entering search terms on the search box on the right.

You may also add it to your browser's (Firefox 2.0 or IE 7) search engines.

This search engine is customized to search Java, Ruby, Rails, Hibernate and Spring Framework API and reference documentation. More API and reference documentation for things that are in my area of interest will be added in the future.

10.19.2006

JSR-277: At last... a module system for Java!

The early draft for JSR-277 has been made available. This is good news! We will have a module system for Java. Its a bit late in the game... Ruby has a module system (GEM), Perl has CPAN, Linux has many... Why did it take so long to have one for Java? Maybe it did not itch that many people. But then why would the Maven team choose to create a repository for dependencies management, it must have itch!

I did a quick read of the specification... And here are my first reaction :
  1. Great! A module system for Java... At last, Java application will be easier to install and we will have a dependable versioning system,
  2. Why do I need to specify in the module definition all the classes that are present in the module? Maybe I did not understand the value of the "members" definition, but I guess that everything inside a module should be a module member. I see no reason to duplicate that information,
  3. I could say the same thin about the "class-exports". Why does the module system need this? It could use class visibility modifiers to do the same thing. I can see a bit of value if it was there to suggest the main entry points and/or API of the module. It should be optional,
  4. There is no use cases on how to install and manage existing module using tools. The specification says that it does not specify any tools. I believe that local repository management tools are a must and should be provided and made standard. At least a command-line tool should be specified. Just like we have a standard specification for using the "java" command even if it has implementation specific options.
Overall, I think this is great news. It does come a bit late and will not be available unto Java 7. But this will still be a great improvement over the current situation.

10.18.2006

Ant without the XML

Yet Another Build Framework was announced today on The Server Side. Gosling is much like Ant (according to the website, it's a fork of Ant) but without the XML. For a start, this is good news. Instead of using XML, you use Java to code your build script.

Do we really need another build framework? Sure writing build script in XML is not very convenient and has its limitations. But we have Maven2. Maven2 is still XML, but it is not build script that you write in XML, it's just your project configuration. Maven2 is the perfect implementation of DRY for your build script. After more than 10 years of Java existence, why would one still have to write in is build script the steps required to produce a JAR file?

Does this mean that Gosling has no future? No! I think it's very nice to have an alternative to Ant to create build script (for those who don't like Maven2 very much). I also think that this would be a nice framework to create build task for Maven2. Because you are using code to create your build script, you can use a debugger to debug them. In that respect, it's much better than Ant and Maven2. I imagine, it would also possible to write libraries of tasks that could be downloaded on the fly (using dependency management) to be able to actually not repeat yourself.

Right now, this framework requires Java6. This is not a very good idea to drive adoption, Java5 and even Java 1.5 should be supported.

But the feature I would want the most for this project would be to be able to write my build script in a scripting language. Be it Ruby (with the help of JRuby) and/or Groovy! That would be much better than XML :-)



10.10.2006

re Otaku, Cedric's weblog: FireFox 2: Please fix this before it's too late

In a recent post Cedric complains about changes in the behaviour and layout of Firefox tabs. I find this a bit amusing... First the behaviour and layout is not that different from the past. And I don't really think its worth a post outside of the developer mailing list. For my part, I like the way the close button is now positionned as in my Firefox 1.5 configuration (using the Tab Mix Plus plugin), my tabs close button is already there.

But what I found amusing is the irony...

Cedrics works for Google... And recently, Google made a complete redesign of  Google Reader. Without any warnings and by changing a lot of stuff (and making several usability mistakes). I guess that Cedric is not working for the Google Reader team. We just have to follow The new user interface thread on Google Groups to see, that this was a much bigger usability blunder than the Firefox 2 one.

The good thing about these two blunders... is that for Google Reader, you can revert back to the old interface if you want to (at least for now) and you can change some Firefox 2 settings to get the old behaviour!


9.22.2006

The simplest thing to do...

I have been living in the Java world for a long time now. In this world full of patterns, complicated API and well intentionend flexible frameworks, we do not always follow the simplest path to a solution.

I'm currently working on adding some functionnality to an application that we wrote for a client last year. This application written in Java using JSF/Facelets/Spring/Hibernate and running on Tomcat.

For the new functionnality, I wish to move information from page to page but I don't want them to stay in the session for long. I also don't want to explicitely have to remove explicitely these object from the session. Now I could use request scope attributes to do that, but then if I choose to do a redirect instead of a forward, I will loose the information. I could also go with a more complicated option of using Spring WebFlow (or something similar). But I don't want to another layer and more configuration files.

In the weeks before starting this new project, I wrote some application using Ruby on Rails. The philosophy behind this framework is very different than the philosophy behind most Java frameworks. Here the DRY (Don't Repeat Yourself) principle is king. This contrast a lot with the stack I'm using as I have to define information about my controller, pages, beans in multiple places.

One of the concept I found useful in Rails is the Flash. The Flash is a hash structure like the session but it retains objects up to the end of the next request. It's a bit like the request scope with the added benefit of surving redirects.

So I thought, why not implement this in Java. For my Java implementation, I choose not to implement the "now" operation that is present in Rails as I did not really needed it. I also use a filter to do the management of the Flash.

This simple solution allow me to pass objects from page to page without having to polute the session to much. It has the benefit of allowing request-like scope to survive redirects. The current implementation may not work well with Ajax requests (I use Ajax4JSF and I have yet to find a way to differenciate Ajax request from normal requests, so the objects will be purge when doing an Ajax request unless I explicitely retain them when processing the Ajax request).

So here is the code (the two classes must be in the same package). Note that you can customize the Filter mapping to suits your particular needs.

Flash.java
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class Flash extends HashMap<String, Object> implements Serializable {
    private Map<String, Integer> time2live= new HashMap<String,    Integer>();
   
    @Override
    public Object put(String key, Object value) {
        time2live.put (key, 1);
        return super.put(key, value);
    }
   
    public Flash keep(String key) {
        if (containsKey(key)) {
            time2live.put(key, 1);
        }
        return this;
    }
   
    public Flash keep() {
        for (Map.Entry<String, Integer> entry : time2live.entrySet()) {
            entry.setValue(1);
        }
        return this;
    }
   
    public Flash discard(String key) {
        if (containsKey(key)) {
            time2live.put(key, 0);
        }
        return this;
    }
   
    public Flash discard() {
        for (Map.Entry<String, Integer> entry : time2live.entrySet()) {
            entry.setValue(0);
        }
        return this;
    }
   
    void manageFlash()  {
        for (Iterator<Map.Entry<String, Integer>> entries= time2live.entrySet().iterator(); entries.hasNext();) {
            Map.Entry<String, Integer> entry= entries.next();
            if (entry.getValue() == 0) {
                entries.remove();
                remove(entry.getKey ());
            } else {
                entry.setValue(entry.getValue()-1);
            }
        }
    }
}

FlashFilter.java
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest ;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * @web.filter name="FlashFilter" display-name="Flash Filter"
 * @web.filter-mapping url-pattern="*.html"
*/
public class FlashFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest= (HttpServletRequest)request;
       
        Flash flash= (Flash) httpRequest.getSession(true).getAttribute("flash");
        if (flash == null) {
            flash= new Flash();
            httpRequest.getSession().setAttribute("flash", flash);
        }
        flash.manageFlash();
       
        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }
}


AdSense Links