본문 바로가기

tag library

EL로 자바 상수 사용방법

How do you reference an constants with EL on a JSP page?

I have an interface Addresses with a constant named URL. I know I can reference it with a scriplet by going: <%=Addresses.URL%>, but how do I do this using EL?

shareimprove this question
   
possible duplicate of Java constants in JSP – pyb Mar 13 '15 at 16:48
up vote113down voteaccepted

EL 3.0 or newer

If you're already on Java EE 7 / EL 3.0, then the @page import will also import class constants in EL scope.

<%@ page import="com.example.YourConstants" %>

This will under the covers be imported via ImportHandler#importClass() and be available as ${YourConstants.FOO}.

Note that all java.lang.* classes are already implicitly imported and available like so ${Boolean.TRUE} and ${Integer.MAX_VALUE}. This only requires a more recent Java EE 7 container server as early versions had bugs in this. E.g. GlassFish 4.0 and Tomcat 8.0.0-1x fails, but GlassFish 4.1+ and Tomcat 8.0.2x+ works.

This facility is only available in JSP and not in Facelets. In case of JSF+Facelets, your best bet is using OmniFaces <o:importConstants> as below:

<o:importConstants type="com.example.YourConstants" />

Or adding an EL context listener which calls ImportHandler#importClass() as below:

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

    @PostConstruct
    public void init() {
        FacesContext.getCurrentInstance().getApplication().addELContextListener(new ELContextListener() {
            @Override
            public void contextCreated(ELContextEvent event) {
                event.getELContext().getImportHandler().importClass("com.example.YourConstants");
            }
        });
    }

}

EL 2.2 or older

This is not possible in EL 2.2 and older. There are several alternatives:

  1. Put them in a Map<String, Object> which you put in the application scope. In EL, map values are accessible the usual Javabean way by ${map.key} or ${map['key.with.dots']}.

  2. Use <un:useConstants> of the Unstandard taglib (maven2 repo here):

    <%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
    <un:useConstants className="com.example.YourConstants" var="constants" />

    This way they are accessible the usual Javabean way by ${constants.FOO}.

  3. Use Javaranch's CCC <ccc:constantsMap> as desribed somewhere at the bottom of this article.

    <%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
    <ccc:constantsMap className="com.example.YourConstants" var="constants" />

    This way they are accessible the usual Javabean way by ${constants.FOO} as well.

  4. If you're using JSF2, then you could use <o:importConstants> of OmniFaces.

    <html ... xmlns:o="http://omnifaces.org/ui">
    <o:importConstants type="com.example.YourConstants" />

    This way they are accessible the usual Javabean way by #{YourConstants.FOO} as well.

  5. Create a wrapper class which returns them through Javabean-style getter methods.

  6. Create a custom EL resolver which first scans the presence of a constant and if absent, then delegate to the default resolver, otherwise returns the constant value instead.

shareimprove this answer
3 
I found this question because I was having the same problem when trying to use a static List field with a form:options tag. I was able to get it working by adding a non-static getter that returns the static list. It's a little kludgy but hey, that's JSP development for ya! – spaaarky21 Nov 1 '11 at 19:56
   
Do you have any example how to configure this for JSF if the beans are managed by spring? Thx in advance. – Lodger Nov 20 '13 at 20:48
2 
@Lodger: I don't do Spring. – BalusC Nov 20 '13 at 20:55
2 
Is the jakarta unstandard-taglib project still alive? is there some alternative? – davioooh Jun 25 '14 at 7:43 
   
Is there a way to leverage this techniques for enums? – Niklas Peter Dec 24 '15 at 9:13

You usually place these kinds of constants in a Configuration object (which has getters and setters) in the servlet context, and access them with ${applicationScope.config.url}

shareimprove this answer
   
Bit of a novice here when it comes to jsp's- could you explain that more fully? – tau-neutrino Sep 17 '10 at 4:33
1 
@tau-neutrino: Its simple actually. Create a class with url as a String property, name it Configuration, instantiate it and set the url to whatever you like. After that set that Configuration object inServletContext. Do something like, servletContext.setAttribute("config", config). And there you go. – Adeel Ansari Sep 17 '10 at 11:10 

