implements Elegance {

// Elwyn Malethan's musings on software development, mountain biking and general navel–gazing...

Articles tagged with 'webdev'

The web needs better/more job titles

I‘ve just seen another job spec posted on line for a web developer job. It is supposedly for a developer, and yet in this advert they cite knowledge of PHP or MySQL as only being desirable, rather than required. The only required skills they do refer to are HTML and CSS.

Frankly, I think that assigning the title of developer to such a narrow role sells the profession of software development and the role of developer short by a country mile. The word developer is used to cover far too many roles. The term web developer is itself overloaded.

Let‘s look at the definition of a web developer from Wikipedia.

A web developer is a software developer or software engineer who is specifically engaged in the development of World Wide Web applications, or distributed network applications that are run over the HTTP from a web server to a web browser.

Let‘s look a little closer at what this says, ”a software developer or software engineer”. Ok, so a web developer is a software developer?

A software developer is a person or organization concerned with facets of the software development process wider than design and coding, a somewhat broader scope of computer programming or a specialty of project managing including some aspects of software product management.

Hmm… so a software developer is a big picture, multi-skilled kinda guy with a role or skills in multiple areas of the software development process. That doesn‘t sound like someone who‘ll just be interested in HTML and CSS, however challenging it is.

The age old building–a–house analogy

Would you call a plasterer an architect? Even if he was really, really good at plastering? Even if he was an absolute wizard plasterer, the best there was?

The answer is no, you wouldn‘t. You‘d give the plasterer due respect and full credit for the achievements in his profession. You may even be able to afford to hire him to plaster your house for you. You wouldn‘t dream of asking him to design it for you.

Similarly for all those HTML/CSS experts out there. Some of them are very, very good at what they do. Give them respect and due credit. Give them a job building your next site. Call them web builders or even page engineers. But don't call them developers.

First published on Dec 22, 2009. Last updated on: Dec 29, 2009.

How to catch GWT HorizontalSplitPanel double click event

I was using GWT's HorizontalSplitPanel. The thing is that it was a quite good solution but not everything I wanted. GWT standard widget–set is known for being on the Spartan side. I have no complaint about this, it is just a fact. The added behaviour I was after is the ability to double-click the splitter in order to toggle a fully collapsed or restored state. I'm not the only one, it seems.

This was not as straight–forward to achieve as I thought it would be. This is an account of the dead-end strategies I followed in trying to achieve this and the solution I settled on.

Inheritance strategy

My first (possibly lazy) approach was to use an inheritance strategy to extend HorizontalSplitPanel. Anyone whose familiar with the GWT standard widget set will know that this approach is a non–starter, since HorizontalSplitPanel is final so it can't be extended and — one step further up the class hierarchy — SplitPanel has package-local access so that can‘t be extended either (not in a class outside the same package in any event).

So of course, I put my best–practice hat back on to try and solve the problem properly.

Composition

So I used a SimplePanel as the base class for my widget as follows.

public class ElegantHorizSplitPanel extends SimplePanel {
    private String presetPosition;
    private HorizontalSplitPanel splitPanel;

    public ElegantHorizSplitPanel() {
        splitPanel = new HorizontalSplitPanel();
        this.add(splitPanel);
        setSplitPosition("30%");
    }

    public void setLeftWidget(Widget widget) {
        splitPanel.setLeftWidget(widget);
    }

    public void setRightWidget(Widget widget) {
        splitPanel.setRightWidget(widget);
    }

    public void setSplitPosition(String position) {
        presetPosition = position;
        splitPanel.setSplitPosition(position);
    }
}

This implementation does not support all the functionality provided by HorizontalSplitPanel — in fact it does nothing more than delegate what little functionality it does support directly to HorizontalSplitPanel. However, it provides enough detail to demonstrate the technique. The methods providing all the other functionality could be added fairly easily.

So now on to adding double-lick behaviour. To do this I needed to get a reference to the the splitter DOM element. Unfortunately — but probably for good reasons — the getter for this element is protected in HorizontalSplitPanel . So, this means we have to cheat a little. GWT exposes some of the DOM traversal JavaScript methods in the Widget API, so provided I could get hold of an element in splitter‘s ancestry somewhere there was hope.

I used Firebug to find out what HTML was generated by my new widget and found the following.

Illustration of the splitter DOM-element using Firebug

So in order to get a reference to the splitter element I need the element returned by:

this.getElement().getFirstChildElement().getFirstChildElement().getFirstChildElement().getNextSiblingElement()

But that – as we all know – is a what @unclebobmartin (and others) describes as a train wreck, so I added the following methods to ElegantHorizSplitPanel

public class ElegantHorizSplitPanel extends SimplePanel {

    // ...

    private Element getSplitterElement() {
        return getLeftElement().getNextSiblingElement();
    }

    private Element getLeftElement() {
        return getSplitPanelInnerElement().getFirstChildElement();
    }

    private Element getSplitPanelInnerElement() {
        return getSplitPanelOuterElement().getFirstChildElement();
    }

    private Element getSplitPanelOuterElement() {
        return getElement().getFirstChildElement();
    }

    // ...

}

Caveat: I checked IE HTML as well and it uses more or less the same HTML, though I suppose it's possible that compiling for different user agents could result in different HTML. I could probably add some test coverage for this using Matt Raible's guide to testing GWT libraries with Selenium, something to look into in future.

Adding double-click behaviour

I‘m more familiar with JavaScript and the DOM than I am GWT so my first approach to adding the behaviour was add native JavaScript code to attach the behaviour to the splitter element.

public class ElegantHorizSplitPanel extends SimplePanel {

    // ...

    private void toggleLeftPanel() {
        int leftWidth = getLeftElement().getClientWidth();
        if(leftWidth == 0) {
            splitPanel.setSplitPosition(presetPosition);
        } else {
            splitPanel.setSplitPosition("0px");
        }
    }

    private native void addBehaviour(Element splitter)/*-{
        var panel = this;
        splitter.ondblclick = function() {
            panel.@com.malethan.gwt.ui.widgets.client.ElegantHorizSplitPanel::toggleLeftPanel()()
        };
    }-*/;

    // ...

}

This actually works just fine in IE but is patchy in Firefox for some reason. But more importantly it introduces a reference cycle and is an almost guaranteed way to introduce a memory leak in most browsers.

Reference cycles & memory leaks.

Well, Google had already thought of that. They provide a standard, non–native way to add event handlers to DOM elements. So the actual code we use to add the double–click behaviour to the splitter element is the following:

public class ElegantHorizSplitPanel extends SimplePanel {

    // ...

    private  void addBehaviour(Element splitter) {
        Event.setEventListener(splitter, new EventListener() {
            public void onBrowserEvent(Event event) {
                if(event.getTypeInt() == Event.ONDBLCLICK) {
                    toggleLeftPanel();
                }
            }
        });
        Event.sinkEvents(splitter, Event.ONDBLCLICK);
    }

    // ...

}

N.B. When I started this post I had only tested the above technique in IE. It works great. Unfortunately it became quickly apparent that when I tried this in Firefox (running on Ubuntu Jaunty) it worked sporadically if at all. If anyone knows of a way to get this working in Firefox, please let me know and I'll post a correction.

First published on Nov 30, 2009. Last updated on: Dec 29, 2009.

Developers vs Designers fallacy

Someone I know and like personally and have enormous amount of respect for professionally, Mark Boulton, is currently embroiled in quite the developer vs designer shit–storm, which he mentions in this article. Mark is bang–on in everything he says here.

However, I‘m not going to write about some developer vs designer problem. I don‘t think there is such a problem between professional designers working with professional developers who all know how to communicate effectively and are working towards a common goal. This is more a rant about bad developers, with poor attitudes, giving the profession a bad name.

It all started when Mark mentioned on Twitter the poor semantic quality of the HTML produced by a popular Drupal module. Though I haven't read all of the responses to this, I gather much of them were from developers and were of the ad homonym, personal kind, rather than a reasoned argument against Mark‘s assertion that the HTML was shit (I‘m paraphrasing there, Mark said “beyond bad”).

One of the comments made by an alleged developer in response to Mark‘s blog post included this:

I don‘t know what “semantic html” even is. When I put HTML in my modules, I try to make sure there‘s enough divs that you can do everything with CSS and that stuff makes sense but I‘m not a designer and I‘m sure a designer would look at it and groan

What the F#@%!? Any web practitioner, designer or developer with any self respect should be surprised at that statement from someone who claims to be a web developer. Semantic HTML is HTML that has meaning, it is HTML that makes sense. Adding arbitrary divs just so the CSS is easier does not make sense, it‘s just pure lazy.

Irrespective of the nature of the debate, I‘m astounded that anyone is in any way in doubt as to the virtues of the semantic web. Is this 90‘s nostalgia or something!? Aside from the obvious SEO advantages, there is enhanced accessibility, a smaller footprint and increased portability – due to the separation of content (HTML) and style (CSS).

If there is any other argument against semantic HTML that isn‘t a variation of “I can‘t be arsed”, I haven‘t heard it.

First published on Sep 1, 2009. Last updated on: Dec 29, 2009.

Publishing in multiple Formats using SeemoreJ

I‘ve been really busy lately and have been neglecting my website and a bunch of other stuff besides. So this post is going to be brief.

... quite a lot more brief than that.

Formats made easy using SeemoreJ

You could also say, Rails-style.

In this post I‘m going to be talking about how SeemoreJ deals with deciding what format to present a resource in and how easy it is to display the same resource in multiple different formats.

The need for this was driven by my desire to provide a new feed for the articles on my website. That was straight forward and I just implemented a special case, which just spat out some XML and didn‘t forward on to a JSP view. This resulted in the following code for the list action.

BlogController.java (before)
package com.malethan.blog.app;

//...

public class BlogController {

    //...

    ArticlePager pager;

    //...

    @BeforeFilter(include = {"home", "list", "byCategory", "byMonth"})
    public void createPager() {
        pager = new ArticlePager();
        pager.setResultsPerPage(10);
        try {
            pager.setCurrentPageNumber(Integer.valueOf(request().getParameter("p")));
        } catch (NumberFormatException e) {
            pager.setCurrentPageNumber(1);
        }
        request().setAttribute("pager", pager);
    }

    @AfterFilter(include = {"home", "list", "byCategory", "byMonth"})
    public void initialisePager() {
        try {
            pager.initialise();
        } catch (Exception e) {
            log.error("Pager failed to initialise", e);
        }
    }

    //...

    public void list() {
        if ("html".equalsIgnoreCase(request().getParameter(FORMAT))) {
            request().setAttribute("sectionTitle", "All Articles");
        } else {
            try {
                Syndicate syndicate = new Syndicate(RequestUtil.getAppURL(request()));
                syndicate.syndicateBlog("atom_1.0", response().getWriter());
                renderNothing();
            } catch (IOException e) {
                log.error("Couldn't produce ATOM feed", e);
                renderView("404");
            }
        }
    }

    //...
}

A quick note on the BeforeFilter and AfterFilter annotated methods. These are a SeemoreJ feature that allow any arbitrary method to be invoked before and after any action. There'll be more on this in future posts.

Anyway, back to the subject at hand. The code above does the job but is not elegant. It did not please me to write it and it does not please me to look at it. It worked well enough and so this was the code for my site for a few months despite the fact that it did not really sit comfortably with me.

A better solution

I recently added SeemoreJ to ohloh. I'm not really sure what ohloh is or whether its going to be useful to me yet, or whether it has or will gain the critical mass of users to become a success. However, one of the features on there was to provide a news feed specifically for a project. So I figured I could just publish all the posts in the SeemoreJ category.

This article is in danger of becoming something far more verbose and – crucially – not at all brief. So I'll cut to the chase.

I have added a feature to SeemoreJ that allows easy customisation of what format to deliver a resource in. Navigate to http://www.malethan.com/all.html, you get a HTML. However, navigate to http://www.malethan.com/all.atom, you get XML. Atom XML to be precise.

This is achieved by having the view JSPs named in such a way that allows SeemoreJ to determine what format they represent. So I have a JSP called list.html.jsp for HTML and list.atom.jsp for Atom XML. Fans of Rails reading this will be familiar with the convention.

First, lets have a look at the relevant code in my controller class now. List is now a one–liner, specifying the title for the page/feed only.

BlogController.java (after)
package com.malethan.blog.app;

//...

public class BlogController {

    //...

    public void list() {
        request().setAttribute("sectionTitle", "All Articles");
    }

    //...
}

To deliver any resource with Atom I just need to create an appropriately named JSP and let it deliver the content. So I have the following view JSP for my Atom feed…

list.atom.jsp
<%@ page contentType="text/atom+xml;charset=UTF-8" language="java" %>
<%@ page import="com.malethan.blog.RequestUtil" %>
<%@ page import="com.malethan.blog.feed.Syndicate" %>
<%@ page import="com.malethan.blog.models.ArticlePager" %>

<%
    String title = request.getAttribute("sectionTitle") + " | implements Elegance { // Elwyn Malethan's Blog";
    ArticlePager pager = (ArticlePager) request.getAttribute("pager");
    Syndicate syndicate = new Syndicate(RequestUtil.getAppURL(request));
    syndicate.syndicateArticles("atom_1.0", response.getWriter(), pager.getResults(), title);
%>

... and this for the HTML

list.html.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/common/taglibs.jsp" %>

<html>
<head>
    <title><%@ include file="/WEB-INF/app/blog/_title.jsp" %></title>
</head>
<body>

<div id="content" class="wide">
    <c:if test="${empty(pager.results)}">
        <p>Your selection has resulted in a page with no articles. Perhaps you would like to look at
            <a href="/all.html">all of them</a>.</p>
    </c:if>
    <c:if test="${!empty(pager.results)}">
        <c:set var="blogPosts" value="${pager.results}" />
        <pager:pages pager="${pager}" />
        <%@ include file="_list.jsp" %>
        <pager:pages pager="${pager}" />
    </c:if>
</div>

</body>
</html>

So, as only somewhat briefly described, I can now syndicate SeemoreJ posts alone to ohloh. It also means that all the other categories and the archive is similarly published.

First published on Jul 6, 2009. Last updated on: Dec 29, 2009.

Self documenting software

Documenting requirements then implementing those requirements and then documenting that implementation is bad enough. Maintaining that documentation when requirements and implementation changes definitely makes documentation, generally a problem looking for a better solution. BDD to the rescue.

Not for a second am I suggesting that the necessary documentation shouldn‘t be produced or that it does not provide essential value to a project. What I am saying is that it should be easier and less laborious to produce. In an Agile environment it should also stay as close to the code as possible. Otherwise, it is likely to be out of date as soon as the first line of code is written.

Stories

When I was at Beanlogic, we covered most of our Ruby/Rails work with Rspec specs and stories. One handy outcome of running Rspec specs and stories is that a nicely formatted HTML document is generated that is readable to civilians. In fact in the case of stories, human–friendly prose actually translate into code coverage. Something we planned to do at the time was to make more use of this feature.

In order to tell good stories and for them to be most valuable to a project, the customer/owner of any project should be encouraged to produce structured stories with scenarios in a Given–When–Then format. This would of course be done in a supportive, collaborative way — perhaps via a wiki — since not all customers have the experience or skill–sets to work in such a prescribed way.

For example, a scenario that a customer operating a luxury holiday cottages website might – with the right guidance – produce the following scenario.

Given a user is searching for cottages
And they provide the search term 'fireplace'
When they perform the search
Then the results should contain all cottages with a fireplace

Obviously, this scenario would be split into finer–grained scenarios describing the lower–level implementation.

Using BDD (and Rspec in particular) in this way means the documentation is a by-product of the development process and is intrinsically linked to the code. This means that if requirement–creep leads to implementation changes, the documentation stays current.

Not only that, what we‘ve just done is managed to get our customer to write our top–level tests for us! Surely this is FTW!

I‘m never sure of the right context in which to use FTW or FAIL or other such intarwebz expressions. On the other hand, I‘m pretty sure I overuse WTF!

easyb

Given that I am ‘into‘ TDD, BDD, Agile and all that best–practice stuff (not everyone is); and given that I even navel–gazed about a possible Java implementation of Rspec's specs, I was shocked to find that easyb had completely flown under my radar until I stumbled upon it last week. Well, I feel like I‘ve only scratched the surface, but my initial impression is good.

I‘ll be furiously trying easyb out on testing this website and SeemoreJ in the next few days and I‘ll be posting my experience here.

First published on May 20, 2009. Last updated on: Dec 30, 2009.

Introducing SeemoreJ: Part #2 CRUD

In my last post about SeemoreJ I gave an account of how one might bootstrap a new web project using the seemorej–example–archetype. In this post I‘ll introduce how quick and easy it is to get a scaffolded CRUD application up and running.

I‘ll do this by stepping through the creation of the Person POJO (so pervasive in tutorials and demos), with Hibernate/JPA annotations as an example of a persistent model and – in the process we‘ll cover the default configuration of database interaction.

The model

Create a package called com.mycompany.model and add this class there.

package com.mycompany.model;

import org.hibernate.validator.NotEmpty;
import org.hibernate.validator.Email;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Entity
public class Person implements Serializable {

    private Long id;
    private String firstName;
    private String lastName;
    private Date dateOfBirth;
    private String emailAddress;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @NotEmpty
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @NotEmpty
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Temporal(TemporalType.DATE)
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    @NotEmpty
    @Email
    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }
}

