Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a method with parameter inside JSTL loop

Tags:

java

jsp

jstl

I have a JSP which needs to print some text which is produced by taking loop iterator and feeding it to another object (Spring bean), something like:

<c:forEach var="myVar" items="${myVars}">
   <c:out value="anotherObject.getFoo(myVar)"/>
</c:forEach>

Obviously the code above isn't valid as JSTL . operator only allows parameter-less invocations. I can see following solutions to the problem:

1) Scriptlets

<c:forEach var="myVar" items="${myVars}">
  <%
    SomeType myVar = (SomeType) pageContext.getAttribute("myVar");
    SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject");
    YetAnotherType result = anotherObject.getFoo(myVar);
    pageContext.setAttribute("result", result);
  %>
  <c:out value="${result}"/>
</c:forEach>

The obvious con here is JSP code pollution and general ugliness.

2) Writing a tag which does whatever is done inside scriptlets. Typical example of over-engineering, yuck!

3) Decompose a collection of myVars and replace each myVar with a dynamic proxy, InvocationHandler of which would add extra parameter-less method to make all getFoo() calls through anotherObject. All of that would be done in the controller so JSP would stay clean and myVar stays the same. But at what price?

I can not add .getFoo() method to the myVar because it doesn't fit there and would break the separation of concerns.

It looks like passing parameters will be possible in JSP/EL 2.2, but I'm using Tomcat 6.0.29 which only bundles EL 2.1 API.

Question: can anyone suggest the cleanest approach for this situation?

like image 522
mindas Avatar asked Jul 20 '11 10:07

mindas


People also ask

How do you call a method in JSTL?

The initial JSTL 1.0 EL lacked support for functions. The JSP 2.0 EL lets you call a Java class's public static method using the following syntax: ${prefix:methodName(param1, param2, ...)}

How to iterate array in JSTL?

Iterating over array using JSTL forEach loop For iterating over an array e.g. String array or integer array in JSP page, "items" attribute must resolved to an array. You can use expression language to get an Array stored in of scope available in JSP e.g. page scope, request scope, session or application scope.

What is the syntax for forEach loop in JSTL?

Full Stack Java developer - Java + JSP + Restful WS + Spring The <c:forEach> tag is a commonly used tag because it iterates over a collection of objects. The <c:forTokens> tag is used to break a string into tokens and iterate through each of the tokens.


1 Answers

A simple Java-only "trick-fix" that works in the older JSTL version, too, and requires no extra taglibs/config/dependencies/frameworks, etc. is to "wrap" the function you want to call from JSTL in a class that extends from a Map class, and override its get() method.

As a minimal example, if you e.g. want to call the Math.sin() function from JSTL, you would define a class:

public class Sine extends HashMap<Double, Double> {
    private static final long serialVersionUID = 1L; // Avoids compiler-warning

    @Override
    public Double get(Object arg) {
        Double x = (Double) arg;
        return Math.sin(x);
    }
}

Then in your Action execute() method, you do:

...
request.setAttribute("sine", new Sine());
...

Then in jsp you can say:

  ${sine[0.75]}

to calculate the value Math.sin(0.75)

JSTL will treat the variable sine as a Map, but you can compute and return anything you like from the get() method.

I guess it gets a bit more involved if you have more than one argument to your function, but there should be workarounds for that, too :)

like image 100
Rop Avatar answered Sep 30 '22 03:09

Rop