You can't. It follows the Java Bean convention. So you must have a getter for it.

shareimprove this answer

The following does not apply to EL in general, but instead to SpEL (Spring EL) only (tested with 3.2.2.RELEASE on Tomcat 7). I think it is worth mentioning it here in case someone searches for JSP and EL (but uses JSP with Spring).

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="constant" expression="T(com.example.Constants).CONSTANT"/>
shareimprove this answer

I implemented like:

public interface Constants{
    Integer PAGE_SIZE = 20;
}

-

public class JspConstants extends HashMap<String, String> {

        public JspConstants() {
            Class c = Constants.class;
            Field[] fields = c.getDeclaredFields();
            for(Field field : fields) {
                int modifier = field.getModifiers();
                if(Modifier.isPublic(modifier) && Modifier.isStatic(modifier) && Modifier.isFinal(modifier)) {
                    try {
                        put(field.getName(), (String)field.get(null));
                    } catch(IllegalAccessException ignored) {
                    }
                }
            }
        }

        @Override
        public String get(Object key) {
            String result = super.get(key);
            if(StringUtils.isEmpty(result)) {
                throw new IllegalArgumentException("Check key! The key is wrong, no such constant!");
            }
            return result;
        }
    }

Next step put instance of this class into servlerContext

public class ApplicationInitializer implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute("Constants", new JspConstants());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

access in jsp

${Constants.PAGE_SIZE}
shareimprove this answer

Yes, you can. You need a custom tag (if you can't find it somewhere else). I've done this:

package something;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

/**
 * Get all class constants (statics) and place into Map so they can be accessed
 * from EL.
 * @author Tim.sabin
 */
public class ConstMapTag extends TagSupport {
    public static final long serialVersionUID = 0x2ed23c0f306L;

    private String path = "";
    private String var = "";

    public void setPath (String path) throws JspException {
        this.path = (String)ExpressionUtil.evalNotNull ("constMap", "path",
          path, String.class, this, pageContext);
    }

    public void setVar (String var) throws JspException {
        this.var = (String)ExpressionUtil.evalNotNull ("constMap", "var",
          var, String.class, this, pageContext);
    }

    public int doStartTag () throws JspException {
        // Use Reflection to look up the desired field.
        try {
            Class<?> clazz = null;
            try {
                clazz = Class.forName (path);
            } catch (ClassNotFoundException ex) {
                throw new JspException ("Class " + path + " not found.");
            }
            Field [] flds = clazz.getDeclaredFields ();
            // Go through all the fields, and put static ones in a Map.
            Map<String, Object> constMap = new TreeMap<String, Object> ();
            for (int i = 0; i < flds.length; i++) {
                // Check to see if this is public static final. If not, it's not a constant.
                int mods = flds [i].getModifiers ();
                if (!Modifier.isFinal (mods) || !Modifier.isStatic (mods) ||
                  !Modifier.isPublic (mods)) {
                    continue;
                }
                Object val = null;
                try {
                    val = flds [i].get (null);    // null for static fields.
                } catch (Exception ex) {
                    System.out.println ("Problem getting value of " + flds [i].getName ());
                    continue;
                }
                // flds [i].get () automatically wraps primitives.
                // Place the constant into the Map.
                constMap.put (flds [i].getName (), val);
            }
            // Export the Map as a Page variable.
            pageContext.setAttribute (var, constMap);
        } catch (Exception ex) {
            if (!(ex instanceof JspException)) {
                throw new JspException ("Could not process constants from class " + path);
            } else {
                throw (JspException)ex;
            }
        }
        return SKIP_BODY;
    }
}

and the tag is called:

<yourLib:constMap path="path.to.your.constantClass" var="consts" />

All public static final variables will be put into a Map indexed by their Java name, so if

public static final int MY_FIFTEEN = 15;

then the tag will wrap this in an Integer and you can reference it in a JSP:

<c:if test="${consts['MY_FIFTEEN'] eq 15}">

and you don't have to write getters!


'tag library' 카테고리의 다른 글

tag library function 사용  (0) 2014.08.08
jsp 커스텀태그  (0) 2014.08.07