views:

1509

answers:

5

In JSP I can reference a bean's property by using the tag ${object.property}

Is there some way to deal with properties that might not exist? I have a JSP page that needs to deal with different types. Example:

public class Person {
    public String getName()
}
public class Employee extends Person {
    public float getSalary()
}

In JSP I want to display a table of people with columns of name and salary. If the person is not an employee then salary should be blank. The row HTML might look like:

<tr>
    <td><c:out value="${person.name}"></td>
    <td><c:out value="${person.salary}"></td>
</tr>

Unfortunately if person is not an employee then it can't find salary and an error occurs. How would I solve this in JSP?

Edit: Is there an instanceof check in JSP tag language?

A: 

You could always have a type field.

public class Person {
    public String getType() { return "Person"; }
    public String getName()
}
public class Employee extends Person {
    public String getType() { return "Employee"; }
    public float getSalary()
}

Your JSP would look like

<tr>
    <td><c:out value="${person.name}"></td>
    <td><c:if test="'Employee' eq person.type"><c:out value="${person.salary}"></c:if></td>
</tr>

Of course the Class class already has this...

<tr>
    <td><c:out value="${person.name}"></td>
    <td><c:if test="'Employee' eq person.class.simpleName"><c:out value="${person.salary}"></c:if></td>
</tr>

You could also have `isEmployee()' method.

sblundy
+1  A: 

One method would be to create a custom tag library and use polymorphism within it to handle the case where a Person is-a Employee.

I haven't done this in a while for JSP, but frequently use a similar technique in GSP (Groovy/Grails Server Pages).

Otherwise, you could put some logic in the JSP (not ideal) to test for Employee-ness:

<% 
   String salary
   if (person instanceof Employee) {
       salary = person.salary
   } else {
       salary = "" // or '&nbsp;'
   }
%>
<td><c:out value="${salary}"></td>
Ken Gentle
+2  A: 

Just use the EL empty operator IF it was a scoped attribute, unfortunately you'll have to go with surrounding your expression using employee.salary with <c:catch>:

<c:catch var="err">
    <c:out value="${employee.salary}"/>
</c:catch>

If you really need instanceof, you might consider a custom tag.a

Eric Wendelin
I _knew_ there was an easier way... DOH!
Ken Gentle
Using Tomcat 5.5 this will throw an exception if the property doesn't actually exist on the object as in the case of the example shown above.
laz
Confirmed, this does not work if person doesn't have a salary property.
Steve Kuo
My apologies for my carelessness. I hate to say it but you may have to use the c:catch tag for this.
Eric Wendelin
+2  A: 

If you want the class, just use ${person.class}. You can also use ${person.class.name eq 'my.package.PersonClass'}

You can also use the "default" on c:out.

 <c:out value='${person.salary}' default="Null Value" />
James Schek
This is exactly what I was looking for! I use a <c:when> tag and the class' simpleName property and I can display each of my subclass's unique fields.<c:when test="${instance.className.simpleName == 'MyClassName'}">
Chris Kentfield
+1  A: 

Concise, but unchecked.

<tr>
    <td>${person.name}</td>    
    <td>${person.class.simpleName == 'Employee' ? person.salary : ''}</td>
</tr>

Is there an instanceof check in JSP tag language?

Not at the moment of this writing. I read somewhere that they have reserved it, instanceof keyword, in EL, may be for future. Moreover, there is a library available that has this specific tag. Look into that before deciding to create some custom tag for yourself. Here is the link, Unstandard Tag Library.

Adeel Ansari