Looking for a Web App Generation Tool

I’m looking for a tool that makes it astonishingly easy to generate a web app that facilitates the editing of the contents of a bunch of database tables. Details follow…

I’m looking for a tool that makes it astonishingly easy to generate a web app that facilitates the editing of the contents of a bunch of database tables. I want to specify:

  • which tables to allow editing (and viewing)
  • which fields to allow editing (and viewing)
  • which fields to show dropdowns for (rather than making users type IDs)
  • what captions to use for all table and column names
  • constraints to enforce
  • constraints to notice and complain about, but not enforce
  • a reasonable user management system for the web app (login/password/rights/etc.)
  • rules that define row-level security, i.e. allow users to edit some rows of a given table but not others

I’d like a “generative” tool, one that spits out a fully functioning app which doesn’t depend on the original tool for runtime infrastructure.

The specification of the things above can be mostly textual. Drag-drop-UML doesn’t excite me all that much (though I’ve used such beasts for Java work before). The generation process must be customizable, since no tool is likely to meet 100% of my present and future needs.

The generated app will preferably be in PHP or Java. PHP seems reasonable as it is ridiculously easy to get up and running (at most, a few packages to isntall in a common Linux distro), and Java is reasonable because I use it heavily for other purposes anyway.

It should be possible to support several common DBs (SQL Server, MySQL, PostgreSQL) with the flip of a switch or two.

The generation process should act like a build process – i.e. the “source” of the application would be the specificaiton file plus perhaps a few files work of manually tweaked code.

OK, so I’m asking for a lot.

… but there are dozens (or even hundred) of tools out there, both commercial and open/free, that meet at least some subset of the above. I Googled for a few minute and was overwhelmed at how many there are to look at.

A good starting point is the Code Generation Network, and a few of the specific tools I saw are phpCodeGenie, PHPMaker, Camino, Jag, JRpt, etc.

Of course, it’s entirely possible that none of them does everything I need – but that’s OK too, there is another layer of tools out there that make it easy to get start with my own generative approach: FMPP, Jostraca, etc.

Enough hoping for tonight. If anyone out there has had a very positive experience with any of these tools, for the kind of problem I’m looking to solve, I’d love to hear about it.


A few clarifications, after the initial post:

  • For this particular need, I prefer a generative approach to an “executable model” approach, though I think the latter might be the long-term winner in MDA.
  • Yes, I know that I’m mostly asking for DB-centric CRUD operations, rather than a domain centric behaviour model. I have plenty of time for the latter approach (with lots of Java code, Hibernate, perhaps even a rules engine) in other place, but for today’s need, which is for the “admin” side of an application, DB-centric CRUD will do the job fine, with a little help from constraints, validation, etc.

JAR Bloat

I am surprised at how large the main client application JAR file is on my current Java project. I have a pile of source code which I have written over the last few months; it contains no generated code and no outside code (that stuff is in other jars).

This body of code results in a 506K JAR file. About 10% of that is because it is a “signed JAR” (An aside: it appears that signed jars actually actually sign each thing inside the JAR… much far higher overhead than .NET’s igned assemblies, which sign the whole thing as a chunk. I think .NET is on to something good with Assemblies with Sun missed with just-a-bunch-of-classes-in-a-JAR. Of course the latter has significant advantages also.)

Without the signing, the JAR is about 450K.

Javac optimization is on. There are ~350 classes in the JAR file. The JAR is compressed; wihtout compression it is around a megabyte.

– debug is on, so I get more helpful stack traces from the field when errant software somehow escapes our highly rigorous release process. Turning off debugdrops it to 424K signed / ~380K unsigned.

These numbers all seems enormous. The source code for the contents of this JAR, is only ~800K, and contain considerable comments, private identifiers, etc. My mental model of compilation suggests that it would produce tightly packed bytecode that tersely captures the executable essence of the source code in a small fraction of the bytes. This appears to not be the case.

Taking a look at Zoe, “Google for your email”

