1

I'm migrating an old application from JSP 1.1 to JSP 2.1, and trying to do everything without scriptlets. I have a JavaBean that I create, populate and insert into the page scope via a CustomTag. This JavaBean exposes some methods that transform data, generate HTML snippets, etc, based on it's instance variables.

When I need to access a property in the JavaBean I use:

${mybean.property}

But since JSP 2.1/EL 2.1 don't support calling methods on your beans (this requires JSP 2.2/EL 2.2), I'm trying to determine the best way to expose such utility methods to my JSP pages without resorting to scriptlets.

Here is an example of the methods on the JavaBean that I need to access:

public String getThumbColor() {
   String tbgcolor = "#FF0000";
   if (this.getJavaBuildTotal() > 0 && 
        this.getJavaBuildBroke() == 0 && 
        this.getCeeBuildBroke() == 0 && 
        this.getJavaBuildInvalid() == 0 && 
        !this.hasBuildException()) {
      tbgcolor = "#00FF00";
   }
   else if (this.getJavaBuildTotal() == 0 && this.getCeeBuildTotal() == 0) {
      tbgcolor = "#f7f814";
   }
   return tbgcolor;
}

It feels like converting this (and the 10 or so other methods like it) entirely to JSTL in the JSP would be muddying up my JSP page.

Since I'm already doing a large refactoring, I don't mind drastic changes; yet I can't think of anyway to eliminate my need of certain methods that use conditionals for deciding on return values, generate small HTML snippets, etc.

bconneen
  • 146
  • 2
  • 12
  • 1
    May I assume that you mean `public static` methods when you say *utility methods*? – BalusC Mar 18 '11 at 17:12
  • Well they aren't currently public static. Since the methods existed in the java class that has now become the javabean accessed from the JSP. They make decisions based on the instance variables in the class and respond accordingly. I do understand that one solution would be to move these "utility" methods out of the javabean, and into the Custom Tag, as static methods that take the java bean as a param. – bconneen Mar 18 '11 at 17:27

2 Answers2

1

Have a look at JSTL. It offers at least a basic set of core tags to control the flow in the page. Use this instead of if/else/switch whatever in scriptlets. It also offers several utility methods in the functions taglib. Basic String operations such as substring and so on are offered by this. You could also homegrow custom EL functions yourself which can call public static methods with arguments.

See also:


Update as per the information in the comment

They make decisions based on the instance variables in the class and respond accordingly

You could add getters for those variables and use this in <c:if> or whatever.

<c:if test="${bean.property == 'somevalue' && bean.otherproperty != 'foo'}">

You could even wrap this in a boolean getter in the bean if those values are for example constants.

public boolean isCondition() {
    return "somevalue".equals(property) && !"foo".equals(otherproperty);
}

which you use as follows:

<c:if test="${bean.condition}">

There are lot of ways depending on the concrete functional requirement, which is still vague in your question.

See also:


Update 2: as per the new example in your question, presentation specifics should go in the view (JSP). The bgcolor is part of the presentation. I'd suggest to replace this by an enum.

public enum Status {
    OK, FAIL, NONE;
}

public Status getStatus() {
   if (this.getJavaBuildTotal() > 0 && 
        this.getJavaBuildBroke() == 0 && 
        this.getCeeBuildBroke() == 0 && 
        this.getJavaBuildInvalid() == 0 && 
        !this.hasBuildException()) {
      return OK;
   }
   else if (this.getJavaBuildTotal() == 0 && this.getCeeBuildTotal() == 0) {
      return NONE;
   }
   return FAIL;
}

And declare the color in the view

<c:set var="bgcolor" value="${(build.status == 'OK') ? '#00ff00' : (build.status == 'FAIL') ? '#ff0000' : '#f7f814'}" />
...
<tr bgcolor="${bgcolor}">

Or, better, make a CSS class of it

<tr class="build ${build.status}">

with in a style(sheet)

tr.build.OK { background: #00ff00; }
tr.build.FAIL { background: #ff0000; }
tr.build.NONE { background: #f7f814; }
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • This is a good suggestion, and I've definitely already done a pass using this. So my JSP no longer uses scriptlets for control or looping. I use the JSTL core tags instead. But I've still found a need to access certain non static methods on my JavaBean. If I was to move the conditional logic in these methods to the JSP using JSTL core, I feel I would be dirtying up my JSP. One possibility would be to move these methods out of the JavaBean and put them into the CustomTag as public static, making them proper taglib functions. But this seems like it might be overkill. – bconneen Mar 18 '11 at 17:30
  • When you speak about wrapping my decisional logic in a getter, you mention only if the values are static? So a getter that has some decision logic in it, can only operate on static variables? – bconneen Mar 18 '11 at 18:39
  • No, when the values are constants and thus not sensitive to changes. – BalusC Mar 18 '11 at 18:45
  • Yes, once the bean is created and populated it won't change again. Especially since it's only stored in the context of the page. Each page request results in a new bean being created and populated based on request parameters. – bconneen Mar 18 '11 at 18:47
  • I noticed your updated question. I added second update to the answer. – BalusC Mar 18 '11 at 18:50
  • Thanks again. I really like both options. And I agree in the case where the bean method is making presentation decisions, it makes sense to move this decision into the JSP. I also appreciate the encapsulation of determining the status in a "getter". And I'm going to give serious consideration to utilizing CSS. Appreciate all the help. – bconneen Mar 18 '11 at 21:17
1

Depending on your application server / framework, etc you might be able to just override the default EL implementation for a EL2.2 one (I have successfully used Tomcat 7 EL 2.2 on a Tomcat 6.0.20 / JSF 2.0 web application). Other than that you can create a <call-method object="..." method=""><param=".."/>...</call-method> tag and substitute the scriptlets.

Anyway if you don't mind drastic changes you should eliminate these calls from your JSPs and go for a MVC architecture. You would have:

  • Controller components (typically servlets / filters) that receive client requests, decode them and invoke the appropiate Actions that update the application Model.

  • View components (typically JSP pages) that are forwarded the request once the Actions have finisihed, so they only need to read the updated Model and dump it into the response to the client.

Most popular Java web frameworks support this architecture (Struts, JSF, Spring MVC, ...)

gpeche
  • 21,974
  • 5
  • 38
  • 51
  • I can appreciate using MVC and that might be something I move to, but I can't see how MVC would solve my core problem... preventing the muddying up of my JSP with scriptlets, while still allowing the JSP to call complex methods for HTML snippets. – bconneen Mar 18 '11 at 18:38