从JSP访问HashMultimap时出现异常的原因是什么

时间:2015-03-04 15:41:02

标签: java spring jsp guava

我有一个Spring MVC控制器,它在范围/模型中添加了一个Guava HashMultimap。然后,JSP读取该数据结构以显示每个应用程序的角色列表:

在控制器中:

HashMultimap<Long,Role> rolesByApp = HashMultimap.create();
//... fill the multimap
model.addAttribute("rolesByApp", rolesByApp);

在JSP中:

<c:forEach items="${applications}" var="app" varStatus="s1">
    <c:set var="appRoles" value="${rolesByApp.get(app.id)}"/>
    <!-- for each role display a checkbox, etc. -->
</c:forEach>

当我尝试从IllegalAccessException读取时,我在JSP的c:set行上得到HashMultiMap

java.lang.IllegalAccessException: Class javax.el.BeanELResolver can not access a member of class com.google.common.collect.AbstractSetMultimap with modifiers "public volatile"

它不会一直发生,也许在我的开发机器(Mac)上有4次中有3次。在服务器上它一直运行良好(Red Hat Linux)。它曾经在我的开发机器上正常工作,当我开发它时,我在Win7下。

如果我将HashMultimap<Long,Role>替换为HashMap<Long, List<Role>>,它也可以正常工作。

我不明白这个错误。可能是什么原因?

3 个答案:

答案 0 :(得分:2)

在使用MultiMap构建数据结构的同时,我公开了Map视图,而不是MultiMap本身:

model.addAttribute("rolesByApp", rolesByApp.asMap());

在JSP中我替换了

<c:set var="appRoles" value="${rolesByApp.get(app.id)}"/>

<c:set var="appRoles" value="${rolesByApp[app.id]}"/>

这可以解决错误。

我仍然不知道上一次错误的原因。如果有人可以复制并解释错误,我会接受答案。否则我最终会接受我自己的解决方法。

答案 1 :(得分:1)

请注意com.google.common.collect.Multimap 实施java.util.Map

因此,除非您在Servlet 3.0兼容容器中运行代码,否则JSTL表达式语言不支持Multimap。 JSTL-specification指出,如果应用了JSTL表达式的对象既没有实现java.util.List,也没有实现java.util.Map,JSTL期望Java-Bean标准符合getter。

这意味着对于Servlet 2而言,必须将Multimap转换为&#34; normal&#34;在将其交给JSP之前映射,以便使用JSTL表达式访问映射。

答案 2 :(得分:1)

Code使用反射来访问该方法。由于它不时地工作并且仅在Mac上工作,因此它产生的问题是它与JDK实现有关。手上的问题是由我猜这个JDK的安全经理造成的。尝试安装OpenJDK(顺便说一下你使用的JDK)并使用不同的JDK并在问题仍然存在时重试。

如果第二个JDK没有引起问题,请尝试将问题最小化到可以重现问题并使用visualVM或(远程)调试器来访问和理解手头的问题。将您拥有的所有内容发送给JDK开发人员团队,并享受发现错误。

您也可以尝试使用自己的Reflection方法访问相关方法,看看它是否也失败。

问题是有效的问题并且不是基于显然随机的属性...