Search code examples
javajsf-2facelets

JSF 2/Facelets: How to use facelets effectively for editing instances of subclassed types uniformly


Suppose for the sake of discussion I have the following classic hierarchy:

abstract class Vehicle {
  private int cost; 
  // imagine the usual getters and setters here
}

class Car extends Vehicle {
  private String make, model, year; 
  // getters and setters
}

class Plane extends Vehicle {
  private int yearIntroduced;
  // getter and setter
}

Now suppose in my backing bean I have a list of Vehicle instances in bb.vehicles. How do I support uniform editing? I don't see how to avoid this kind of code:

<ui:repeat value="#{bb.vehicles}" var="vehicle">
  <!-- this is where the trouble begins -->
  <app:editCar      car="#{vehicle}"  rendered="#{test vehicle to see if it is a car}"/>
  <app:editPlane  plane="#{vehicle}"  rendered="#{test vehicle to see if it is a plane}"/>
</ui:repeat>

This seems like an affront to proper OO design, which would seem to dictate that the vehicle itself should somehow participate in the selection of the right view rather than the view examining it and deciding itself. I see this pattern in a lot of places in my code where I have a semi-heterogeneous collection or a property on an object that must be an instance of a class or one of its subclasses, and I need a special editor that exposes what makes the subclass different. Seems like a smell, thought I'd ask if there's a better way.


Solution

  • In general, you should probably have something in your backing bean which wraps vehicles, and gives an xhtml file to include to edit that particular vehicle type (or just use convention if you'd like). That way you don't have anything specific in your jsf file. just use ui:include and call the property on the vehicle backing bean.