There‘s a lot of annotation in this POJO. Some for JPA persistence and some for Hibernate Validator, which the Hibernate specific SeemoreJ package uses as the validation framework. We‘ll see shortly what these validation annotations do for us.

Persistence

Mapping

Add this line to hibernate.cfg.xml within the session-factory element.

<mapping class="com.mycompany.model.Person" />

Database connection

Now to configure the database connection. I‘m assuming you have MySQL installed and that this is what you‘re going to use. Find the following section in the POM (pom.xml) and change the values to something appropriate.

<!-- ... -->
    <properties>
        <!-- ... -->
        <hibernate.dialect>org.hibernate.dialect.MySQL5InnoDBDialect</hibernate.dialect>
        <jdbc.groupId>mysql</jdbc.groupId>
        <jdbc.artifactId>mysql-connector-java</jdbc.artifactId>
        <jdbc.version>5.0.5</jdbc.version>
        <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
        <jdbc.url>jdbc:mysql://localhost/myapp?createDatabaseIfNotExist=true&amp;amp;useUnicode=true&amp;amp;characterEncoding=utf-8</jdbc.url>
        <jdbc.username></jdbc.username>
        <jdbc.password></jdbc.password>
    </properties>
<!-- ... -->

CRUD Scaffold

Add the following class to the com.mycompany.app. Whilst this is a great deal more verbose than it would be in Rails, this is all you need to have CRUD functionality for a Hibernate mapped class. It certainly beats implementing each action required. My intention is replace this implementation inheritance with some sort of configuration, probably annotation. This would make the resulting controller classes more flexible and nicer to use.

