Closed GoogleCodeExporter closed 9 years ago
If we don't require explicit @Inject, I guarantee you that people *will* find
ways to avoid it
everywhere (you're right: "too noisy", they'll say), and then goodbye to any
hope of eyeballing
injection points. That "single, simple level of indirection" might as well be a
hundred complex
levels for those of us who read (and write) code in simple text editors. If
injection is indeed
to be the new "new", I need to be able to take the source of a Java class and
identify its
injection points as easily and directly as I can currently identify its
constructors.
Original comment by tpeie...@gmail.com
on 9 Sep 2009 at 1:13
An injection point should be explicit for sure just by looking at the code. Its
just a question of where the annotation goes; on the injection point or on the
qualifier
annotation.
Already JSR330 supports a level of indirection; qualifier annotations are
annotated with @Qualifier - so you need to comprehend the custom annotations
used at an
injection point to understand it already (even if you use a simple text
editor).
Given this - (whether this issue is accepted or not) - I'd recommend using a
modern IDE which includes a ton of powerful code comprehension, navigation,
visualisation & refactoring support rather than having to do 'levels of
indirection in your head'.
To cater for the simple text editor crowd, should we also avoid the existing
level of indirection with @Qualifier and force that to be added to the
injection point as
well to avoid the person reading code having to understand what the annotations
mean?
e.g.
public class VerboseCheese {
@Inject
@Qualifier // indicate that one of the other annotations is a qualifier to save you looking at the annotation definitions
@Red
DataSource customerDb;
...
}
There's a delicate balance of noise versus power here.
I don't think adding a level of indirection with @Inject on annotations is that
big a leap given we're already supporting annotated annotations with @Qualifier
on
annotations and this proposal will result in less noisy code - plus this
apparently simple change will let us re-work all existing injection mechanisms
defined by the
JCP to be JSR330 compliant (assuming the legacy annotations get JSR330
annotations).
BTW folks already use @Resource for example in JSR250 and EJB; I've not heard
any complaints yet from folks using simple text editors using those specs,
demanding an extra @Inject to be in there just in case.
Original comment by james.st...@gmail.com
on 9 Sep 2009 at 3:29
I like your proposal James, I think it effectively deals with 'legacy' IoC
specifications in a clean fashion wrt the resultant code.
Original comment by Larry.Ca...@gmail.com
on 10 Sep 2009 at 3:27
I agree that this is an important problem to solve, but I don't think
meta-annotating @Resource with @Inject is
the best solution.
I'd prefer we permit JSR 330 implementations to support legacy annotations
directly. The spec is wide open on
the configuration side, so I'd prefer to leave that up to the injectors. Guice
can already support @Resource
(thanks James!) and its own "legacy" @com.google.inject.Inject annotation.
Other injectors will have their own
legacy infrastructure to support, and I don't think it's worth the complexity
to bake this into the spec.
Original comment by limpbizkit
on 10 Sep 2009 at 3:56
well, for future specification versions of JSR-250 et al, I find it ok to
further
meta-annotate annotations like @Resource or @PersistenceContext, but imho we
should
not 'silently' change 'old' annotations. At least we should think _really_ long
about
it - the risk that we could introduce big problems for existing projects is
pretty high.
And btw, imho @Resource, @PersistenceContext and kinds are NO basic Java
entities but
EE and therefore _way_ out of scope for this very spec!
This should be discussed in other EGs anyway. If common-annotations 2 will use
JSR-330 @Inject then it would be cool - but that's not our duty.
> or made @Inject optional when using an annotation annotated with @Qualifier
+1
That's exactly what is defined in JSR-299, and imho this is pretty straight
forward.
Tooling support is not really an argument against it here. If a tool is able to
look
at @Inject, it will also be able to look if an annotation is meta-annotated with
@Qualifier.
Original comment by MarkStruberg@gmail.com
on 10 Sep 2009 at 4:25
@limpbizkit the thing is to support @Resource with say, Guice, we can only do
post-injection reflection to inject fields or call methods. Constructor
injection is
never gonna be supported.
e.g. this is not possible today with Guice...
public class Brie {
public Brie(@Resource('blah') DataSource ds) {...}
}
Also as a result of us hacking this in 'around the back' - Guice is not really
aware
of this injection taking place (so it won't be visible to DI tooling for
example).
This proposal allows legacy & custom annotations to be supported easily by all
JSR330
providers out of the box in a standard way using @Inject - it avoids developers
of
frameworks or the RIs of JSR250/EJB/JPA/JAXRS/Servlet3 of having to write N
custom
hooks to plug into each JSR330 provider (with different DI capabilities - e.g.
constructor injection never being possible with Guice).
The nice thing about this proposal is its a very minimal change to the JSR330
provider (looking for @Inject at the injection point and on its annotations -
which
JSR330 already mandates for @Qualifier anyway); but it really helps unify all
the
various DI mechanisms that exist today in the JavaSE platform into all the
possible
JSR330 providers. I think that unification has lots of merit (having suffered
lots of
pain already using various JCP standards which have forms of injection with
various
DI containers today which offer varying degrees of plugin support).
Original comment by james.st...@gmail.com
on 10 Sep 2009 at 4:26
fair points! thinking about it I agree that the individual EE/SE specifications
should own the responsibility for revising their injection annotations (or not)
to be meta annotated via @Inject ... as long as we permit/enable it from a 330
perspective
Original comment by Larry.Ca...@gmail.com
on 10 Sep 2009 at 4:44
@james.strachan: "Constructor injection is never gonna be supported"
Well, we've had it for a few months, so never-say-never!
http://code.google.com/p/google-guice/wiki/ToConstructorBindings
I can see the problem of getting N frameworks to work with M JSR 330
implementations seems is infeasible.
But rather than retrofitting the frameworks' existing annotations, would it be
simpler to just migrate the
application code to support the vanilla JSR 330 annotations? I don't really
want to carry @Resource around
with me for the rest of my life.
The broader problem is that each of these frameworks have their own interesting
semantics. I'm skeptical that
we can map the weird and wonderful behaviours of JSR250/EJB/JPA/JAXRS/Servlet3
to the streamlined 330
model.
Original comment by limpbizkit
on 10 Sep 2009 at 6:55
I'm with Tim and Jesse on this one.
I don't care about making things easier for injector implementors if it results
in less
maintainable code. We should keep 330 simple.
The indirection of @Qualifier is different. You only have to look for it when
@Inject is
present.
While it would be nice if we always view code in smart IDEs w/ JSR-330 support,
the
reality is that online code review tools are just one of several exceptions.
It also appears as though you're blurring the line between injection and
qualifier
annotations. To support your example:
public class Brie {
public Brie(@Resource('blah') DataSource ds) {...}
}
You'd just need to annotate @Resource w/ @Qualifier.
Original comment by crazybob...@gmail.com
on 10 Sep 2009 at 10:49
@crazybob In that case it'd not work, you'd also need to add an @Inject onto it
too
like this.
public class Brie {
@Inject
public Brie(@Resource('blah') DataSource ds) {...}
}
Unless as @limpbizkit mentioned, for every occurrence of @Resource you wrote
some
explicit binding code (or a provider method) which kinda misses the whole point
of
the @Resource in the first place (to avoid having to write custom binding code
in
guice/spring).
i.e. so this means none of the existing IoC related JCP specifications could be
supported out of the box with JSR330 (250, EJB, JPA, JAXRS) without littering
@Inject
everywhere - which is a big shame IMHO.
BTW I don't buy the code review argument either; pretty much everyone knows what
@Resource is for from JSR250 or what @PersisenceContext is for from JPA or what
@Context is for from JAXRS - if not its very trivial to do a quick lookup in the
javadoc. We're talking a handful of annotations period in JCP specifications.
Maybe this just means 330 is always gonna be simple for "guice style" IoC only
(@Inject mandatory everywhere unless you hand craft binding/providers) and 299
is
where the IoC unification of the JavaSE and JavaEE specifications goes then?
Original comment by james.st...@gmail.com
on 11 Sep 2009 at 7:55
James, JSR 330 configuration is not the same as Guice configuration. We can
write JSR 330 injectors that support
@Resource and @Context naturally, using their existing semantics. But there's
no need to pen that into the JSR
330 spec, or to meta-annotate anything.
Original comment by limpbizkit
on 11 Sep 2009 at 8:05
Correct, Jesse. Users can already use JSR-330 and 250 together w/o any
additional
specification.
Original comment by crazybob...@gmail.com
on 11 Sep 2009 at 8:15
Another way to look at this: if @Inject is supposed to mark "places that can be
injected" then the current @Target list of constructors, methods, and fields is
correct. But you can't inject an annotation, so marking them with @Inject would
technically be at odds with the meaning (unless that was changed of course).
Also what happens if I have an annotation that can be put on a class (as well
as the
usual fields, methods, etc.) and I decide to decorate it with @Inject - this
could
confuse developers who might then expect to be able inject all members in a
class
using this annotation. What if someone uses two levels of annotation
indirection?
I can certainly see how decorating @Resource would be helpful, but I agree with
Tim
that this could really diminish the benefits of @Inject (and also blur its
meaning).
Original comment by mccu...@gmail.com
on 11 Sep 2009 at 8:53
FYI, the 299 group has done a lot of thinking about the relationship between
Java EE
component environment injection, and the new-style typesafe injection, and this
is
addressed in the 299 specification.
Original comment by gavin.k...@gmail.com
on 11 Sep 2009 at 3:31
I discourage users from using @Resource altogether. Your example should just be:
public class Brie {
@Inject Brie(DataSource ds) { ... }
}
If you have more than one DataSource impl, use a qualifier:
public class Brie {
@Inject Brie(@ReadOnly DataSource ds) { ... }
}
Original comment by crazybob...@gmail.com
on 11 Sep 2009 at 8:20
Original issue reported on code.google.com by
james.st...@gmail.com
on 9 Sep 2009 at 12:40