I tried out Zoe (http://zoe.nu) recently, having seen it described as “Google for your email”. Of course that monikor will make less sense with Gmail here.

Zoe runs in the background on your machine, acting as a (non-real-time) proxy for your incoming (POP) and outgoing (SMTP) email connections; you continue to use your existing email client, seamlessly, while Zoe catalogs, cross-links, and full-text indexes every message. It’s a slick idea, and I believe that a few years from now, the features in it will be built in to many email clients.

Zoe provides a HTML user interface, even though it is a local application; it worked fine for me with both IE and Mozilla/Firefox. I also use POPFile (which uses an HTML interface), so the approach didn’t bother me, but it’s quite different from a “rich client” experience. The primary thing to do in Zoe is
to search, and web browsers work well enough for search/results/browse interfaces.

Zoe is written in Java, and other Java app writers should take a look at how painless the expierence is there: unzip the application, and run it. From the web site Zoe appears to be Mac-centric, but it works the same way on Windows (and presumably Linux/etc.)

I ended up giving up on Zoe after a few days, though, for several reasons:

  • Too many files: Zoe stores each email message in a separate file, plus various
    other files for indexes. After importing several years of stored email, I
    had 63,000 files under my Zoe directory. Aodern file system doesn’t mind lots
    of files, but there is more to life than file systems – try copying 63,000
    files to another drive, or backing them up, and it become clear that storing
    every archived email message forever in its own file, doesn’t scale well.
    (By the way, the emails are stored in directories named for the year/month/day
    of the message – good idea!)
  • Rebuild needed: A couple of times I was getting obviously wrong results
    from Zoe searches, and had to rebuilt its indexes to correct it. Easy to do
    – a one-line command. Downside: Zoe was unaccesible and my PC was working
    hard the next two hours while it rebuilt. I’ve worked with full-text-index
    systems in the past, and believe that this process could be made much faster.
  • Bugs – I sometimes get a “java.lang.NullPointerException” when
    clicking on a link in Zoe. It will go away… if I wait through another 2-hour
    rebuild.
  • I’m apparently not clever enough to tell how the GUI works – lots of things
    are clickable in Zoe; with many of them it’s not clear where the link will
    go
  • Missing hits – the search in Zoe often files far fewer hits for a term,
    than I know exist in my mail archives. This might be related to the Rebuild
    issue, though.
  • Lack of threading – contrary to some comments I saw about Zoe, I am unable
    to find any feature/view in it where it shows a threaded mail conversation.
    This is my #2 feature needed to manage a massive email collection, right behind
    Search.

In spite of this, I’m very pleased to see Zoe out there, wish them well, and
encourage anyone with a lot of email to give it a try, if only get an idea what
it coming.

Graph Visualization in Delphi

For a project at Oasis Digital, we need to show the end user a graphical representation of a graph (in the “graph theory” sense of the word). The application is written in Delphi, and in looking around I didn’t find any native Delphi components for doing that.

I did find GraphViz, and a COM Wrapper for it called WinGraphViz. Wiring the latter up to Delphi turned out to be quite easy. The minimal code to do it, for a demo app, is below. To make this compile you’ll need to import the type library for WinGraphviz.

procedure TExampleForm.DrawGraphForData(Data: string);
var
Dot: IDot;
Image: IBinaryImage;
ImageFileName: string;
begin
ImageFileName := 'c:image.gif';
Dot := CoDOT.Create;
Image := Dot.ToGIF(Data);
Image.Save(ImageFileName);
WebBrowser1.Navigate('file:///C:/image.gif');
end;

Production code would probably use a better way of getting the generated graph on to the screen. GraphViz support imagemaps, making it easy to make the notes clickable. It can draw various arrow types, node shapes, etc., and tries to lay out graphs in a readable way, without crossing lines, etc.

A trivial sample app looks like this:

Update: a correspondent pointed out that the graphic example above is a bit ugly, with non-anti-aliased lines and fonts. To resolve that, I turned to SVG; GraphViz can produce output in SVG format (among others), and the freely downloadable Adobe SVG Viewer can display them.

With slightly different code:

ImageFileName := 'c:image.svg';
Dot := CoDOT.Create;
Image := Dot.ToSVGZ(Data);
Image.Save(ImageFileName);
WebBrowser1.Navigate('file:///C:/image.svg');

We get an application with this appearance:

You can download the Delphi WinGraphViz Sample Application Source code.

More Bowling

In my last post, I presented an enhancement to a "bowling score calculator" problem being discussed on the Extreme Programming Mailing List. My solution extended a not-very-OO
solution presented here; though not object oriented, it was short and clear. I generally write intensively OO code, so I found this interesting.

A contention on the list, though, was that the procedural solution could not be extended to support more features easily. Today I’d added even more features, just to see if this is true:

  • Know how many pins are standing, and prevent the caller from knocking down
    more pins than are up.
  • Know which rolls occurred in which frame; be able to answer "what were
    the rolls in frame N?"
  • Present an HTML representation of the state of the game after each roll.

As usual, I added this features a test at a time a bit at a time. It turned out to be easy to keep track of which rolls go in which frame. The updated source code can be downloaded: bowling-java-3c.tgz and is also on github. As before the download includes the tests also. I’ve renamed a few things for greater clarity. (I’ve updated the file a couple of times since posting it, to fix a problem in the final output, and separate some tests I had combined.)

I was surprised to find that adding these features didn’t add much complexity to the code. When I look at this code, it cries out to have a class of some kind extracted – but I’ve tried extracting, for example, the idea of a Frame and been unsatisfied. Perhaps I’ll explore that more another day. These variable:

  private int[] frameScores = new int[NUM_FRAMES];
  private int[] firstRollInFrame = new int[NUM_FRAMES + 1];
  private int scoredFrame;
  private int finishedFrame;

could form the starting point for that, like so:

class Frame {
    private int score;
    private int firstRoll;
    private boolean scored;
    private boolean finished;
}

The Game class is in its entirety is
available here (syntax highlighted HTML) or in the download above.

I implemented the HTML rendering of frames without aid of test cases. The code is included
in the download above, and produces output like the sample run below. The output looks
much better when not included inside a WordPress post – the sample below is
partially mangled.

The main
loop of the demo program biases the random numbers toward high scores:

        while (!game.gameOver()) {
          // Bias our guy toward good rolls:
          int n = rnd.nextInt(game.pinsStanding() + 4);
          int pins = Math.min(n, game.pinsStanding());
          renderer.tellAboutPins(pins);
          game.roll(pins);
          renderer.printGame(game);
        }

Rolling… 7 pins

7

Rolling… 3 pins

7 3

Rolling… 10 pins

7 3

20

10

Rolling… 4 pins

7 3

20

10
4

Rolling… 2 pins

7 3

20

10

36

4 2

42

Rolling… 10 pins

7 3

20

10

36

4 2

42

10

Rolling… 0 pins

7 3

20

10

36

4 2

42

10
0

Rolling… 3 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

Rolling… 10 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

Rolling… 3 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10
3

Rolling… 5 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

Rolling… 10 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

10

Rolling… 4 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

10
4

Rolling… 0 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

10

98

4 0

102

Rolling… 1 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

10

98

4 0

102

1

Rolling… 1 pins

7 3

20

10

36

4 2

42

10

55

0 3

58

10

76

3 5

84

10

98

4 0

102

1 1

104


Comments welcome, via email (address below).