package com.mycompany.app;

import com.malethan.seemorej.hibernate.crud.CrudControllerHibernate;
import com.mycompany.model.Person;

public class PeopleController extends CrudControllerHibernate<Person, Long> {
    public PeopleController() {
        super(Person.class, Long.class);
    }
}

Now start Jetty up using mvn jetty:run-exploded. If you‘re running it for the first time you‘ll have to wait for all the dependencies to download. Once it‘s up and running got to http://localhost:8080/people/list.html

What you‘ll see is a rudimentary, fairly ugly – if I‘m honest – CRUD application. On my To–do list is to make it more attractive and – through configuration – provide some customisation. Also, I‘d like to support one–to–many, many–to–many and many–to–one relationships.

In my next post about SeemoreJ I‘ll be talking about action filters and how they‘re implemented in SeemoreJ.

First published on Apr 30, 2009. Last updated on: Dec 30, 2009.

Introducing SeemoreJ: Part #1 Hello World

I've been mentioning SeemoreJ in passing for a while in my posts on here. I've mentioned that it is a yet another Java web framework and that it is inspired by my experiences working with Ruby on Rails and Merb (soon to be one and the same thing). Also, there‘s a link at the bottom of every page. So I think it‘s high time I stopped faffing. It‘s in a pretty reasonable state now so I think it‘s time to release it as an open–source project.

