Guice PrivateModule providing both named and not named injections - dependency-injection

I have a PrivateModule defining the following configuration:
public void configure() {
Optional<String> annotationName = Optional.ofNullable(config.getString(ANNOTATION_NAME_KEY));
if (annotationName.isPresent()) {
bind(SqlClient.class).annotatedWith(named(annotationName.get()))
.toProvider(this::createClient)
.in(Singleton.class);
expose(SqlClient.class).annotatedWith(named(annotationName.get()));
} else {
bind(SqlClient.class)
.toProvider(this::createClient)
.in(Singleton.class);
expose(SqlClient.class);
}
}
#Provides
private SqlClient createClient() {
return SqlClient.init(config);
}
This private module is initialized multiple times vs json configuration, providing multiple sql clients with different configurations. This works ok when all of the configurations have ANNOTATION_NAME_KEY: calling
#Inject
#Named("AAA")
SqlClient aaaClient;
#Inject
#Named("BBB")
SqlClient bbbClient;
returns expected results. But when i have a json configuration that has no ANNOTATION_NAME_KEY key, this to provide a solution for case without named annotation like
#Inject
SqlClient defaultClient;
I get the following exception:
A binding to my.SqlClient was already configured at my.SqlClientModule.configure(SqlClientModule.java:110).
Am I missing something or the entire idea of mixing named and non-named injections are wrong? Thanks.

Related

e4 dependency reinjection order: field vs. method

I was quite surprised to see that there is no deterministic behavior for the order in which objects get reinjected.
public class Test {
#Inject private Boolean testBool;
#Inject
public void checkNewObject(Boolean testBoolNew) {
if (!testBoolNew.equals(this.testBool)) {
System.out.println("Out of sync!");
} else {
System.out.println("In sync!");
}
}
}
And this is how I use the class:
context.set(Boolean.class, new Boolean(true));
Test test = ContextInjectionFactory.make(Test.class, context);
context.set(Boolean.class, new Boolean(false));
So, sometimes I get the output:
In sync!
In sync!
And sometimes I get:
In sync!
Out of sync!
Is this really non deterministic or am I just overseeing something?
The documentation clearly states that the injection order should be:
Constructor injection: the public or protected constructor annotated with #Inject with the greatest number of resolvable arguments is selected
Field injection: values are injected into fields annotated with #Inject and that have a satisfying type
Method injection: values are injected into methods annotated with #Inject and that have satisfying arguments
See: https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection#Injection_Order
I'm not sure, why this doesn't work as expected in your case.
How is equals() implemented in MyContent?
Is MyContent annotated with #Creatable and or #Singleton?
As a side note: Is this a practical or just an academic problem? Why is it necessary to inject the same instance into a field and into a method on the same target-instance? If you want to have a field variable to cache the value, you can set this from the method.
If you feel this is a bug, please file it here: https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Platform

StructureMap Convention - Differences between Registy.AddType and Registry.For().Use()

Short question. Exists some diference between registry.AddType(pluginType, type); and registry.For(pluginType).Use(type); ?
Code:
public class BasicConvention : ConfigurableRegistrationConvention
{
public override void Process(Type type, Registry registry)
{
if (something)
registry.For(pluginType).Use(type).Singleton();
}
}
}
and
public class BasicConvention : ConfigurableRegistrationConvention
{
public override void Process(Type type, Registry registry)
{
if (something)
registry.AddType(pluginType, type);
}
}
}
Using WhatDoIHave() I can see the same:
Using AddType:
===============================================================================================================================================================================================================================================================================
PluginType Namespace Lifecycle Description Name
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession Paf.Application.Session Transient Paf.Application.Session ('Paf.Application.Session, Paf.Modules.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null') Paf.Application.Session,... (Default)
===============================================================================================================================================================================================================================================================================
Using For().Use():
===============================================================================================================================================================================================================================================================================
PluginType Namespace Lifecycle Description Name
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession Paf.Application.Session Singleton Paf.Application.Session (Default)
===============================================================================================================================================================================================================================================================================
The only difference is in the description ...
Somebody?
The call to registry.AddType(pluginType, type) is basically shorthand for chaining together For and Use as in registry.For(pluginType).Use(type).
Calling registry.AddType(pluginType, type) causes a direct call to Registry.alter.set with the plugin type and the concrete type specified together.
Calling registry.For(pluginType).Use(type) chains together For and Use. The call to For returns a new GenericFamilyExpression (the constructor calls Registry.alter.set for the interface type), and the call to Use ends up calling Registry.alter.set to make the concrete type the default for the plugin family.
See the source code for Registry.cs and GenericFamilyExpression.cs, and other classes in the StructureMap source.
The accepted answer is not entirely correct. They are not the same. Which is surprisingly is indicated at the end of an answer. Use will set default instance for plugin (type) and AddType will not. So you will not be able to use Structure map as service locator with AddType. You can have this error No default Instance is registered and cannot be automatically determined for type <type>

