[
https://issues.jboss.org/browse/CDI-565?page=com.atlassian.jira.plugin.sy...
]
Martin Andersson edited comment on CDI-565 at 10/9/15 9:39 AM:
---------------------------------------------------------------
Emily, good to have you here. You wrote:
{quote}
.. optional injection forces the end users to check for null, which is boilerplate code in
most scenarios and confusing.
{quote}
I must say that this statement is just wrong. The user doesn't have to do anything.
With the proposed change, all CDI applications remain the same. We are talking about
trading a "premature" CDI specific exception type, {{DeploymentException}} for
the more specialized and well known {{NullPointerException}} during runtime. The fallacy
in the CDI specification is that it treat an unsatisfied dependency as a problem. Section
"5.2.2. Unsatisfied and ambiguous dependencies"
{quote}
If an unsatisfied .. dependency exists, the container automatically detects the problem
and treats it as a deployment problem.
{quote}
But we know an unsatisfied dependency cannot always be treated as a problem. Contrary to
what you stated, I had hoped all experienced Java developers abide to the principle of not
writing "paranoid" null checks all over the code unless null is expected.
Because +if+ and +when+ null is a problem, we will face a NPE exactly +where+ that problem
surface. In a sense, nothing could ever be more clear or easily debugged and understood.
If you don't agree with me, please share your thoughts. Until then, I say that
checking for null, which is what all CDI implementations currently do, is the boilerplate
code. It saddens me that they are enforced to act in this way with quite possibly the only
result achieved being a reduced feature set offered to the application developer.
Today, when the application want to have an optional dependency, then he has to write,
yeah that's right: *boilerplate code*.. to circumvent the normal lookup mechanism and
take the route through {{Instance}} which is not the first API most people learn about.
Even more so, {{Instance}} will provide you with all the available injection targets. If
your application only expected one to be present, any more than so would be ambiguous,
then the application has to add it's own {{@PostContruct}} method that crash bean
initialization if more than just one target was found. Compare all this *boilerplate code*
to the simple use of one annotation {{@Inject}} which automatically, and with all right,
treat many targets of the same kind being ambiguous.
So if this proposition goes through, the "intuitive" approach would enrich CDI:s
service offer and vastly reduce boilerplate code that all those applications in need of
optional dependencies has to write. Like any other normal Java application, those that do
require their dependency to be present will face the world's most known exception
type: NPE. I say we reach out a hand to them by introducing the {{@Required}} annotation.
Today, I believe that in this context, CDI work in an unintuitive way only to destroy its
own usability and API simplicity. Again, the real question for us to answer, or vote on,
is what the most intuitive approach is. If the most intuitive approach break backward
compatibility, then the change has to wait to the next major release. Me personally, I
would also like someone to give their view as to why CDI:s injection mechanism is
semantically different from {{Map.get()}}?
was (Author: martin.andersson):
Emily, good to have you here. You wrote:
{quote}
.. optional injection forces the end users to check for null, which is boilerplate code in
most scenarios and confusing.
{quote}
I must say that is just wrong. The user doesn't have to do anything. With the proposed
change, all CDI applications remain the same. We are talking about trading a
"premature" CDI specific exception type, {{DeploymentException}} for the more
specialized and well known {{NullPointerException}} during runtime. The fallacy in the CDI
specification is that it treat an unsatisfied dependency as a problem. Section
"5.2.2. Unsatisfied and ambiguous dependencies"
{quote}
If an unsatisfied .. dependency exists, the container automatically detects the problem
and treats it as a deployment problem.
{quote}
But we know an unsatisfied dependency cannot always be treated as a problem. Contrary to
what you stated, I had hoped all experienced Java developers abide to the principle of not
writing "paranoid" null checks all over the code unless null is expected.
Because +if+ and +when+ null is a problem, we will face a NPE exactly +where+ that problem
surface. In a sense, nothing could ever be more clear or easily debugged and understood.
If you don't agree with me, please share your thoughts. Until then, I say that
checking for null, which is what all CDI implementations currently do, is the boilerplate
code. It saddens me that they are enforced to act in this way with quite possibly the only
result achieved being a reduced feature set offered to the application developer.
Today, when the application want to have an optional dependency, then he has to write,
yeah that's right: *boilerplate code*.. to circumvent the normal lookup mechanism and
take the route through {{Instance}} which is not the first API most people learn about.
Even more so, {{Instance}} will provide you with all the available injection targets. If
your application only expected one to be present, any more than so would be ambiguous,
then the application has to add it's own {{@PostContruct}} method that crash bean
initialization if more than just one target was found. Compare all this *boilerplate code*
to the simple use of one annotation {{@Inject}} which automatically, and with all right,
treat many targets of the same kind being ambiguous.
So if this proposition goes through, the "intuitive" approach would enrich CDI:s
service offer and vastly reduce boilerplate code that all those applications in need of
optional dependencies has to write. Like any other normal Java application, those that do
require their dependency to be present will face the world's most known exception
type: NPE. I say we reach out a hand to them by introducing the {{@Required}} annotation.
Today, I believe that in this context, CDI work in an unintuitive way only to destroy its
own usability and API simplicity. Again, the real question for us to answer, or vote on,
is what the most intuitive approach is. If the most intuitive approach break backward
compatibility, then the change has to wait to the next major release. Me personally, I
would also like someone to give their view as to why CDI:s injection mechanism is
semantically different from {{Map.get()}}?
Unsatisfied dependency should be null?
--------------------------------------
Key: CDI-565
URL:
https://issues.jboss.org/browse/CDI-565
Project: CDI Specification Issues
Issue Type: Feature Request
Components: Beans
Reporter: Martin Andersson
What if I am writing a component that call a collaborator only if that class exist during
runtime? It is amazingly intuitive to write code like this:
{code:java}
class MyComponent
{
@Inject
SomeCollaborator collaborator;
public void someMethod() {
// .. do something
if (collaborator != null) {
collaborator.callback();
}
}
}
{code}
But the specification currently says in section "5.2.2. Unsatisfied and ambiguous
dependencies" that this code should cause a "deployment problem". IIRC,
GlassFish 4.1 and WildFly 9 doesn't actually crash during deployment. They will inject
{{null}}. WebLogic 12, I just learned, do crash during deployment.
I believe it is unfortunate to have this null value logic for no apparent reason. It is
inevitably so that the application code would crash anyways as soon as it tries to
dereference a null reference. And you probably agree with me that there's a general
guideline established in the developer community which say you shouldn't do null
pointer checks all over the code because null pointers will crash exactly when and where
the absence of a value really is a problem.
The work around is to inject an {{Instance}} of my type and iterate through all of them,
or do any other form of programmatic lookup. However, me personally, I've had this
requirement far too many times now. It is often the case that a component I write has a
"subframework" in place such that when I want to affect how the application
performs, I can just add in new classes of a particular type and it is scoped up. Please
don't even make the notion of a design smell out of your own lack of creativity, if
you want to see a concrete example then of course I am more than happy to provide you with
that. Just saying =)
Something so intuitive and present in our every day coding life as a "null return
value" should be present in the CDI specification too. I mean that is what the
specification in essence is; one huge {{lookupInstanceOf(class)}}-method. Reading this
method name, would you really expect it to crash, or return {{null}}?
How about adding in a new annotation such that the injection point accept null values for
unsatisfied dependencies, but if the injection point has an annotation {{@Required}}, then
an unsatisfied dependency do crash for this injection point?
You will probably say "let's do it the other way around so that we don't
brake backward compatibility" by creating an {{@Optional}} annotation. Hey, if I am
abusive to my wife and she divorce me. Should I continue to be abusive to my next wife so
that I don't break backward compatibility? Our number one goal should be to define the
most awesome specification and API possible - nothing else. If we keep leaving small piles
of poo everywhere, then we will inevitably end up deep in shit.
Thank you all for your hard work and time devoted to making all of our lives so much
greater.
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)