I hasten to add at this point that I am in no way under the illusion that SeemoreJ will become popular or attract (m)any users. I developed it because of my frustration with the verbose and heavyweight frameworks that were already available. I wanted to bring some of the simplicity and expressiveness that I experienced working with Ruby into my Java development.

Essentially, SeemoreJ allows me write web applications quickly, efficiently and pleasurably. That‘s my only motivation. If others find it useful or draw inspiration from it as well, that‘s a bonus.

Getting started

I think that one of the big facilitators in the uptake of rails is the easy bootstrapping of your fist project, this page makes it look friendly. So this section is going to be inspired by that page. Well... without all the pretty graphics...

Java

I‘ve been using Java 6 for my work. SeemoreJ will probably work with Java 5 just as well. Follow those links and follow the instructions for your platform.

Alternatively, if you have Ubuntu, like me, the following whould do the trick.

~$ sudo apt-get install sun-java6-jdk

Maven

Maven is a build management tool (like Make and Rake), which I think will completely replace Ant as the build tool of choice for most Java developers. Get the latest version here then follow the installation instructions for your platform. Alternatively, if your using Ubuntu, just type

~$ sudo apt-get install maven2

Then check Maven is installed by running mvn -v. You should see something like this.

~$ mvn -v
Maven version: 2.0.8
Java version: 1.6.0_06
OS name: "linux" version: "2.6.18-xenu" arch: "i386" Family: "unix"

