Monday, February 15, 2010

Parent-Child Relationship in Java Business Logic Beans

There must be good tips and info out there on the net about best practices for designing Java beans business objects, etc. I don't mean basic stuff like getters/setters, but much more subtle questions like when to hide constructors, how to deal with parent-child objects and what sort of methods to expose for that, etc.
Somehow I never found good info on that (not that I tried too hard), and my classes didn't cover it.

Here's my take on the parent-child relationship between Java objects. Say there are two classes: Customer and Contact (a typical sales-app situation). Each customer has multiple contacts - a simple one-to-many relationship. The customer object keeps track of the child contacts with a collection, and the contact maintains a parent customer reference.

Question: how to handle creating new contact objects?

In contact class:
// package-private constructor
Contact(Customer c, parameters...) {
  this.customer = c; // keep parent reference
  // deal with other parameters
In customer class:
public Contact createContact(parameters...) {
  Contact c = new Contact(this, parameters...);
  this.contacts.add(c); // update children collection
  return c;
Why not expose the contact constructor directly and have it update the customer contacts collection? Adding to the children collection is altering object state - it is best to keep that inside the customer class.

Even in terms of readability this makes more sense. When humans say "customer", the meaning includes all the relevant contacts, etc. When we create a contact we change customer state, first and foremost. So it makes sense to initiate that change with the customer object.

Wednesday, February 10, 2010

Two-column Form Layout Without Floats

As part of my job, I work with HTML forms almost daily, and styling them is an ever-evolving challenge.

Clients like it when labels are horizontally aligned with inputs. It's the standard look, and it works well.

One of the big requirements is avoiding floats. Float behaviour is complicated and buggy, even outside of IE. Normally that's not a big issue, but in apps one can't predict where a given form will end up, what kind of custom widgets (that use their own funky float layout) will need to be part of it, etc. Basically, form CSS has to be rock-solid.

Markup has to be simple and valid XHTML. So no tricks like placing the input inside the label. And it sucks to litter markup with spans and whatnot.

There has to be allowance for error messages, help tips, overflowing label text, etc. Basically, no reliance on hand-tweaking content.

A good method that does not use floats is described in this A List Apart article:

It uses inline-block for labels - not great, because it's hard to put properly aligned help text after it. Same with error text.

The answer? Negative margins. Check this example (forgive the programmer art):

First, we keep label content to the left of everything else by assigning a width to it (as a block), and applying a left margin to other content in the form.

Next, we apply a negative bottom margin to every label. Any content that follows a label is "pulled up" vertically to appear as though they are on the same horizontal line.

For consistency across fonts and browsers, we assign a generous fixed height to the label, and make the negative margin match it. In theory, the fixed height can be anything, even zero - but IE6's overflow bug puts an end to that theory.

This brings up a big caveat with this method. If the label contains several lines of text, the browser will not auto-magically shift remaining content down, as it would with normal cleared floats. In the particular case of HTML forms, this is not an issue, given enough vertical spacing between inputs.

Monday, April 13, 2009

NetBeans, Subversion and plink revisited

An earlier post detailed some issues with NetBeans bundled SVN+SSH support. NetBeans allows specifying a different SSH connection command-line (e.g. for plink) for different Subversion URLs - e.g. to set the username, password or other custom connection options; the problem is that it does not actually use that setting after first restart. Instead, a central Subversion config file is consulted; the connection options from there are used for every Subversion URL. That's probably a bug.

The work-around so far has been to just put the settings in the central file. But of course that stops working the moment there is more than one Subversion URL used. Here is my new solution when using plink.exe.

In the central Subversion config file, specify the command-line of "<..path..>\plink.exe -batch -load"; firstly, that turns off interactive prompt (and hence annoying hangs), and also makes plink interpret hostnames passed by Subversion as PuTTY session names! The next step is to set up a PuTTY session named after that host and put all the appropriate settings there - the auto-login username, the private key for authentication, etc.

NOTE: this allows using arbitrary "fake" hostnames in Subversion URLs, as long as they correspond to a PuTTY session.

NOTE: the "-load" option magically works here because the first parameter passed by Subversion after it is the hostname; if that was not the case, the above would fail.

Unix/Linux SSH users, of course, have always had the option to use session names as pseudo-hostnames - without the "-load" option hackery. But this would not even come up if not for the NetBeans bug.

Wednesday, December 31, 2008

NetBeans bundled Subversion troubles

This is a small note-to-self.

NetBeans support for Subversion on Windows has an option to use either bundled svn binaries or CollabNet's official installation. The bundled NetBeans svn client works just fine at first - I use it with plink to do ssh tunneling.

Except that eventually it starts failing with a mysterious exception along the lines of:
org.tigris.subversion.javahl.ClientException: The system cannot find the file specified.
Commit failed (details follow):
Can't create tunnel: The system cannot find the file specified.

Long story short, the snafu is likely because in the NetBeans SVN settings, the full path to plink executable has to use forward slashes. Also, it may be prudent to surround whitespace-containing paths with quotation marks.

Anywho, it may still stop working, but we'll see.

UPDATE: nope, still doesn't work, heh.

UPDATE: works now. following NetBeans wiki instructions, it turns out that the bundled svn client doesn't actually listen to tunnel settings given by NetBeans (!). It listens to the .../Application Data/Subversion/config file. Another important caveat that wasted me a lot of time is that any time that file is changed, NetBeans must be restarted for any change to make a difference. And another important caveat is to use the explicit .exe extension on the plink executable file path. I added plink's location to my PATH; I also used Pageant for private-key auth instead of directly specifying the private-key path. Grr, what a stupid NetBeans bug.

Sunday, November 2, 2008

Computer Science Approach to OS Design

So I had to tinker with Debian administration a bit... I can't help but philosophize about how some fairly abstract CS theory can apply to pragmatic admin stuff - packages, admin shell-scripts, etc.

Debian's dpkg already allows treating software in a fairly declarative OOP fashion. You have concrete "implementation" packages providing functionality guaranteed by special virtual packages, generic system-wide scripts for things like startup/shutdown sequence management, conf.d approach (one of my favourites) for modular "plug-in" configuration, etc. It is all very much interfaces vs classes and design-by-contract.

So I wonder if there is room to go a step further. Make packages declare their functionality in an abstract IDL/CORBA-like interface language. For example, a /usr/share file is kind of like a read-only property getter. An executable is a method (obviously). A config file is a special variation of user input (where the user is the admin). And so on and so forth.

Then, packages can declare their prerequisites in a much more granular and consistent way - by indicating individual files and utils that they use. There could be even tools that would automate half the work of a package maintainer. For example, compile the program directly from a SourceForge tarball, run it and sniff out its runtime library dependencies, system file access on the fly. In fact, existing debs and rpms could be scanned and adapted appropriately without a recompile.

What does that do? The package manager can be much smarter in detecting broken dependencies and software management issues. There is also room to get closer to a nice unified configuration system (not that everyone really cares too much about that). This would also help a lot to make Linux consumer-friendly (although that is still mostly about desktop app usability). It just seems so much... cleaner.

There is more to this - current Linux kernel allows so much cool admin trickery (such as LUFS) I am surprised core OS maintainers are not using it for more.

Sunday, October 26, 2008

So I was thinking about enriching/AJAX-ifying my current JSF UI. The data displayed is very complex; the code is getting big and cumbersome, and the size of each page is reaching 100kb. Actions feel very un-responsive and slow, since it takes 2-3 seconds just to download the HTML itself!

One option is to not even do HTML+JS, and use a Swing-based downloadable client UI. Another is to use partial page replacement and keep existing JSF code. Also, I could just use bare-bones DWR and jQuery.

Common things to think about are:
  • I have a good POJO model of what the UI is managing, and I want to re-use it
  • Wherever the POJO model lives, it has to be able to talk to J2EE service beans
A Swing UI would let the model live on client-side JVM, and would require an RPC channel to the J2EE side directly. Promises to be clunky...

I did some quick Googling on DWR and direct JavaScript <-> server-side session POJO interfacing. Looks very cool because of its simplicity. I am comfortable with using jQuery, and its one-liner minimalism could mesh very well with making simple get/set calls to Java model beans. However, as the UI itself gets complex, one-liners get hairy.

JSF with PPR could be nice and easy to add to existing code. But since it will still generate huge amounts of HTML, I wonder if it will stay just as slow. The only way it wouldn't be the case is if JSF only rendered the affected parts of HTML.

Something to ponder...

Wednesday, October 15, 2008

Nano HTTP server

A tiny utility that provides a super-minimalist HTTP server, serving up contents of just one file. I mocked it up in Perl a while back, I think it was supposed to provide a WAR file for remote deployment to Tomcat, or some such.

Not really that great, but may be useful for quick-and-dirty file transfer or for testing HTTP stuff. The source code follows:
# listens for HTTP connections and, regardless of request,
# always returns contents of given file, with given content-type
# header value
# useful to serve up some test data as though it was from a real
# HTTP server

use IO::Socket;

my($port, $file, $contentType) = @ARGV;

$port = int($port);

defined $contentType or die "must supply content type";

open(FILE, $file) or die "cannot open file";
local $/ = undef;
my $data = <FILE>;

my $socket = new IO::Socket::INET('LocalPort' => $port, 'Proto' => 'tcp', 'Listen' => 1, 'Reuse' => 1);
$socket or die "cannot create listener socket";

my $clientSocket = $socket->accept();

# read a token amount of data, just for appearance's sake
my $buf;
$clientSocket->recv($buf, 5);

# print our response
print $clientSocket "HTTP/1.0 200 OK\r\n";
print $clientSocket "Content-Type: ", $contentType, "\r\n";
print $clientSocket "Content-Length: ", length($data), "\r\n";
print $clientSocket "\r\n";
print $clientSocket $data;