30

I'm working on a web application using Java and its frameworks(Spring 3.1.1). And I'm trying to avoid using scriptlets as much as possible, however I can't find a way other than this to define an array:

<%
    String[] alphabet = {"A", "B", "C", ... , "Z"};
    pageContext.setAttribute("alphabet", alphabet);      
%> 

After setting pageContext attribute, I can use it with ${alphabet}. But I want to know, is it possible to use plain JSTL/EL to create an array?

UPDATE: I'm using this array to create links. For example, if user clicks 'S', a list of employees whose first name starts with 'S' comes. So, instead of creating links one by one I'm iterating ${alphabet}.

Alpha Carinae
  • 441
  • 2
  • 8
  • 11

6 Answers6

55

If you're already on EL 3.0 (Tomcat 8+, WildFly 8+, GlassFish 4+, Payara 4+, TomEE 7+, etc), which supports new operations on collection objects, you can use ${[...]} syntax to construct a list, and ${{...}} syntax to construct a set.

<c:set var="alphabet" value="${['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']}" scope="application" />

If you're not on EL 3.0 yet, use the ${fn:split()} function trick on a single string which separates the individual characters by a common separator, such as comma.

<c:set var="alphabet" value="${fn:split('A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z', ',')}" scope="application" />

I do however agree that you're better off using normal Java code for this. Given that it's apparently static data, just create this listener class:

@WebListener
public class ApplicationData implements ServletContextListener {

    private static final String[] ALPHABET = { "A", "B", "C", ..., "Z" };

    @Override
    public void contextInitialized(ServletContextEvent event) {
        event.getServletContext().setAttribute("alphabet", ALPHABET);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // NOOP.
    }

}

It'll transparently auto-register itself on webapp's startup and put the desired data in application scope.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Thanks, I like the "function"(fn) usage. By the way, does `@WebListener` work on Java EE 5? – Alpha Carinae Jan 24 '13 at 06:47
  • You're welcome. No, use `` in `web.xml`. Those annotations are new since Servlet 3.0 / Java EE 6. – BalusC Jan 24 '13 at 10:11
  • Is there any way to declare an array and add elements to array in for each? – Subin Chalil Jan 28 '16 at 05:34
  • value="${['A','B', ... IS NOT WORKING on "javax.servlet.jsp.jstl-1.2.1.jar" – Park JongBum Dec 06 '19 at 01:11
  • @Park: as explained in the answer, you need a minimum of EL 3.0 and this is already built into Tomcat 8+, WildFly 8+, GlassFish 4+, Payara 4+, TomEE 7+, etc. Note that the JAR file which you're mentioning is not EL, but JSTL. – BalusC Dec 06 '19 at 09:25
28

If you want to iterate over tokens in string then simply use forTokens:

<c:set var="alphabet">A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z</c:set>

<c:forTokens items="${alphabet}" delims="," var="letter">
    ${letter}
</c:forTokens>
multitask landscape
  • 8,273
  • 3
  • 33
  • 31
7

If you use Java EE 7 / Expression Language 3.0 you can create a List literal

<c:set var="alphabet" value="${['A', 'B', 'C', ... , 'Z']}" />

which can then iterate over much like an Array.

mxxk
  • 9,514
  • 5
  • 38
  • 46
3

JSP's are not intended for this kind of stuffs. They are meant to consume, not create. If you want to create an array, then you probably need a Servlet here.

Add the logic of array creation (or even better, List creation), in a Servlet, and use it to pre-process the request to your JSP page. And then, you can use the List attribute set in the servlet in your JSP page.

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
3

Not pure EL, but a pretty clean solution nevertheless:

<c:set var="alphabet" value='<%=new String[]{"A", "B"} %>'/>
wvdz
  • 16,251
  • 4
  • 53
  • 90
2

Without knowing which framework are you using, the best approach to work with JSPs without using is scriptlets is to back every JSP (view) with a Java bean (an object):

Backing bean:

public class MyBackingBean {

   private List<String> alphabet;

   public List<String> getAlphabet() {
      if (alphabet == null) {
         // Using lazy initialization here, this could be replaced by a
         // database lookup or anything similar
         alphabet= Arrays.asList(new String[]{ "A", "B", "C", ... });
      }
      return alphabet;
   }

}

Then instantiate the bean at the JSP this way:

<jsp:useBean id="backingBean" scope="page" class="com.example.MyBackingBean" />

After that, you could use the EL ${backingBean.alphabet} to access that list.

Note: if you need more complex processing then you will have to use Servlets or any of the features provided by any framework.

Alonso Dominguez
  • 7,750
  • 1
  • 27
  • 37