Starter application (or archetype)

This is the Maven equivalent of running rails my_app. It‘s a little more verbose but we‘ll only ever have to do it once per project.

~$ mvn archetype:generate -DarchetypeCatalog=http://maven.malethan.com/repo/archetype-catalog.xml

Select seemorej-example-archetype from the list, this will probably be number 1, since I have no other archetypes there at the time of writing. Select a suitable groupId (e.g. com.mycompany) artifactId (e.g. myapp) and accept the defaults for the rest.

Now change into the project directory and type the following.

~/myproject$ mvn jetty:run-exploded

Then visit http://localhost:8080/index.html

Voila! You now have a running SeemoreJ application. Now let‘s have a look around the application source.

.
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- HelloController.java
    |   |-- resources
    |   |   |-- hibernate.cfg.xml
    |   |   |-- hibernate.properties
    |   |   `-- log4j.xml
    |   `-- webapp
    |       |-- WEB-INF
    |       |   |-- app
    |       |   |   |-- default
    |       |   |   |   `-- default.jsp
    |       |   |   `-- hello
    |       |   |       `-- world.jsp
    |       |   |-- common
    |       |   |   |-- _flash.jsp
    |       |   |   `-- taglibs.jsp
    |       |   |-- decorators
    |       |   |   `-- application.jsp
    |       |   |-- decorators.xml
    |       |   |-- urlrewrite.xml
    |       |   `-- web.xml
    |       |-- javascripts
    |       |   `-- prototype.js
    |       `-- stylesheets
    |           `-- application.css
    `-- production
        `-- resources
            `-- hibernate.properties

