Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Map value with the null key inside JSP

Tags:

java

jsp

map

el

I have a Map<Integer, Object> in passed to JSP from a controller. There is a null key with a default value, that means map.get(null) returns a default object. keyObject.keyProp is Integer and might be null.

When I use this in jsp

<c:out value="${map[keyObject.keyProp]}"/>

I do not get any output for the null keys. Is there any way to make null keys work in jsp?

like image 864
kenor Avatar asked Jan 17 '13 21:01

kenor


People also ask

Can we use null as key in map?

Yes, null is always a valid map key for any type of map key (including primitives, sobjects, and user-defined objects). Do you mean doing something like this? Map<String, String> myMap = new Map<String, String>{}; myMap. put('key1', null);

How do I assign a null value to a map?

Get the set view of the Map using Map. entrySet() method. Convert the obtained set view into stream using stream() method. Now map the null values to default value with the help of map() method.

How does HashMap handle null values?

HashMap puts null key in bucket 0 and maps null as key to passed value. HashMap does it by linked list data structure. HashMap uses linked list data structure internally. In Entry class the K is set to null and value mapped to value passed in put method.

How check map is empty or not in JSP?

Try this <c:if test="${not empty hiringManagerMap}"> . It should check for both null and empty. Please read this for more details if you need to check other collections or maps for being empty.


1 Answers

It seems that the only way of getting the value for the null key using standard EL implementation is to call get() method on the map (considering that you said keyObject.keyProp resolves to Integer object):

<c:out value="${map.get(keyObject.keyProp)}" />

I tested this solution and it works.

Actually, in this case, you can easily do without <c:out />, just use plain EL where you need it, e.g.

${map.get(keyObject.keyProp)}

Simple example:

TestMapServlet.java

package com.example;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import java.util.Map;
import java.util.HashMap;

import java.io.IOException;

public class TestMapServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
        Map<Integer, Object> map = new HashMap<Integer, Object>();
        Integer noValueInt = null;
        Integer one = new Integer(1);
        Integer two = new Integer(2);

        map.put(noValueInt, "Default object for null Integer key");
        map.put(one, "Object for key = Integer(1)");
        map.put(two, "Object for key = Integer(2)");

        request.setAttribute("map", map);
        request.setAttribute("noValueInt", noValueInt);
        request.setAttribute("one", one);
        request.setAttribute("two", two);

        request.getRequestDispatcher("/test-map.jsp").forward(request, response);
    }
}


test-map.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
    <title>Home Page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <h1>Testing access to java.util.Map using just EL</h1>
    <p><b>\${map.get(noValueInt)}</b>: ${map.get(noValueInt)}</p>
    <p><b>\${map[one]}</b>: ${map[one]}</p>
    <p><b>\${map[two]}</b>: ${map[two]}</p>

    <h1>Testing access to java.util.Map using JSTL and EL</h1>
    <p><b>&lt;c:out value="\${map.get(noValueInt)}" /&gt; </b>: <c:out value="${map.get(noValueInt)}" /></p>
    <p><b>&lt;c:out value="\${map[one]}" /&gt; </b>: <c:out value="${map[one]}" /></p>
    <p><b>&lt;c:out value="\${map[two]}" /&gt; </b>: <c:out value="${map[two]}" /></p>

    <h2>Printing java.util.Map keys and values (when Key = null, the <i>null</i> won't be shown)</h2>
    <c:forEach items="${map}" var="entry">
        <p><b>Key</b> = "${entry.key}", <b>Value</b> = "${entry.value}"</p>
    </c:forEach>
</body>
</html>


web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <servlet>
        <servlet-name>Test Map Servlet</servlet-name>
        <servlet-class>com.example.TestMapServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Test Map Servlet</servlet-name>
        <url-pattern>/TestMap.do</url-pattern>
    </servlet-mapping>

</web-app>


IMPORTANT NOTE
To be able to invoke methods with arguments using EL you must use minimum Servlet version 3.0.
Quote from here: https://stackoverflow.com/tags/el/info

Since EL 2.2, which is maintained as part of Servlet 3.0 / JSP 2.2 (Tomcat 7, Glassfish 3, JBoss AS 6, etc), it's possible to invoke non-getter methods, if necessary with arguments.


Apart from the above solution you could use custom Unified Expression Language implementation such as JUEL that has an alternative solution.

An explanation why it is not possible (in the standard implementation) to access map value by the null key using [] and the custom solution can be found in Java Unified Expression Language (JUEL) documentation (emphasis in paragraphs is mine):

2.5. Advanced Topics

...

Enabling/Disabling null Properties

The EL specification describes the evaluation semantics of base[property]. If property is null, the specification states not to resolve null on base. Rather, null should be returned if getValue(...) has been called and a PropertyNotFoundException should be thrown else. As a consequence, it is impossible to resolve null as a key in a map. However, JUEL's expression factory may be configured to resolve null like any other property value. To enable (disable) null as an EL property value, you may set property javax.el.nullProperties to true (false).

Assume that identifier map resolves to a java.util.Map.

  • If feature javax.el.nullProperties has been disabled, evaluating ${base[null]} as an rvalue (lvalue) will return null (throw an exception).

  • If feature javax.el.nullProperties has been enabled, evaluating ${base[null]} as an rvalue (lvalue) will get (put) the value for key null in that map. The default is not to allow null as an EL property value.

...

Hope this will help.

like image 65
informatik01 Avatar answered Sep 22 '22 00:09

informatik01