Context & Dependency Injection : How to inject implementation of an interface? - dependency-injection

I am at beginner stage of CDI and trying to inject the implementation of interface using field injection as below:
AutoService.java
package com.interfaces;
public interface AutoService {
void getService();
}
BMWAutoService.java
package com.implementations;
import javax.inject.Named;
import com.interfaces.AutoService;
#Named("bmwAutoService")
public class BMWAutoService implements AutoService {
public BMWAutoService() {
// TODO Auto-generated constructor stub
}
#Override
public void getService() {
System.out.println("You chose BMW auto service");
}
}
AutoServiceCaller.java
package com.interfaces;
public interface AutoServiceCaller {
void callAutoService();
}
AutoServiceCallerImp.java
package com.implementations;
import javax.inject.Inject;
import javax.inject.Named;
import com.interfaces.AutoService;
import com.interfaces.AutoServiceCaller;
public class AutoServiceCallerImp implements AutoServiceCaller {
#Inject
#Named("bmwAutoService")
private AutoService bmwAutoService;
public AutoServiceCallerImp() {
}
#Override
public void callAutoService() {
bmwAutoService.getService();
}
}
TestDisplayMessage.java
package com.tests;
import com.implementations.AutoServiceCallerImp;
import com.interfaces.AutoServiceCaller;
public class TestDisplayMessage {
public TestDisplayMessage() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
AutoServiceCaller caller = new AutoServiceCallerImp();
caller.callAutoService();
}
}
When I run TestDisplayMessage.java , the expected result would be "You chose BMW auto service" but I get NullPointerException as below :
Exception in thread "main" java.lang.NullPointerException
at com.implementations.AutoServiceCallerImp.callAutoService(AutoServiceCallerImp.java:21)
at com.tests.TestDisplayMessage.main(TestDisplayMessage.java:16)
Couldn't figure out exactly what I am missing here. Please help.Thanks in advance.

Ok, it seems you misunderstood the concept of CDI a bit - the idea is that you leave the bean lifecycle to CDI container. That means CDI will create a dispose beans for you. In other words, you are not supposed to create beans by calling new. If you do that, CDI does not know about it and will not inject anything into it.
If you are in SE environment, which I think you are since you use main method to test, you want to use Weld (CDI implementation) SE artifact (I guess you do that).
There, you will need to start the CDI container. Note that if you were developing a classical EE application on a server, you don't do this, because the server will handle it for you. Now, the very basic way to boot Weld SE container is:
Weld weld = new Weld();
try (WeldContainer container = weld.initialize()) {
// inside this try-with-resources block you have CDI container booted
//now, ask it to give you an instance of AutoServiceCallerImpl
AutoServiceCallerImpl as = container.select(AutoService.class).get();
as.callAutoService();
}
Now, second issue with your code. The usage of #Named is intended for EL resolution. E.g. in JFS pages, so you can access the bean directly. What you probably want is to differentiate between several AutoService implementations and choose a given one. For that CDI has qualifiers. Check this documentation section for more information on how to use them.

Related

How to use DependencyInjection in BenchmarkDotNet?

I'd like to use BenchmarkDotNet on some legacy code I'm working with right now. It is written in C# Net462.
It is a big, old and complex system and I'd like to Benchmark some methods inside some specific class. Those classes use dependency injection and I'm not sure how I could do it. All the examples I've seen so far are not using any dependency injection.
Does anyone have any ideas or examples I could have a look?
Thank you very much.
You need to create the dependency injection container in the ctor or a method with [GlobalSetup] attribute, resolve the type that you want to benchmark and store it in a field. Then use it in a benchmark and dispose the DI container in a [GlobalCleanup] method.
Pseudocode:
public class BenchmarksDI
{
private IMyInterface _underTest;
private IDependencyContainer _container;
[GlobalSetup]
public void Setup()
{
_container = CallYourCodeThatBuildsDIContainer();
_underTest = _container.Resolve<IMyInterface>();
}
[Benchmark]
public void MethodA() => _underTest.MethodA();
[GlobalCleanup]
public void Cleanup() => _container.Dispose();
}

.net framework- how to create IServiceProvider to get already registered service instance using IServiceProvider?