In my next post on the subject I‘ll show you how to set up a simple CRUD application, based on a Hibernate POJO. Also, at some point or other I‘ll create a project on Google Code, just in case anybody is interested in the source.

First published on Apr 22, 2009. Last updated on: Dec 30, 2009.

SeemoreJ

SeemoreJ is a lightweight MVC2 framework that I have developed as a pet project. This site runs on SeemoreJ, amongst other things. "Another one!?" I can imagine some people exclaiming. SeemoreJ is different, honest! I've developed a lot of apps using Struts 1 & 2 and I‘ve dabbled in some other Java-based MVC2 frameworks. They all have one thing in common. They‘re all terribly verbose and somewhat obese.

SeemoreJ is open–source and freely available under the LGPL on Google Code.

Verbose? Obese?

The one thing that strikes me with the majority of the popular Java web-frameworks is how much effort one has to go just to say “Hello World!”. The number of files that need creating because of how few assumptions are made is a real hindrance to a quick bootstrapping of a new project, Even one as simple as Hello World

I have also developed a number of apps using Rails and Merb. I have my issues with both of these but the one thing they are good at is allowing a developer to concisely and quickly build web applications. This is because that while these two frameworks aren‘t limited in their configurability (well, ActiveRecord is useless for legacy data and Rails more or less requires that you use it) they do make a lot of sensible assumptions that allow a developer to just get on with things. That is my main motivation in developing SeemoreJ.