ASP.NET MVC + Ninject: InRequestScope

I want to create instance of PerRequestResourceProvider using ninject InRequestScope:
public class PerRequestResourceProvider: IPerRequestResourceProvider
{
priavte readonly _perRequestResorceInstance;
public PerRequestResourceProvider()
{
_perRequestResorceInstance = new PerRequestResource();
}
public PerRequestResource GetResource()
{
return _perRequestResorceInstance;
}
}
public interface IPerRequestResourceProvider
{
PerRequestResource GetResource();
}
In my NinjectDependencyResolver:
.....
kernel.Bind<IPerRequestResourceProvider>.To<PerRequestResourceProvider>().InRequestScope();
I inject IPerRequestResourceProvider in few classes. But when I add breakpoint to PerRequestResourceProvider constructor I see that PerRequestResourceProvider is created three times during one request and not single per request. What's wrong?
Update: source code ttps://bitbucket.org/maximtkachenko/ninjectinrequestscope/src
There are two issues with your code:
Ninject is not getting initialized correctly.
You need one of the Ninject.MVCx packages (according to the MVC version you are using). To configure it correctly, see: http://github.com/ninject/ninject.web.mvc
You are injecting PerRequestResourceProvider (the class type), and not IPerRequestResourceProvider (the interface type) into HomeController, thus the .InRequestScope() defined on the IPerRequestResourceProvider binding is not taking any effect. Change the HomeController constructor to get the inteface type injected and you're good.
Ninject does not require bindings for instantiatable (non-abstract,..) classes. This is why it is not obvious when the wrong binding is used.

Handling dependencies with IoC that change within a single function call

