2

I have a Spring MVC controller that adds a Guava HashMultimap to the scope/model. The JSP then reads that data structure to display a list of roles per application :

In controller :

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

In 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>

I get an IllegalAccessException on the c:set line of the JSP, when trying to read from the HashMultiMap :

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

It doesn't happen all the time, maybe 3 out of 4 times on my dev machine (Mac). On the server it works fine all the time (Red Hat Linux). It used to work fine on my dev machine too, at the time I was developing it I was under Win7.

If I replace the HashMultimap<Long,Role> with a HashMap<Long, List<Role>> it also works fine.

I don't understand this error. What could be the cause ?

Pierre Henry
  • 16,658
  • 22
  • 85
  • 105
  • 1
    Related to http://stackoverflow.com/q/12037489/502399 maybe? – Tavian Barnes Mar 04 '15 at 19:14
  • @Tavian : while the error is similar, I would not think the cause is the same. In the question you pointed, the cause is access to a private inner class' members. This is not the case here. The get() method of HashMultiMap returns a HashSet, which is standard Java Collections class. Also, the error as in this other question would happen consistently I would guess. – Pierre Henry Mar 06 '15 at 09:27

3 Answers3

2

While still using the MultiMap to build the data structure, I exposed its Map view instead of the MultiMap itself :

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

And in the JSP I replaced

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

with

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

This fixes the error.

I still don't know the reason of the previous error. If somebody can reproduce and explain the error, I will accept the answer. Otherwise I will eventually accept my own workaround.

Pierre Henry
  • 16,658
  • 22
  • 85
  • 105
1

Keep in mind that com.google.common.collect.Multimap does NOT implement java.util.Map.

Hence Multimap it is not supported by the JSTL expression language unless you are running your code in a Servlet 3.0 compatible container. The JSTL-specification states that if the object a JSTL-expression is applied to is neither implementing java.util.List or java.util.Map, JSTL expects a Java-Bean standard conform getter.

This means for Servlet 2 and lower you have to convert a Multimap to a "normal" map before handing it over to a JSP in order to access the map with JSTL expressions.

Fritz Duchardt
  • 11,026
  • 4
  • 41
  • 60
  • Makes sense, and it is finally how I made it worked. However, as to [this answer](http://stackoverflow.com/questions/7121303/how-to-call-parameterized-method-from-jsp-using-jstl) and [this oracle doc](http://docs.oracle.com/cd/E19798-01/821-1841/bnahu/index.html) (section Parameterized Method Calls), since Servlet 3.0 spec, you can call any method including with parameters, from JSP using EL. At least that is how I understand it. And the code I posted worked most of the time too. If it were an unsupported operation, I suppose it would never work. – Pierre Henry Mar 13 '15 at 11:14
  • Thank you - good points - I have updated my answer accordingly. – Fritz Duchardt Mar 13 '15 at 16:22
1

The Code uses reflection to access the method. Since it works from time to time and only on Mac it makes problems it seams to be related to the JDK implementation. The problem on the hand is caused by the security manager of this JDK I guess. Try to install OpenJDK (what JDK are you using by the way) and use a different JDK and retry if the problem is still present.

If the second JDK does not cause problems try to minimize your problem down to the point where you can reproduce the problem and use visualVM or a (remote) debugger to access and understand the problem at hand. Send everything you have to the JDK developer team and enjoy having found a bug.

You can also try to access the method in question using your own Reflection method and see if it also fails.

It is problematic to have a problem that works and works not based on appearently random properties... .

Martin Kersten
  • 5,127
  • 8
  • 46
  • 77
  • It actually fails only on the Mac :) Anyway, it is the same. And this might well be a bug of the JDK so +1. I use JDK 8 from Oracle on Mac, Win and Linux. But I must admit I feel a bit lazy to do all the testing right now, especially since I have a workaround that is almost cleaner. Maybe when I have time, and it's not weekend, and I am recovered from that damn cold ;-) – Pierre Henry Mar 13 '15 at 16:40
  • Well ok. Best would be to install OpenJDK then and try it. Since the Mac is almost of non importance when it comes to running a server, the community might survive your laziness :-). – Martin Kersten Mar 13 '15 at 16:48
  • Last time I looked, I couldn't find an OpenJDK 8. Is there one ? – Pierre Henry Mar 13 '15 at 17:06
  • Yes but on the homepage of openJDK.java.net it still says : "Download and install the open-source JDK 7 for most popular Linux distributions. If you came here looking for Oracle JDK 8 product binaries for Solaris, Linux, Mac OS X, or Windows, which are based largely on the same code, you can download them from java.oracle.com." :-/ – Pierre Henry Mar 16 '15 at 08:36
  • Interesting. I havent got it either. I installed Oracle JDK 8 two days before for linux. Maybe they had ditched the afford. Curious. – Martin Kersten Mar 17 '15 at 16:45
  • Yeah, I don't quite get it either. It was nice to be able to apt-get jdk or jre. – Pierre Henry Mar 17 '15 at 16:51
  • I have high hopes for Ceylon :-). Would solve many issues if we have a good alternative. But I guess it might even take two or three more years. – Martin Kersten Mar 17 '15 at 17:39