I initially implemented Seemore in PHP just as an experiment, but quickly rediscovered why I hated developing in PHP (I had a job as a PHP developer for 2 years) so I ported it to Java. I've got a lot to do before it can be considered anywhere near a viable alternative to the current crop of MVC2 frameworks. I'm currently working on a simple annotation-based validation framework (I'm currently using Hibernate Validator for this) and automagic request to bean population, which will lead on to a make_resourceful-style autoCRUD and scaffolding. When I think it is worthy of public view I‘ll make it available for feedback and the critique of my peers.

As a quick illustration of how concise SeemoreJ allows one to be when developing web applications, below is an extract from the controller class for basic CRUD functionality.

package com.malethan.blog.app;

import com.malethan.seemorej.*;
import static com.malethan.seemorej.HttpMethod.*;
import static com.malethan.seemorej.SeemoreJ.request;
import static com.malethan.seemorej.SeemoreJ.response;
i
/* ... */

/**
 * <p>Controller for the website</p>
 */
public class BlogController {
    //----------------------------------------------------------------------- Filters

    @BeforeFilter()
    public void loadPageArtifacts() { /* ... */ }

    @BeforeFilter(include = "new")
    public void clearSesssion() { /* ... */ }

    //----------------------------------------------------------------------- Actions

    public void list() { /* ... */ }

    public void show() { /* ... */ }

    public void edit() { /* ... */ }

    @Accepts(method = POST)
    public void delete() { /* ... */ }

    @Accepts(method = POST)
    public void update() { /* ... */ }

    @Accepts(method = POST)
    public void create() { /* ... */ }

}

A controller is usually a POJO where each action is a public method. By default, a JSP view of the same name will be looked for to render for the action.

Common tasks that need to run before and after actions are configured using Annotations BeforeFilter and AfterFilter respectively.

An Accepts annotation can be used to limit the HTTP method allowed for a given action.

When I have some time I‘ll give a more comprehensive account of what SeemoreJ is and how it works.

First published on Nov 18, 2008. Last updated on: Dec 30, 2009.

 
People I like
Other sites