Using CDI to inject a Data Access Object - dependency-injection

Assuming I have a data access object that I've already written, I'd like to be able to use CDI to inject that into say, a service class. Furthermore, I have two implementations of that DAO.
My understanding of CDI is that I'd have to annotate my DAO implementation class so that CDI would know which implementation to inject.
The problem is, the DAO is in a .jar file. By annotating it with CDI annotations, I'm using JavaEE imports in a non-JavaEE class.
For example, let's say I have the following class
public class BusinessService {
#Inject #SomeMybatisQualifier AccountDAO accountDao;
...
}
The #Inject annotation comes from javax.inject.Inject. Now, this service class is dependent on a JavaEE environment.
Can someone please explain to me what I'm missing? How do I inject a non-annotated class into another non-annotated class? This is fairly simple with Spring.

I agree with LightGuard if there's enough classes. But for a couple, why not just produce them with #Produces?
Here's a decent example of implementing your own producer:
Depedency inject request parameter with CDI and JSF2
You should be able to write return new MyObject(); and you can add whatever qualifiers you want
Not sure what's unclear but here's the gist of things: For CDI to scan a jar for beans it must have a beans.xml. Else it will not be scanned and thus not available for injects.A String is not available either. If you try to inject a String say;
#Inject
String myString;
CDI will have no clue what to give you just like your jar. But I know what String I want (a requestparam) and I can let CDI know as well. How? Well I supply a qualifier #RequestParam to my producer (see example again) and now when I want to use it in client code I do it like this:
#Inject
#RequestParam
String myString;
You can do the same thing. Have a producer and just create a new instance of whatever you need and then return it. Now CDI will know just how to dependency inject that particular bean.
Now say you have 40 classes. Then it gets messy to produce them and you want to make sure it gets scanned instead. Then you write your own little extension, observe when CDI is about to scan and instruct it to scan additional jars. Such extension is probably easy to write but I don't know the details because I have not written any extensions like it

By far, the easiest thing would be to create a CDI extension to add the classes in the jar (because there's no beans.xml in that jar so it won't be picked up by CDI) and add additional qualifiers to the metadata.

Related

How to inject an e4view with Guice injection

