[cdi-dev] [JBoss JIRA] (CDI-527) allow proxying of classes with non-private final methods

Mark Struberg (JIRA) issues at jboss.org
Tue Dec 15 03:59:00 EST 2015

    [ https://issues.jboss.org/browse/CDI-527?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13141075#comment-13141075 ] 

Mark Struberg commented on CDI-527:

I wrote down a summary of the problem and possible solutions for proxying with final fields:

Java8 introduced a few final methods to existing classes.
This now leads to a javax.enterprise.inject.UnproxyableResolutionException at bootstrap if you have a producer method or field for those classes.

EJB also seemingly allows this. 
But it's specced on a completely different level.
EJB disallows final 'business methods'.
That means that whenever you have an interface only those methods will get proxied.
The methods of the implementation do not matter at all.
With NIV all methods are 'business methods' and must be proxyable imo (can someone verify this?).

I personally like the non-proxyable rule.
It really prevents tons o user errors.
As you all know CDI heavily relies on subclassing proxies. 
Means we override all methods from the proxied type.
But we obviously cannot override (and thus proxy) static, private and final methods.
While static and private methods do not really matter, all non-private non-static final methods do.
The problem appears when people invoke such a final method on the proxy.
In that case they will just hit the proxy and not the Contextual Instance.
To prevent the user from making this error we throw the UnproxyableResolutionException at bootstrap.

We now have a few options to deal with that:

A.) no it's not a problem at all. 
 - We often got the report for ConcurrentHashMap. 
 But people can already just use the ConcurrentMap interface as return type in their producers.
 - Also the report that this only makes a problem since Java8 is plain wrong imo.
 ConcurrentHashMap has the following method since at least Java7:
 	final V put(K key, int hash, V value, boolean onlyIfAbsent)
 - There are a few situations where it hurts though.
 E.g. extending ConcurrentHashMap with own functionality. 
 This would require introducing an own interface for this new functionality.

B.) Generally allow proxying of beans with final methods.
 - I'm rather -1 for this.
 The current behaviour was introduced exactly because people made too many errors and blew up at runtime.
 Removing this rule would really make things worse.
 Because people might then add new final methods. 
 And if you call those then you will only hit the proxy class and not the Contextual Instance.
C.) Introduce an annotation to explicitly declare Beans to be proxyable
 - Something like @AllowProxying
 Can be applied to producer methods, producer fields and managed beans.
 - That would make it explicit for programmers that they leave the sunshine path.
 People will blow up with the UnproxyableResolutionException and can then decide whether they want to provide that bean anyway or not.
 - Con: Only the author of the Producer or managed bean knows that he added it. 
 Thus other users will first need to look at the producer to become aware.
 But that might not be so much of a problem in most cases as it's only a matter of JavaDoc.
D.) Introduce an exclude list for knowingly 'bad' classes.
 - We could e.g. introduce that all classes from java.* and javax.* are proxyable by definition.
 - Con: hard to know what's going on and why the code doesn't work if a user calls such a final method.

> allow proxying of classes with non-private final methods
> --------------------------------------------------------
>                 Key: CDI-527
>                 URL: https://issues.jboss.org/browse/CDI-527
>             Project: CDI Specification Issues
>          Issue Type: Feature Request
>          Components: Beans
>    Affects Versions: 1.2.Final
>            Reporter: Mark Struberg
>            Assignee: Mark Struberg
>             Fix For: 2.0 (proposed)
> Currently we explicitly disallow proxying of classes with non-private final methods. 
> EJB _does_ allow this. And there are a few final methods in the JDK and other libs. E.g. HashMap#initHashSeedAsNeeded. Currently we cannot have a producer method for it.
> We might rethink our decision and allow it. Probably with an own annotation like @AllowProxying which disables this check for certain cases (subclass managed-beans or producers).

This message was sent by Atlassian JIRA

More information about the cdi-dev mailing list