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?
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.
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:
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.
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}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With