Using varargs in a Tag Library Descriptor
Asked Answered
P

4

10

Is it possible to have a TLD map to the following function:

public static <T> T[] toArray(T... stuff) {
    return stuff;
}

So that I can do:

<c:forEach items="${my:toArray('a', 'b', 'c')}"...

I tried the following <function-signature>s

java.lang.Object toArray( java.lang.Object... )
java.lang.Object[] toArray( java.lang.Object[] )

And others but nothing seems to work.

Possing answered 17/2, 2011 at 19:26 Comment(0)
S
10

Unfortunately that's not possible. The EL resolver immediately interprets the commas in the function as separate arguments without checking if there are any methods taking varargs. Your best bet is using JSTL fn:split() instead.

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...    
<c:forEach items="${fn:split('a,b,c', ',')}" var="item">
    ${item}<br/>
</c:forEach>

It would have been a nice feature in EL however, although implementing it would be pretty complex.

Sayre answered 17/2, 2011 at 19:52 Comment(2)
implementing the whole java method selection algorithm is going to hurtAmadou
I can't use this approach since I'm not dealing with strings (just had it for the example), but a nice trick to keep in mind.Possing
A
1

oh well. so this is for literal construction, and there will be limited items

public static Object[] array(Object x0)
{ return  new Object[] {x0}; }

public static Object[] array(Object x0, Object x1)
{ return  new Object[] {x0, x1}; }

....

public static Object[] array(Object x0, Object x1, Object x2, ... Object x99)
{ return  new Object[] {x0, x1, x2, ... x99}; }

I don't find it sinful to do this. Auto generate 100 of them and you are set. Ha!

Amadou answered 17/2, 2011 at 19:59 Comment(1)
I ended up doing something similar to this (only need two elements currently). Ugly but works.Possing
P
1

It's a little more painful, but you could do something like this:

class MyAddTag extends SimpleTagSupport {
    private String var;
    private Object value;

    public void doTag() {
        ((List) getJspContext().getAttribute(var).setValue(value);
    }
}

<my:add var="myCollection" value="${myObject}" />
<my:add var="myCollection" value="${myOtherObject}" />
<c:forEach items="myCollection">...</c:forEach>
Pallium answered 4/4, 2012 at 21:29 Comment(0)
A
0

One thing I did to get around this was to create a utility function class and set it on the application context when the server starts up, rather than trying to define it as an EL function. You can then access the method in EL.

So when my servlet starts up:

context.setAttribute("utils", new MyJSPUtilsClass());

and on my JSP:

${utils.toArray(1, 2, 3, 4)}

Arboreal answered 31/7, 2015 at 0:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.