On .NET Framework 4.6.2 application, where there is no built-in DI container we are using LightInject DI Container to object initialization but don't know how to create 'IServiceProvider' Object in Main() so the other class implementations can get the already registered instance of service via IServiceProvider without using new keyword.
How to create IServiceProvider object? in .net framework 4.6.2 application
public class Program
{
public static void Main()
{
var container = new ServiceContainer();
// calls below extension method
container.RegisterDependencies();
}
}
public static class LightInjectDIExtension
{
/// Registers the application dependencies.
public static void RegisterDependencies(this ServiceContainer container)
{
container.Register<IBackgroundService1, BackgroundService1>();
container.Register<Service2>();
}
}
Once IServiceProvider instance is available to use, I'm intended to do the below
// This is background service app & this class will be
// instantiated once in application lifetime
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceProvider _serviceProvider;
public BackgroundService1(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_serviceProvider.GetService(typeof(Service2));
service2.CallMe();
}
}
Modification after Steven's suggestion
public class BackgroundService1 : IBackgroundService1
{
private readonly IServiceContainer_container;
public BackgroundService1 (IServiceContainer container)
//Exception thrown: 'System.InvalidOperationException' in LightInject.dll
{
_container = container;
}
public void Method1(string elementName)
{
// every time call to 'Method1' has to get the new instance
// of registered 'Service2' class rather than using 'new'
// keyword
var service2 = (Service2)_container.GetInstance(typeof(Service2));
service2.CallMe();
}
}
In general, injecting an IServiceProvider (or any abstraction that gives access to an unbound set of dependencies is a bad idea, because it can lead to the Service Locator anti-pattern. A discussion on this anti-pattern can be found here.
A Service Locator is something that only exists outside the Composition Root. Your BackgroundService1, however, might be part of the Composition Root, which might injecting a DI Container -or an abstraction there over- a feasible solution. Note that you should strive keeping all business logic out of the Composition Root. This ensures that BackgroundService1 purely functions as a mechanical peace of code that delegates the operation to classes that run the actual business logic.
Though, when operating inside the Composition Root, there is typically no need to use an abstraction over your DI Container, such as an IServiceProvider. The Composition Root already has intrinsic knowledge over all application's dependencies, including your DI Container.
This means that you can inject LightInject's ServiceContainer directly into the constructor of BackgroundService1; there is no need for an IServiceProvider.
If, however, you insist in using the IServiceProvider abstraction, you can create an IServiceProvider implementation that wraps ServiceContainer and forwards its GetService method to the wrapped ServiceContainer. This wrapper class can than be registered in the ServiceContainer.

Need Clarification about Dependency Inversion Example

Im trying to understand Dependency Injection.
I have created a sample example for this .
Can any one please tell ,is this example correct or not
public interface IEngine
{
void Start();
void SayHelloFromEngine();
};
public class Engine :IEngine
{
public Engine(){
}
public void Start()
{
Console.Write ("Hey it is started");
}
public void SayHelloFromEngine()
{
Console.Write ("Hello from Engine");
}
}
public class Car
{
private readonly IEngine _engine;
public Car(IEngine engine){
_engine=engine;
_engine.SayHelloFromEngine ();
}
}
and my object creation would be
Car car2 = new Car (new Engine ());
Please guide me on what steps i'm doing wrong.
You example looks good to me. That's pretty much how I tend to structure things.
There is a good stack overflow thread here with some useful links and posts.
The thing to work on I guess, is how you create the implementations and managing your dependencies. You can create your own factory classes/methods to do it, or use an existing framework, something like Ninject.
It's common to add a guard clause to your constructors that take dependencies, so that you can throw an exception immediately if someone tries to pass in a null dependency.
public class Car
{
private readonly IEngine _engine;
public Car(IEngine engine)
{
if (engine == null)
{
throw new ArgumentNullException("engine");
}
_engine=engine;
_engine.SayHelloFromEngine ();
}
}
A big part of dependency injection is how you create your dependencies. When you say Car car2 = new Car (new Engine ());, you're hard coding your dependency, which is kind of defeating the purpose of dependency injection. You should have a single composition root where all of your dependencies are defined. If you're not sure whether you're doing something correctly, a good rule of thumb is that you should not be newing any of your dependencies anywhere.
One more thing; when you're composing your dependencies, make sure you don't fall into the trap of making a service locator.

Adding Dagger to an existing project

I'm trying to add Dagger to an existing web application and am running into a design problem.
Currently our Handlers are created in a dispatcher with something like
registerHandler('/login', new LoginHandler(), HttpMethod.POST)
Inside the login handler we might call a function like
Services.loginService.login('username', 'password');
I want to be able to inject the loginService into the handler, but am having trouble figuring out the best approach. There is a really long list of handlers in the dispatcher, and injecting them all as instance variables seems like a large addition of code.
Is there a solution to this type of problem?
Based on your comment about having different services to inject. I would propose next solution.
ServicesProvider:
#Module(injects = {LoginHandler.class, LogoutHandler.class})
public class ServicesProvider {
#Provides #Singleton public LoginService getLoginService() {
return new LoginService();
}
}
LoginHandler.java:
public class LoginHandler extends Handler {
#Inject LoginService loginService;
}
HttpNetwork.java
public class HttpNetwork extends Network {
private ObjectGraph objectGraph = ObjectGraph.create(new ServicesProvider());
public registerHandler(String path, Handler handler, String methodType) {
getObjectGraph().inject(handler);
}
}
There is one week point in this solution - you can't easily change ServiceProvider for test purpose (or any other kind of purpose). But if you inject it also (for example with another object graph or just through constructor) you can fix this situation.

