Skip to content
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

Add support for single non no-arg constructor injection without @Inject #548

Merged
merged 2 commits into from
Jan 18, 2019

Conversation

geoand
Copy link
Contributor

@geoand geoand commented Jan 17, 2019

Basically when the bean has a single constructor that contain arguments,
then the @Inject annotation is not necessary, since the injection point
can be safely deduced.
This is analogous to what Spring DI does since Spring 4.3

@geoand geoand changed the title Add support for single no-arg constructor injection without @Inject Add support for single non no-arg constructor injection without @Inject Jan 17, 2019
Basically when the bean has a single constructor that contain arguments,
then the @Inject annotation is not necessary, since the injection point
can be safely deduced.
This is analogous to what Spring DI does
@mkouba
Copy link
Contributor

mkouba commented Jan 17, 2019

So this is definitely against the spec. On the other hand, we don't run TCK and not even try to be fully spec-compliant. It really depends on how useful you guys think this "feature" is. @emmanuelbernard @stuartwdouglas @FroMage @Sanne and others?

@Sanne
Copy link
Member

Sanne commented Jan 17, 2019

Not my area of expertise, but out of curiosity: by "against the spec" you mean the spec doesn't mention anything like this, or is it explicitly prohibiting such a thing to work?

In the second case, might be good to know why they did that.. might have good reasons?

(Other than that doubt I personally like it!)

@mkouba
Copy link
Contributor

mkouba commented Jan 17, 2019

@Sanne http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#instantiation and http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#declaring_bean_constructor. So stricly speaking the constructor should not be found. But I don't think there is a tck test that would fail...

@manovotn @antoinesd Your opinion?

@manovotn
Copy link
Contributor

This is definitely against CDI spec so the real question here is how much you want this implementation to pretend it's CDI compliant and how much you want to step away and say you are creating a different (C)DI implementation.

Settings that aside, I think this is more of a syntactic sugar rather then anything else. Bean with just one constructor cannot be a CDI bean anyway, as you need a no-args one by definition, so I think it should work.

@mkouba
Copy link
Contributor

mkouba commented Jan 17, 2019

Bean with just one constructor cannot be a CDI bean anyway, as you need a no-args one by definition..

Hm, I disagree. A bean with non-normal scope can either have no-args constructor or a constructor with @Inject -> and this PR is only about the possibility to omit the @Inject annotation.

@manovotn
Copy link
Contributor

Sorry, I wasn't clear. In my previous comment I meant that a class that has only once constructor and that one is parameterized.
In such a case, without the @Inject annotation, CDI will blow up complaining it doesn't have a no-args one. Hence as a programmer, if you wanted that class to become a bean, you simply missed the @Inject annotation which is something this PR addresses.

@Sanne
Copy link
Member

Sanne commented Jan 17, 2019

@Sanne http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#instantiation and http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#declaring_bean_constructor. So stricly speaking the constructor should not be found. But I don't think there is a tck test that would fail...

The bean constructor may be identified by annotating the constructor @Inject.

My reading of the spec is that it describes one way which is expected to work. The language is open-ended, it doesn't preclude you to offer additional ways of constructing such beans.

As long as you don't violate the definition:

The bean constructor is a default-access, public, protected or private constructor of the bean class.

I'd argue you'd still be allowed to call this a CDI implementation (if not for missing other things..)

@manovotn
Copy link
Contributor

@Sanne this part of spec http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#what_classes_are_beans states that:

It has an appropriate constructor - either:

  • the class has a constructor with no parameters, or
  • the class declares a constructor annotated @Inject.

@Sanne
Copy link
Member

Sanne commented Jan 17, 2019

@manovotn good catch. That section is indeed more restrictive

@emmanuelbernard
Copy link
Member

If the change makes sense, let's push for a change in the spec.

@geoand
Copy link
Contributor Author

geoand commented Jan 17, 2019

If the change makes sense, let's push for a change in the spec.

I know that I use the respective Spring capability whenever the opportunity arises :P, so from my point of view it makes a lot of sense

@stuartwdouglas
Copy link
Member

I think we should include it and try and change the spec.

@manovotn
Copy link
Contributor

Yea, we can make a proposal for sure. I'll put up an issue tomorrow

@manovotn
Copy link
Contributor

FYI, created CDI-742. Feel free to add any remarks and notes.

@geoand
Copy link
Contributor Author

geoand commented Jan 18, 2019

So do we merge this in the meantime or wait?

@emmanuelbernard
Copy link
Member

+1 to merge

@manovotn
Copy link
Contributor

I'd say merge, one might grow a beard before there is next CDI release ;-)

@mkouba
Copy link
Contributor

mkouba commented Jan 18, 2019

@geoand Ok, so we agreed that this "feature" should be merged. Now let's polish the code a little ;-)

@geoand
Copy link
Contributor Author

geoand commented Jan 18, 2019

@mkouba Of course! What sort of polish do you have in mind?

// if the class has a single non no-arg constructor that is not annotated with @Inject,
// the class is not a non-static inner or and it not a superclass of of a bean
// we consider that constructor as an injection
if (injections.isEmpty() && isFirstLevel) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The injections list contains all injection points found, i.e. injections.isEmpty() returns false if any injection point (field, method) is found. If you add @Inject Head head2 field to your test it fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very interesting case I hadn't thought of :).
I will see how it can be fixed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just check isFirstLevel first and then proceed if there is no injection for which Injection.isConstructor() returns true ;-)

Copy link
Contributor Author

@geoand geoand Jan 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I'm thinking as well, but I'm trying to think if it would fail in any case - but probably not :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Should I also rebase onto the current master?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there are conflicts it should not really matter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No conflicts, so I'll leave as is then

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkouba Tests passed with the latest fix. Is there anything else you would like to see?

@mkouba mkouba merged commit 660f064 into quarkusio:master Jan 18, 2019
@mkouba
Copy link
Contributor

mkouba commented Jan 18, 2019

@geoand Thanks for your contribution ;-)

@geoand
Copy link
Contributor Author

geoand commented Jan 18, 2019

@mkouba You are most welcome!

@geoand geoand deleted the single-constructor branch January 18, 2019 10:23
@cescoffier cescoffier added this to the 0.7.0 milestone Jan 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants