Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.IllegalAccessException: can not access a member of class java.util.Collections$UnmodifiableCollection with modifiers "public"

Tags:

el

jsf-2

I have classes PrimitiveProperty and ComplexProperty and the interface Property. I want to create an implementation of Property which enforces an empty unmodifiable Set of Property instances as return value of Property.getProperties, e.g.

public interface Property {
    Set<Property> getProperties();
}

public class ComplexProperty implements Property {
    private Set<Property> properties; 
    //getter overrides the interface method
}

public class PrimitiveProperty implements Property {
    private final static Set<Property> EMPTY_PROPS = Collections.unmodifiableSet(new HashSet<Property>(1));

    @Override
    public Set<Property> getProperties() {
        return EMPTY_PROPS;
    }
}

With Glassfish 4.0 and I'm getting

java.lang.IllegalAccessException: Class javax.el.ELUtil can not access a member of class java.util.Collections$UnmodifiableCollection with modifiers "public"

when I access the property in the leaf attribute of a Richfaces tree, e.g.

<r:tree id="aTree" 
        toggleType="ajax" var="item" >
  <r:treeModelRecursiveAdaptor roots="#{aCtrl.roots}" 
                               nodes="#{item.properties}" leaf="#{item.properties.isEmpty()}">
    <r:treeNode>
      #{item.name}
    </r:treeNode>
    <r:treeModelAdaptor nodes="#{item.properties}" leaf="#{item.properties.isEmpty()}"/>
  </r:treeModelRecursiveAdaptor>
</r:tree>

The issue disappears if I make the EMPTY_PROPS constant modifiable (by assigning an instance of HashSet instead of the return value of Collections.unmodifiableSet) which is not my intention.

Is it possible to achieve what I want to do? Do I have to invent or use an implementation of what Collections$UnmodifiableCollection ('s subclasses) do(es) which is compatible with the JSF access needs?

like image 353
Kalle Richter Avatar asked Jul 29 '14 16:07

Kalle Richter


People also ask

What is illegalaccessexception in Java?

When an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, if that method is not accessible to your application (probably the modifier is private or not accessible one), then your application will throw java.lang.IllegalAccessException.

Is unmodifiableset a public class in Java?

Although it implements Collection, which is public, the UnmodifiableSet implementation itself, where EL (read: Reflection API) is trying to find the method on the class, is not public. Exactly this problem is reproducible in plain Java (a main () method) as follows:

Does JDBC driver 11g (ojdbc6) cause illegal access exception?

But, after upgrading to JDBC driver 11g (ojdbc6.jar), the application fails with an illegal access exception. The same error reproduces from a JDBC standalone application.


1 Answers

Here is the problem:

leaf="#{item.properties.isEmpty()}"

You're attempting to invoke a method directly on the UnmodifiableSet instance. Although it implements Collection, which is public, the UnmodifiableSet implementation itself, where EL (read: Reflection API) is trying to find the method on the class, is not public.

Exactly this problem is reproducible in plain Java (a main() method) as follows:

Set<Object> set = Collections.unmodifiableSet(new HashSet<>());
for (Method method : set.getClass().getMethods()) {
    if ("isEmpty".equals(method.getName())) {
        method.invoke(set); // IllegalAccessException.
    }
}

This is essentially a bug in the EL implementation used.

You'd better just use EL's own empty operator:

leaf="#{empty item.properties}"
like image 123
BalusC Avatar answered Oct 19 '22 17:10

BalusC