I am working on an existing Eclipse RCP based on Luna which consists of 99% 3.x API. We want to change this in an ongoing process; so when I was given the task of creating a new view, I wanted to use the new (in Luna, anyways) e4view element for the org.eclipse.ui.views extension point.
My problem is that part of the RCP uses xtext and thus, several components are available by using Guice.
I am now stranded with something like this
public class MyViewPart
{
#Inject // <- should be injected via Guice (I used #com.google.inject.Inject, otherwise E4DI would complain)
ISomeCustomComponent component;
#PostConstruct // <- should be called and injected via E4 DI
public void createView(Composite parent)
{
// ...
}
}
To get this injected with Guice, I would usually use an AbstractGuiceAwareExecutableExtensionFactory (as usually done in Xtext contexts) like this:
<plugin>
<extension
point="org.eclipse.ui.views">
<e4view
class="my.app.MyExecutableExtensionFactory:my.app.MyViewPart"
id="my.app.view"
name="my view"
restorable="true">
</e4view>
</extension>
</plugin>
But I did not expect this to work, because I thought it would bypass the E4 mechanism (actually, it seems to be the other way round and the e4view.class element seems to ignore the extension factory and just uses my.app.MyViewPart to inject it with E4DI. To be sure, I have set a class loading breakpoint to MyViewPart which is hit from ContextInjectionFactory.make()).
As I said, I didn't expect both DI frameworks to coexist without conflict, so I think the solution to my problem would be to put those object which I need injected into the E4 context.
I have googled a bit but I have found multiple approaches, and I don't know which one is the "correct" or "nice" one.
Among the approaches I have found, there are:
providing context functions which delegate to the guice injector
retrieving the objects from guice and configure them as injector bindings
retrieving the objects from guice, obtain a context and put them in the context
(The first two approaches are mentioned in the "Configure Bindings" section of https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection)
And of course I could get the objects from Guice in the MyViewPart implementation, but that's not what I want...
[Edit:] In the meantime I have explored the options above a bit more:
Context Functions
I tried to register the context functions as services in the Bundle Activator with this utility method:
private void registerGuiceDelegatingInjection(final BundleContext context, final Class<?> clazz)
{
IContextFunction func = new ContextFunction()
{
#Override
public Object compute(final IEclipseContext context, final String contextKey)
{
return guiceInjector.getInstance(clazz);
}
};
ServiceRegistration<IContextFunction> registration =
context.registerService(IContextFunction.class, func,
new Hashtable<>(Collections.singletonMap(
IContextFunction.SERVICE_CONTEXT_KEY, clazz.getName()
)));
}
and called registerGuiceDelegatingInjection() in the BundleActivator's start() method for each class I needed to be retrieved via Guice.
For some reason, however, this did not work. The service itself was registered as expected (I checked via the OSGi console) but the context function was never called. Instead I got injection errors that the objects could not be found during injection. Maybe the context functions cannot be contributed dynamically but have to be contributed via declarative services, so they are known as soon as the platform starts?
(Answer here is: yes. As the JavaDoc to IContextFunction says: Context functions can optionally be registered as OSGi services [...] to seed context instances with initial values. - and since the application context already exists when my bundle is started, the dynamically registered service is not seen by the ContextFactory in time).
Injector Bindings
I quickly found out that this solution does not work for me, because you can only specify an interface-class to implementation-class mapping in the form
InjectorFactory.getDefault().addBinding(IMyComponent.class).implementedBy(MyComponent.class)
You obviously cannot configure instances or factories this way, so this is not an option, because I need to delegate to Guice and get Guice-injected instances of the target classes...
Putting the objects in the context
This currently works for me, but is not very nice. See answer below.
[Edit 2:] As I have reported, putting the objects in the (application) context works for me. The downside is that having the objects in the application context is too global. If I had two or more bundles which would require injection of object instances for another DSL, I would have to take care (e.g., by using #Named annotations) to not get the wrong instance injected.
What I would like better is a way to extend the Part's context with which my e4view is created and injected directly. But so far I have not found a way to explicitly target that context when putting in my instances ...
Thanks for any further hints...
Try the processor mechanism of E4: You should be using a (Pre or Post) Processor (along with the PostContextCreate annotation) to register your POJOs into the (global) IEclipseContext.
The solution that worked for me best so far was getting the IEclipseContext and put the required classes there myself during the bundle activator's start() method.
private void registerGuiceDelegatingInjection(final BundleContext context, final Class<?> clazz)
{
IServiceLocator s = PlatformUI.getWorkbench();
IEclipseContext ctx = (IEclipseContext) s.getService(IEclipseContext.class);
ctx.set(clazz.getName(), guiceInjector.getInstance(clazz));
}
This works at least for now. I am not sure how it works out in the future if more bundles would directly put instances in the context; maybe in the long-term named instances would be needed. Also, for me this works, because the injected objects are singletons, so it does not do any harm to put single instances in the context.
I would have liked the context function approach better, but I could not get it to work so far.

CDI and multiple instances

I'm just investigating possibilities of DI frameworks and I made some stupid example for it. I have simple service.
public class Service implements ServiceI {
private Source source;
private Translator translator;
#Inject
public Service(Translator translator, Source source) {
this.translator = translator;
this.source = source;
}
I want to have two instances of this service one which is initiated with TranslatorA and SourceA and second which will be injected with different values.
How can one have two instances with different beans injected inside?
I'm interested in ways how to achieve this in both Guice and Weld CDI.
So far I created multiple Guice modules and specify bind-to in it as I like. But I'm not completely sure if it is correct way. And this completely fails in CDI as there are no modules.
I thing that having multiple instances must be pretty common case or am I wrong?
The way you would do this with CDI is by setting up a producers for translator and source. It's the only way to control which implementations are used for injection at runtime. The implementation details may vary based on your exact needs but something like this should get you on the right track
#Produces
public Translator produceTranslator(#Dependent TranslatorA implA, #Dependent TranslatorB implB) {
return checkRuntimeCondition() ? implA : implB;
}
And the same for the source. That way when you inject Service, CDI'll call the producer method for each parameter and use a runtime condition to select the implementation. YMMV on the details, you may need to set up additional qualifiers to avoid ambiguity.

The benefits and correct usage of a DI Container

I'm having troubles getting the advantage of a IoC (DI) container like Ninject, Unity or whatever. I understand the concepts as follows:
DI: Injecting a dependency into the class that requires it (preferably via constructor injection). I totally see why the less tight coupling is a good thing.
public MyClass{
ISomeService svc;
public MyClass(ISomeService svc){
svc = svc;
}
public doSomething(){
svc.doSomething();
}
}
Service Locator: When a "container" is used directly inside the class that requires a dependancy, to resolve the dependancy. I do get the point that this generates another dependancy and I also see that basically nothing is getting injected.
public MyClass{
public MyClass(){}
public doSomething(){
ServiceLocator.resolve<ISomeService>().doSomething();
}
}
Now, what confuses me is the concept of a "DI container". To me, it looks exactly like a service locator which - as far as I read - should only be used in the entry point / startup method of an application to register and resolve the dependancies and inject them into the constructors of other classes - and not within a concrete class that needs the dependancy (probably for the same reason why Service locators are considered "bad")
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
public void main(){
DIContainer.register<ISomeService>(new SomeService());
// ...
var myclass = new MyClass(DIContainer.resolve<ISomeService>());
myclass.doSomething();
}
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
DI containers are supposed to help you create an object graph quickly. You just tell it which concrete implementations you want to use for which abstractions (the registration phase), and then it can create any objects you want want (resolve phase).
If you create the dependencies and pass them to the constructor (in the application initialization code), then you are actually doing Pure DI.
I would argue that Pure DI is a better approach in many cases. See my article here
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
I would say yes. You should create the object graph when your application starts up. This is called the composition root.
If you need to create objects after your application has started then you should use factories (mainly abstract factories). And such factories will be created with the other objects in the composition roots.
Your classes shouldn't do much in the constructor, this will make the cost of creating all the dependencies at the composition root low.
However, I would say that it is OK to create some types of objects using the new keyword in special cases. Like when the object is a simple Data Transfer Object (DTO)

Advantages of WebServiceGatewaySupport vs WebServiceTemplate

I have to implement a webservice client using Spring WS.
I've read the documentation at http://static.springsource.org/spring-ws/site/reference/html/client.html but it's not clear to me what are the advantages of extending WebServiceGatewaySupport versus directly using WebServiceTemplate in my service class.
As far as I can tell from the source, the WebServiceGatewaySupport only has a couple of wrapper methods for the WebServiceTemplate and some initialization support.
So why should I extend WebServiceGatewaySupport instead of directly using a WebServiceTemplate ?
Thank you!
I think this sums it all up (found in the client reference you linked):
Alternatively, consider deriving from Spring-WS's
WebServiceGatewaySupport convenience base class, which exposes
convenient bean properties to enable easy configuration. (You do not
have to extend this base class... it is provided as a convenience
class only.)
So, if the WebserviceTemplate offers all you need, that'll probably suffice. If you need anything extra you can use the WebServiceGatewaySupport as an example on how to wrap your own convenience methods around the WebserviceTemplate.
In my client software, I just configure the WebserviceTemplate in my #Configuration class like this:
#Bean
public WebServiceTemplate webServiceTemplate() {
WebServiceTemplate template = new WebServiceTemplate();
template.setMessageFactory(messageFactory());
template.setDefaultUri(defaultUri);
template.setMarshaller(marshaller());
template.setUnmarshaller(marshaller());
template.setInterceptors(new ClientInterceptor[] {interceptor()});
return template;
}
(All the method calls are references to other methods in the configuration which aren't that relevant in this example).
I can use that bean everywhere in my code to send messages.

Where to keep guice injectors?

What is your advice?
I found most suitable for me solution - keep injectors and modules in enumeration classes.
Advantages:
injectors and modules created once,
injectors can be used from different classes while running application (not only at bootstrap),
injectors kept in one place and can be easily found.
Example:
import static ru.package.Modules.*;
public enum Injectors {
FOO_INJECTOR(BarModule.module()),
FOO2_INJECTOR(FOO_INJECTOR.injector(),
Bar2Module.module(), FooModule.module());
private final Injector m_injector;
Injectors (Module... modules) {
m_injector = Guice.createInjector(modules);
}
Injectors (Injector parentInjector, Module... modules) {
m_injector = parentInjector.createChildInjector(modules);
}
public Injector injector() {
return m_injector;
}
}
You appear to be fundamentally misunderstanding how dependency injection works. If you are trying to use a reference to Injector anywhere in your code besides the place where you bootstrap the application, you're not using dependency injection, you're using it as a Service Locator instead. You're forced to prepare an Injector whenever you need to test a class and your classes do not make it clear in their constructors exactly what their dependencies are (since who knows what they'll get out of the Injector in some method if they have or can get a reference to it). Actually, using enum as you've described here is even worse than that: you cannot change the configuration at all, even for testing, because your modules are hardcoded into the enum.
With dependency injection, classes declare their dependencies only and allow the Injector, working transparently (after the initial call to get the root application object), to provide all those dependencies. This makes understanding, testing and changing functionality in your code relatively easy. Anyway, I'd suggest learning more about how DI and Guice are intended to be used... you really should not want to do this.
The bigger question is why?
There should be no need to keep the Injector around, because once the injection is done the Injector should be done and should disappear.
If, however, you really need the Injector, couldn't you simply:
#Inject
private Injector injector;
Is this application web based or is it standalone?

Resources