We are trying to figure out how to setup Dependency Injection for situations where service classes can have different dependencies based on how they are used. In our specific case, we have a web app where 95% of the time the connection string is the same for the entire Request (this is a web application), but sometimes it can change.
For example, we might have 2 classes with the following dependencies (simplified version - service actually has 4 dependencies):
public LoginService (IUserRepository userRep)
{
}
public UserRepository (IContext dbContext)
{
}
In our IoC container, most of our dependencies are auto-wired except the Context for which I have something like this (not actual code, it's from memory ... this is StructureMap):
x.ForRequestedType().Use()
.WithCtorArg("connectionString").EqualTo(Session["ConnString"]);
For 95% of our web application, this works perfectly. However, we have some admin-type functions that must operate across thousands of databases (one per client). Basically, we'd want to do this:
public CreateUserList(IList<string> connStrings)
{
foreach (connString in connStrings)
{
//first create dependency graph using new connection string
????
//then call service method on new database
_loginService.GetReportDataForAllUsers();
}
}
My question is: How do we create that new dependency graph for each time through the loop, while maintaining something that can easily be tested?
To defer the creation of an object until runtime, you can use a factory:
public interface ILoginServiceFactory
{
ILoginService CreateLoginService(string connectionString);
}
Usage:
public void CreateUserList(IList<string> connStrings)
{
foreach(connString in connStrings)
{
var loginService = _loginServiceFactory.CreateLoginService(connString);
loginService.GetReportDataForAllUsers();
}
}
Within the loop, do:
container.With("connectionString").EqualTo(connString).GetInstance<ILoginService>()
where "connectionString" is the name of a string constructor parameter on the concrete implementation of ILoginService.
So most UserRepository methods use a single connection string obtained from session, but several methods need to operate against a list of connection strings?
You can solve this problem by promoting the connection string dependency from IContext to the repository and adding two additional dependencies - a context factory and a list of all the possible connections strings the repository might need to do its work:
public UserRepository(IContextFactory contextFactory,
string defaultConnectionString,
List<string> allConnectionStrings)
Then each of its methods can build as many IContext instances as they need:
// In UserRepository
public CreateUserList() {
foreach (string connString in allConnectionStrings) {
IContext context = contextFactory.CreateInstance(connString);
// Build the rest of the dependency graph, etc.
_loginService.GetReportDataForAllUsers();
}
}
public LoginUser() {
IContext context = contextFactory.CreateInstance(defaultConnectionString);
// Build the rest of the dependency graph, etc.
}
We ended up just creating a concrete context and injecting that, then changing creating a wrapper class that changed the context's connection string. Seemed to work fine.

Structure Map Generic Type Scanner

High Level
With StructureMap, Can I define a assembly scan rule that for an interface IRequestService<T> will return the object named TRequestService
Examples:
FooRequestService is injected when IRequestService<FooRequest> is requested
BarRequestService is injected when IRequestService<BarRequest> is requested
Details
I have a generic interface defined
public interface IRequestService<T> where T : Request
{
Response TransformRequest(T request, User current);
}
and then I have multiple Request objects that implement this interface
public class FooRequestService : IRequestService<Foo>
{
public Response TransformRequest(Foo request, User current) { ... }
}
public class BarRequestService : IRequestService<Bar>
{
public Response TransformRequest(Bar request, User current) { ... }
}
Now I am at the point where I need to register these classes so that StructureMap knows how to create them because in my controller I want have the following ctor (which I want StructureMap to inject a FooRequestService into)
public MyController(IRequestService<Foo> fooRequestService) { ... }
Right now to get around my issue I have implemented an empty interface and instead of having the FooRequestService implement the generic interface I have it implement this empty interface
public interface IFooRequestService : IRequestService<Foo> { }
Then my controllers ctor looks like so, which works with StructureMaps' Default Convention Scanner
public MyController(IFooRequestService fooRequestService) { ... }
How could I create a rule with StructureMap's assembly scanner to register all objects named TRequestService with IRequestService<T> (where T = "Foo", "Bar", etc) so that I don't have to create these empty Interface definitions?
To throw something else into the mix, where I am handling StructureMap's assembly scanning does not have any reference to the assembly that defines IRequestService<T> so this has to use some sort of reflection when doing this. I scanned the answer to "StructureMap Auto registration for generic types using Scan" but it seems as though that answer requires a reference to the assembly that contains the interface definition.
I am on the path of trying to write a custom StructureMap.Graph.ITypeScanner but I am kind of stuck on what to do there (mainly because I have little experience with reflection).
You are on the right path with the scanner. Thankfully there is one built into StructureMap. Unfortunately it is not yet, as of this writing, released. Get the latest from trunk and you will see a few new things available within the scanner configuration. An example for your needs is below.
public class MyRegistry : Registry
{
public MyRegistry()
{
Scan(x =>
{
x.TheCallingAssembly();
//x.AssembliesFromApplicationBaseDirectory();
x.WithDefaultConventions();
x.ConnectImplementationsToTypesClosing(typeof (IRequestService<>));
});
}
}
First you need to tell the scanner configuration which assemblies to include in the scan. The commented AssembliesFromApplicationBaseDirectory() method also might help if you are not doing a registry per assembly.
To get your generic types into the container use ConnectImplementationsToTypesClosing.
For an example on how to setup use registries when setting up the container see:
http://structuremap.sourceforge.net/ConfiguringStructureMap.htm
If you like you can skip using registries in general and just do a scan within ObjectFactory.Initialize.
Hope this helps.

Resources