-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify behavior for sealed types #693
Conversation
This is a proposal for discussion, but I believe it's good enough. I previously mentioned that we could make normal scoped records a definition error, but I figured it would be easier to just specify that they are unproxyable, which leads to a deployment problem. I didn't want to go through the same exercise with sealed types :-) |
Writing TCK tests for this is problematic as long as the TCK is compiled for Java 11. I'm not sure how to solve that problem. We can leave records and sealed types unspecified in CDI 4.1 and only specify them in CDI 5.0, where we could bump the Java version. |
@@ -81,7 +81,7 @@ The bean types of a bean are used by the rules of typesafe resolution defined in | |||
|
|||
Almost any Java type may be a bean type of a bean: | |||
|
|||
* A bean type may be an interface, a concrete class or an abstract class, and may be declared final or have final methods. | |||
* A bean type may be an interface, a concrete class or an abstract class or a record, may be declared sealed or non-sealed or final, and may have final methods. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* A bean type may be an interface, a concrete class or an abstract class or a record, may be declared sealed or non-sealed or final, and may have final methods. | |
* A bean type may be an interface, a concrete class, an abstract class or a record. It may be declared sealed, non-sealed or final, and may have final methods. |
Just a minor suggestion. The original sentence is somewhat long and hard to chew on, so splitting it in two might help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this confusing. Records and Sealed classes cannot be managed beans. Why do we call them out for Bean Types. Can you list a use case to support such a Record or Sealed Classes as bean types and then inject them to something else. I would not add them here at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Andrew's comment nicely sums this up #693 (comment)
Generally the use case is similar to why you would want to have a non-proxyable class (such as with no no-arg constructor) to be a bean - it is doable but only works until you try to assign it normal scope or use an interceptor.
We didn't have a specific case in mind; instead, the idea is to avoid introducing extra rules where we can apply what CDI already does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Records and sealed types can be managed beans. (They are unproxyable, so cannot be normal scoped or intercepted or decorated, but it's perfectly legal to make a record @Dependent
, as long as it defines a zero-param constructor, which it can. It is not very practical, but it is possible.)
But that's not the point here. There are other kinds of types that cannot be managed beans (such as interfaces) yet it makes perfect sense for them to be bean types. Maybe you're confusing bean types and bean classes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point is that it is VERY problmatically. I recommend not to list them out. If we call it out here, it encourages end users to use Records in anger if they just do a quick search on the doc.
The existing phrase A bean type may be an interface, a concrete class or an abstract class, and may be declared final or have final methods.
covers to Records, sealed classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we call it out here, it encourages end users to use Records in anger if they just do a quick search on the doc.
That is not an argument for or against anything. This is a specification, not a microwave oven manual.
You could argue that per JLS, a record class is "a restricted kind of class", so whatever applies to classes applies to records as well, which would be correct. So we don't necessarily have to call out records.
But that doesn't cover sealed types. We specify that a bean type may be final, but we don't specify whether it may be sealed, and until we do, it remains unspecified and hence non-portable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, just add sealed types then.
I am also wondering whether to clearly say what kind of injections an end user can do with Records. In order to inject a Record, it must be @Dependent
scoped and it must define a zero-arg constructor. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Records may be made beans by following the existing rules. Records are always final, so they are unproxyable, which means that a record bean cannot be normal scoped. That leaves @Singleton
and @Dependent
. It also has to have a zero-param constructor or an @Inject
constructor. All the usual. If you don't want to mention records here (because users would want to use them and because the information is redundant), why would we want to mention them elsewhere (causing the same "problems")?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, fine with not mentioning Record.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good and covers what we originally talked discussed.
Let's keep it open until next CDI meeting and see if anyone has comments on this.
The inability to test this is unfortunate but perhaps we can keep a tracking TCK issue with future version (5.0?) where we know the JDK version will be enough. It's the same case as with records and the lang model TCK. Personally, I think it's worth putting this into specification, even at the cost of missing TCK test.
One open question: should non-abstract sealed classes be managed beans? I opted into no, because it felt like the right thing to do, but I don't think there's anything fundamental preventing that from working. It's just that trying to inject it would likely lead to unresolved ambiguity, because all permitted subclasses of that class would have it among their bean types. |
Generally, I don't think there is much use for sealed classes as beans. |
That is correct, yes. |
I think I'd lean towards just reiterating how the existing rules apply to records and sealed classes, so that there aren't new rules to remember.
While I can't see a use case for a non-abstract sealed class being a managed bean, I also don't see a reason to have a special case to make it not be a managed bean. It also won't be discovered unless it has a scope annotation or the discovery mode is |
f3d06d0
to
24c15f5
Compare
Good point, I agree that we shouldn't impose additional rules other than what already falls out from the existing rules and new JLS/JVMS rules. I amended the PR. |
24c15f5
to
cdd9433
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I am in favor of merging this as-is.
Sealed types are valid bean types, but they are unproxyable. This commit only makes explicit what already implicitly follows from the existing CDI specification and updates in the Java / JVM specifications.
cdd9433
to
7fdaaff
Compare
Removed references to records, because records are a restricted form of classes that are always |
Sealed types are valid bean types, but they are unproxyable.
This commit only makes explicit what already implicitly follows from
the existing CDI specification and updates in the Java / JVM specifications.