-
1. Re: Dynamic Injection
gavin.king Dec 29, 2009 6:18 PM (in response to meetoblivion)I don't understand your problem. (Your explanation is missing about 3 steps.) Perhaps you just need to use an AnnotationLiteral to instantiate the SomeQualifier instance.
-
2. Re: Dynamic Injection
meetoblivion Dec 29, 2009 6:47 PM (in response to meetoblivion)I don't think I need to instantiate the SomeQualifier instance. I'm not sure what 3 steps I'm missing, so that's probably why they're missing. Basically, for a given Foo, it can help me make a Bar with some reusable business logic, but it's all tied to the Foo instance. so that means when I @Inject @SomeOtherQualifier(key="",foo=@SomeQualifier(key1="",key2="")) Bar bar; I'm essentially going to have to look up the dynamic Foo instance based on the foo parameter of my SomeOtherQualifier, right?
Another question, is this going to end up being scoped properly? If my Foo instances are all ApplicationScoped, it's not going to produce a new Foo each time, right?
-
3. Re: Dynamic Injection
gavin.king Dec 29, 2009 7:10 PM (in response to meetoblivion)So you're telling me you want to have to write @SomeOtherQualifier(key="",foo=@SomeQualifier(key1="",key2="")) at the injection point? I figured you were trying to avoid that. You have a qualifier for one object that embeds the qualifier of another object? That sounds kinda awful. It's not how qualifiers are really mean to be used.
I'm essentially going to have to look up the dynamic Foo instance based on the foo parameter of my SomeOtherQualifier, right?Well, if the generic producer that produces the Bar can't directly inject the Foo because the qualifier of the Foo depends upon the instance of Bar, then you need to do a lookup. Just inject @Any Instance<Foo> into the producer method.
But since your Foo producer method needs an InjectionPoint, you can't use lookup in this case.
Look, I think you need to take a step back, actually describe your real requirements (without Foos and Bars) so that I can understand what you're actually trying to achieve.
-
4. Re: Dynamic Injection
meetoblivion Dec 29, 2009 7:34 PM (in response to meetoblivion)Ok (and it's going to require a bit of knowledge of DNA's APIs). No, I do not think it's a clean way using the interwoven Qualifiers, but I can't think of any other way to do it.
You start with an object called JcrConfiguration. This will be created once, application level, and only one exists. This is a forget about it object, it needs to exist, but you only need it to pull out other objects. I want to make this configurable to some level (on start up, it reads an XML file to configure itself, and the path to this XML file is likely to end up in the annotation). JcrConfiguration has a method start() that creates a JcrEngine object. The way I see it, I need to wrap the call to this start() in a Producer as I will need the JcrEngine to create javax.jcr.Repository and javax.jcr.Session instances. In theory, you could have multiple JcrConfiguration/JcrEngines, simply by having them be
@Inject @NamedJcrEngine("/path/to/my/config.xml") JcrEngine engine1; @Inject @NamedJcrEngine("/path/to/another/config.xml") JcrEngine engine2;
instances of javax.jcr.Repository are going to be dynamic, e.g. the code I'm working on will not be aware of what Repositories will be created, it'll be up to the application that uses this library to determine that. The complication comes in at this point. I want my code to be able to produce the Repository without being aware ahead of time what JcrEngine will be needed. The way I see it, the best way to do this is to have my Repository annotated as:
@Inject @NamedRepository(name="AuditRepo",engine=@NamedJcrEngine("/path/to/my/config.xml")) Repository repo1Engine1; @Inject @NamedRepository(name="ProductRepo",engine=@NamedJcrEngine("/path/to/my/config.xml")) Repository repo2Engine1; @Inject @NamedRepository(name="SillyRepo",engine=@NamedJcrEngine("/path/to/another/config.xml")) Repository repo1Engine2;
Which means that my producer for repositories would need to lookup the JcrEngine for the given engine attribute on the annotation.
And please let me know if it just sounds way too difficult, as what I'm trying to mimic is how a <bean ref=""/> works in spring, except by making it more dynamic.
-
5. Re: Dynamic Injection
alin.heyoulin.qq.com Dec 29, 2009 7:55 PM (in response to meetoblivion)Right, currently i modify weld code to support spring bean inject(@Autowire). and intergrate spring jpacontainer and transaction(@Transactional).So i can use two framework advantage.
I love weld's observer,fireEvent,type safe,decorators....
I also love spring's dynamic inject,xml config...... -
6. Re: Dynamic Injection
asookazian Dec 29, 2009 8:04 PM (in response to meetoblivion)
he youlin wrote on Dec 29, 2009 19:55:
I also love spring's dynamic inject,xml config......How does Spring do dynamic injection? via proxies? I couldn't find anything on this in google...
-
7. Re: Dynamic Injection
alin.heyoulin.qq.com Dec 29, 2009 8:14 PM (in response to meetoblivion)I can create xml in runtime and create beans by beanfactory. I don't know if this is dynamic injection.
-
8. Re: Dynamic Injection
gavin.king Dec 29, 2009 8:34 PM (in response to meetoblivion)
No, I do not think it's a clean way using the interwoven Qualifiers, but I can't think of any other way to do it.A qualifier is a way of selecting between pre-defined implementations, it's not meant for defining things. You can't just embed your Spring XML bean definition into a qualifier, that's not what it's for. OK, so InjectionPoint lets you push the boundary on this a bit, but not very far.
So what you are looking for is a way to define a generic set of inter-related beans. The usual way to define a bean in CDI is to write a Java class or producer method. But that's not the only way. The portable extension SPI let's you read some other metadata source, and create and register a Bean object. The
other metadata source
could be an XML or properties file, or course, or it could be an annotation on a field, method, class or interface.For these kinds of problems, a portable extension is the right solution. An earlier revision of the spec did have the notion of
realization
which was designed to address cases like this where you want to definegeneric
producer methods that are inherited by subclasses, but with different qualifiers. But that feature didn't make it (probably a good thing, too). -
9. Re: Dynamic Injection
gavin.king Dec 29, 2009 8:35 PM (in response to meetoblivion)
he youlin wrote on Dec 29, 2009 20:14:
I can create xml in runtime and create beans by beanfactory. I don't know if this is dynamic injection.Yick! How is this not a much uglier solution than CDI's portable extension SPI?
-
10. Re: Dynamic Injection
gavin.king Dec 29, 2009 8:45 PM (in response to meetoblivion)By
these kinds of problems
, I mean cases where you want to specify a single item of metadata, and have that result in the creation of multiple beans. -
11. Re: Dynamic Injection
alin.heyoulin.qq.com Dec 29, 2009 8:59 PM (in response to meetoblivion)
For these kinds of problems, a portable extension is the right solutionI'm glad to see it and hope seam3 will do for me.
Yick! How is this not a much uglier solution than CDI's portable extension SPI?Yes,this just a example. In my project i don't use like that.
By these kinds of problems, I mean cases where you want to specify a single item of metadataYes,but i really want to reuse some whole function of spring include it's metadata.
-
12. Re: Dynamic Injection
meetoblivion Dec 29, 2009 9:07 PM (in response to meetoblivion)Hmm. I kind of get what you're saying. In this case though, the instances represented by JcrEngine and javax.jcr.Session should belong to different scopes (JcrEngine should be @ApplicationScoped and Session should be @RequestScoped). At runtime, the JcrEngine should be created when the application gets initialized - e.g. a Singleton bean should have something like @Inject @MyQualifier JcrEngine engine. I'm not looking to precreate the instances either, they should be created
So besides the fact that it looks a bit ugly and that it somewhat borders programming xml/programming annotations, is there a big issue if I use the initial approach? I really don't get what's going to end up being so different in the code if I use a portable extension vs annotations and producer methods.
I assume at some level, I'm still going to have an annotation that's pointing to an properties/xml file, rather than just inferring the configuration based on the annotation, right?
-
13. Re: Dynamic Injection
gavin.king Dec 29, 2009 9:23 PM (in response to meetoblivion)
Hmm. I kind of get what you're saying. In this case though, the instances represented by JcrEngine and javax.jcr.Session should belong to different scopes (JcrEngine should be @ApplicationScoped and Session should be @RequestScoped). At runtime, the JcrEngine should be created when the application gets initialized - e.g. a Singleton bean should have something like @Inject @MyQualifier JcrEngine engine. I'm not looking to precreate the instances either, they should be createdRight, that's the point I'm trying to make. You have a bunch of different objects with different lifecycles and different scopes. Even if I was to use Seam2 or Spring XML, I would need multiple bean definitions for every JCR respository. I just don't think that's the right way. Much better to write a portable extension that picks up a single item of metadata defining the repository and creates all the beans relating to that repository.
So besides the fact that it looks a bit ugly and that it somewhat borders programming xml/programming annotations, is there a big issue if I use the initial approach? I really don't get what's going to end up being so different in the code if I use a portable extension vs annotations and producer methods.Your initial approach just wasn't going to work. It's broken. You just can't use qualifiers like that.
-
14. Re: Dynamic Injection
gavin.king Dec 29, 2009 10:19 PM (in response to meetoblivion)So I've been bothered for a while by these kinds of problems. I experimented with the
realization
stuff in the spec, but honestly that didn't quite work out, so we ditched it. I think the problem was that I had my head too much in how existing products like Spring or Seam2 solve the problem with XML, and that was blocking my creativity. Today I came up with a much better, much simpler solution than XML. I don't think we can easily, elegantly implement this as a portable extensions right now (though I think it's possible with some inelegance), but we can do it once I have some new SPI features that are already on the wishlist. Alternatively, perhaps this stuff is cool enough to add to the actual spec in 1.1.The idea is that you can define a set of
generic beans
for a specificconfig annotation
like @MessageBus. These beans can inject the configuration, and can inject each other.@Generic(MessageBus.class) @ApplicationScoped class Topic { @Inject MessageBus config; }
@Generic(MessageBus.class) @RequestScoped class Session { @Inject Topic topic; @Inject MessageBus config; }
You can then add the config annotation to a producer field, together with whatever qualifier annotations you need:
@Produces @MessageBus(topic="default") Topic topic; @Produces @Prices @MessageBus(topic="prices") Topic prices; @Produces @Deals @MessageBus(topic="deals") Topic deals;
And now, finally, we can inject the
configured objects
:@Inject Topic topic; @Inject Session session; @Inject @Prices Topic topic; @Inject @Prices Session session; @Inject @Deals Topic topic; @Inject @Deals Session session;
The trick here is that the @Prices Session gets the @Prices Topic injected, along with @MessageBus(topic="prices") , and the @Deals Session gets the @Deals Topic injected, along with @MessageBus(topic="deals").
WDYT?