dependency injection with OSGI

I have built an application with the dependency framework Guice. Now I will move over to OSGI and started to extend my jars with bundle information.
The main problem, which I currently face is, how to set up the dependency injection correctly. I have bundle A, which exports some packages. Then Bundle B defines a component, which needs some object (class AA) of bundle A injected.
I could set up a service for the class AA in bundle A, which will be injected automatically, but what if bundle A has also a dependency to some class in bundle A, which is maybe not exported. Do I have to set up the second class then also as service, which will not work, because it is not exported.
The following code will show the problem:
Bundle A
package test.bundleA.api
public class AA {
#Inject
public AA(AInternal someReference) {...}
}
package test.bundleA.internal
public class AInternal {...}
Bundle B:
package test.bundleB.api
public class ComponentB {
#Inject
public ComponentB(AA refToA) {...}
}
When I will use any other classes in bundle A from the exported package, do I have then to set up for each of them a service?
What is a common approach to solve the problem of dependency injection inside the bundle and even over bundle boundaries?
If you are independent of using Guice I would recommend to use Eclipse+Bndtools to create your OSGi bundles. With Bndtools, its quite easy to create OSGi bundles and also DI via Annotations. Let's take an example:
You have an interface in bundleA:
public interface Greeting {
String sayHello(String name);
}
An implementation in bundleB where #Component enables our bundle to use OSGi Declarative Service.
#Component
public class ExampleComponent implements Greeting {
public String sayHello(String name) {
return "Hello " + name;
}
}
And in the end a third bundleC where you want to us DI and inject all Greeting implementation to a specific component for usage.
#Component
public class GreetingCommand {
private Greeting greetingSvc;
#Reference
public void setGreeting(Greeting greetingSvc) {
this.greetingSvc = greetingSvc;
}
public void greet(String name) {
System.out.println(greetingSvc.sayHello(name));
}
}
As you can see with #Reference you indicate that you want to inject an implementation of your Greeting interface. The example above uses OSGi Declarative Services in combination with Bndtools. Bndtools itself takes the annotations and creates a XML file needed for OSGi to use Declarative Services. I don't want to go more deep into it. Please see [1] and [2] for more information. Just wanted to show you how DI is made by using declarative services and Bndtools.
[1] http://bndtools.org/
[2] http://wiki.osgi.org/wiki/Declarative_Services
Well, there is a extension library called Peaberry which provide integration Guice with OSGi. There is nice example how to inject a service bundle into another bundle.
Hope you will find it helpful.
The solution to your specific scenario is to define a public factory (builder) service/component that you can register with osgi and inject that type. The factory impl can be defined in the same module, and create the internal type via a 'create' or 'build' method with a return type of a public interface type, but the impl is internal.

Resources