How do I convert the following example to use one of the wicket/IOC integration packages?
I want to learn and understand the DI/IOC pattern. I have read a lot about it, but I've found it a little hard to grasp without digging into a code example. I have an example of a complete, working Wicket panel, which I think I want to convert to using DI.
The panel is basically a web UI editor for a list. It takes an IPanelFactory as a constructor argument. The constructor creates a list (DefaultRefreshingView), and the panel factory knows how to create a ViewPanel for each row. The panelFactory also knows how to create an add form, for introducing a new item into the list.
I will cut out a lot of code to get to the heart of what I think is relevant:
public interface IPanelFactory<T extends DomainEntity, U extends DomainEntity>
extends IDetachable {
IAddItemPanel<T, U> newAddItemPanel(String id);
Component newEditPanel(ViewPanel.ViewPanelParameters<T> parms);
Component newListPanel(String id, IModel<Collection<T>> listModel);
}
public class ListEditorPanel2<T extends DomainEntity, U extends DomainEntity>
extends Panel implements IHeaderContributor {
private static final long serialVersionUID = 1L;
private final IPanelFactory<T, U> panelFactory;
public ListEditorPanel2(String id, IModel<Collection<T>> listModel,
final IPanelFactory<T, U> panelFactory) {
super(id, listModel);
this.panelFactory = panelFactory;
final AjaxCell listCell = new AjaxCell("listCell");
DefaultRefreshingView<T> itemList = new DefaultRefreshingView<T>(
"itemList", listModel) {
#Override
protected void populateItem(final Item<T> item) {
Component editPanel = ListEditorPanel2.this.panelFactory
.newEditPanel(new ViewPanelParameters<T>("viewPanel",
item.getModel(), new EditPanelCallback(item)));
item.add(editPanel);
}
};
listCell.add(itemList);
add(listCell);
final IAddItemPanel<T, U> addItemPanel = panelFactory
.newAddItemPanel("addItemForm");
add((Component) addItemPanel);
Form<T> form = addItemPanel.getForm();
}
}
Each implementation of IPanelFactory provides different components for the View and Add sections. There can be multiple instances of ListEditorPanel2 that use different factory implementations in the same page hierarchy.
My thinking is that I want IPanelFactory to be an injected dependency. So...
Is this a good use case for DI/IOC, or does it not make sense to use it here?
How would I do this "by hand" without using an IOC container? (Am I doing it already?)
Which wicket-IOC integration should I use? I am using wicket 1.4.8 at present. I was going to try wicket-spring-annot, but it looks like that project is out of date.
How do I set up the IOC container to do this for my wicket components?
I dont quite understand your use case but i will try to answer your question anyway.
Wicket has great support for the 2 most popular DI containers namely Spring and Guice. Personally i prefer using guice since it i find it less bloated and easier to use. You need to understand how guice works and how guice modules are created. To intergrate you wicket application with guice, you do something like below on your wicket application init method:
Injector injector = Guice.createInjector(new AppModule(),PersistenceService.usingJpa().across(UnitOfWork.REQUEST).buildModule());
addComponentInstantiationListener(new GuiceComponentInjector(this, injector));
Here am instantiating a guice injector with 2 modules, namely appModule and Persistence module (ignore the persistenceModule details . am using warp persist for transactions)
In a guice module, you bind all the components that you would like to be injecting. I mostly bind my Daos and my services. I can then inject the same to my panels, pages and any other wicket component. I can also bind panels and other custom components so that i can inject them to other components as neccessary. I have however not found a situation where i will need to bind and inject a user interface component.
Related
I'm struggling with a particular dependency injection problem and I just can't seem to figure it out. FYI: I'm new to guice, but I have experience with other DI frameworks - that's why I believe this shouldn't be to complicated to achieve.
What am I doing:
I'm working on Lagom multi module project and using Guice as DI.
What I would like to achieve:
Inject multiple named instances of some interface implementation (lets' call it publisher, since it will publishing messages to kafka topic) to my service.
This 'publisher' has injected some Lagom and Akka related services (ServiceLocator, ActorSystem, Materializer, etc..).
Now I would like to have two instances of such publisher and each will publish messages to different topic (So one publisher instance per topic).
How would I achieve that?
I have no problem with one instance or multiple instances for the same topic, but if I want to inject different topic name for each instance I have a problem.
So my publisher implementation constructor looks like that:
#Inject
public PublisherImpl(
#Named("topicName") String topic,
ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
...
}
If I want to create one instance I would do it like this in my ServiceModule:
public class FeedListenerServiceModule extends AbstractModule implements ServiceGuiceSupport {
#Override
protected void configure() {
bindService(MyService.class, MyServiceImpl.class);
bindConstant().annotatedWith(Names.named("topicName")).to("topicOne");
bind(Publisher.class).annotatedWith(Names.named("publisherOne")).to(PublisherImpl.class);
}
}
How would I bind multiple publishers each for it's own topic?
I was playing around with implementing another private module:
public class PublisherModule extends PrivateModule {
private String publisherName;
private String topicName;
public PublisherModule(String publisherName, String topicName) {
this.publisherName = publisherName;
this.topicName = topicName;
}
#Override
protected void configure() {
bindConstant().annotatedWith(Names.named("topicName")).to(topicName);
bind(Publisher.class).annotatedWith(Names.named(publisherName)).to(PublisherImpl.class);
}
}
but this led me nowhere since you can't get injector in you module configuration method:
Injector injector = Guice.createInjector(this); // This will throw IllegalStateException : Re-entry is not allowed
injector.createChildInjector(
new PublisherModule("publisherOne", "topicOne"),
new PublisherModule("publisherTwo", "topicTwo"));
The only solution which is easy and it works is that I change my PublisherImpl to abstract, add him abstract 'getTopic()' method and add two more implementations with topic override.
But this solution is lame. Adding additional inheritance for code reuse is not exactly the best practice. Also I believe that Guice for sure must support such feature.
Any advises are welcome.
KR, Nejc
Don't create a new Injector within a configure method. Instead, install the new modules you create. No child injectors needed—as in the PrivateModule documentation, "Private modules are implemented using parent injectors", so there's a child injector involved anyway.
install(new PublisherModule("publisherOne", "topicOne"));
install(new PublisherModule("publisherTwo", "topicTwo"));
Your technique of using PrivateModule is the one I'd go with in this situation, particularly given the desire to make the bindings available through binding annotations as you have it, and particularly if the full set of topics is known at runtime. You could even put the call to install in a loop.
However, if you need an arbitrary number of implementations, you may want to create an injectable factory or provider to which you can pass a String set at runtime.
public class PublisherProvider {
// You can inject Provider<T> for all T bindings in Guice, automatically, which
// lets you configure in your Module whether or not instances are shared.
#Inject private final Provider<ServiceLocator> serviceLocatorProvider;
// ...
private final Map<String, Publisher> publisherMap = new HashMap<>();
public Publisher publisherFor(String topicName) {
if (publisherMap.containsKey(topicName)) {
return publisherMap.get(topicName);
} else {
PublisherImpl publisherImpl = new PublisherImpl(
topicName, serviceLocatorProvider.get(), actorSystemProvider.get(),
materializerProvider.get(), applicationLifecycleProvider.get());
publisherMap.put(topicName, publisherImpl);
return publisherImpl;
}
}
}
You'd probably want to make the above thread-safe; in addition, you can avoid the explicit constructor call by using assisted injection (FactoryModuleBuilder) or AutoFactory, which will automatically pass through explicit parameters like topicName while injecting DI providers like ServiceLocator (which hopefully has a specific purpose, because you may not need much service-locating within a DI framework anyway!).
(Side note: Don't forget to expose your annotated binding for your PrivateModule. If you don't find yourself injecting your topicName anywhere else, you might also consider using individual #Provides methods with the assisted injection or AutoFactory approach above, but if you expect each Publisher to need a differing object graph you might choose the PrivateModule approach anyway.)
Guice's approach to dependency injection is that the DI framework complements your instantiation logic, it doesn't replace it. Where it can, it will instantiate things for you, but it doesn't try to be too clever about it. It also doesn't confuse configuration (topic names) with dependency injection - it does one thing, DI, and does that one thing well. So you can't use it to configure things, the way you can with Spring for example.
So if you want to instantiate an object with two different parameters, then you instantiate that object with two different parameters - ie, you invoke new twice. This can be done by using provider methods, which are documented here:
https://github.com/google/guice/wiki/ProvidesMethods
In your case, it might look something like adding the following method to your module:
#Provides
#Named("publisherOne")
#Singleton
Publisher providePublisherOne(ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
return new PublisherImpl("topicOne", serviceLocator,
actorSystem, materializer, applicationLifecycle);
}
Also, you probably want it to be a singleton if you're adding a lifecycle hook, otherwise you could run into memory leaks each time you add a new hook every time it's instantiated.
Consider a simple action filter in an ASP.NET Core MVC project that takes a dependency:
public class TestActionFilter : IAsyncActionFilter {
private readonly IMyDependency _dep;
public class TestActionFilter(IMyDependency dep)
{
_dep = dep;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context,
ActionExecutionDelegate next)
{
// do things with _dep...
await next();
}
}
I already have IMyDependency registered with Simple Injector and working elsewhere. I would like for Simple Injector to handle the action filter as well.
If I add an IServiceCollection registration for the same type, it does get injected into the action filter. I do not want two bindings though and I'm trying to avoid the framework container and just stick with Simple Injector.
Is there some trick to get Simple Injector to handle my action filter? I remember there used to be some sort of "filter provider" concepts in older Simple Injector incarnations that allowed this.
At this moment, there is nothing in the Simple Injector integration package for ASP.NET Core MVC that simplifies working with filter attributes. We are still hoping that Microsoft will add simplifications to the framework to support non-conformers (since Microsoft promised to make integration as smooth as it can be), but this seems a lost cause.
There are a few solutions. An approach is to cross-wiring, as you did already. But the more you cross-wire, the more you move control out of Simple Injector and the more you lose the verification ability that Simple Injector gives. This typically won't be much a problem when all your object graphs are singletons, but that's a different discussion.
Another option is to create a proxy filter in the built-in configuration system that delegates to the real filter that is resolved from Simple Injector. Such proxy can be defined as follows:
public sealed class SimpleInjectiorAsyncActionFilterProxy<TAsyncActionFilter>
: IAsyncActionFilter
where TAsyncActionFilter : class, IAsyncActionFilter {
private readonly Container container;
public SimpleInjectiorAsyncActionFilterProxy(Container container) {
this.container = container;
}
public Task OnActionExecutionAsync(
ActionExecutingContext c, ActionExecutionDelegate n) =>
container.GetInstance<TAsyncActionFilter>().OnActionExecutionAsync(c, n);
}
This is how you hook up your filter using this proxy:
container.Register<TestActionFilter>();
services.AddMvc(options =>
{
options.Filters.Add(
new SimpleInjectiorAsyncActionFilterProxy<TestActionFilter>(container));
});
This works great for global filters. When it comes to controller or action scoped filters, take a look at passive attributes.
Checking out Guice and I love it. I currently have problem where guice solved it by injecting all the required dependencies I need. But I wonder if I am using Guice in the wrong way. What I require though is define bindings depending on specific instance. And to achieve this I passed the instance in the module.
For instance, consider the following (somewhat similar to my problem):
public class CustomerModule extends AbstractModule {
private Customer customer;
public CustomerModule(Customer customer){
this.customer = customer;
}
#Override
public void configure() {
bind(ReportGenerator.class).to(HtmlReportGenerator.class);
}
#Provides
Account providePurchasingAccount() {
return customer.getPurchasingAccount();
}
}
I use this module to get Account dependency injected to the report generator class that needs the account of a specific customer. For example, a user chooses a specific customer and say, wants to show a generated report. I have method like
public void printReport (Customer customer){
Injector injector = Guice.createInjector(new CustomerModule(customer));
ReportGenerator reportGenerator = injector.getInstance(ReportGenerator.class);
showReport(reportGenerator.generate())
}
Once the work is done, I am done with this module.
Is this a ok use of guice?
It is appropriate and useful to accept a constructor argument for a Module. This is an especially common pattern when making bindings for similar objects. Example:
// Installs #Named("accounts") Db to the given impl, backed with the given cache.
install(new DbModule("accounts", AccountDb.class, InMemoryCache.class));
// Same as above.
install(new DbModule("users", UserDb.class, DiskCache.class));
install(new DbModule("products", ProductDb.class, CustomProductCache.class));
That said, it is not common to create a new root Injector per action (such as printReport). Injector creation can take a long time as Guice reflectively queries classes and their dependencies. Instead, it is much more common to create the root Injector at application startup, and then create a child injector when you need to bind specific objects the way you have them.
Though it may make sense for you to temporarily create a brand new root Injector for each action, the way you have it, bear in mind that future development may make warrant singleton or application-level scope that persists beyond a single action, or your object graph may grow such that mid-action root Injector creation is no longer performant enough for your uses. If/when that happens, you may want to shift most of your Injector creation and configuration to a predictable startup flow, and only bind your Customer (and nothing else) into a child injector.
I am in the process of migrating from StructureMap to Simple Injector in a ASP.NET MVC3 application.
I am using the MVC3 extension for controller DI, but I am running into an issue with trying to replace the static aspects of StructureMap. We have calls to
StructureMap.ObjectFactory.GetInstance<Interface>()
throughout different layers of the app. It does not look like Simple Injector has a way to do that.
Am I missing something? Or is Simple Injector not applicable for my application?
Please advise and thanks in advance.
Allowing the application to directly access the container is considered to be bad practice. It is an form of the Service Locator anti-pattern.
Because this is considered to be a bad thing, Simple Injector does not contain anything like StructureMap's ObjectFactory.GetInstance. And as a matter of fact, the author of StructureMap is considering the removal of the ObjectFactory API in a furure release of StructureMap.
However, nothing stops you from storing the SimpleInjector.Container instance in a static field and let the application use this:
// Service Locator implementation in low application layer.
public static class ObjectFactory
{
private static SimpleInjector.Container container;
public static void SetContainer(Container container)
{
ObjectFactory.container = container;
}
public static T GetInstance<T>() where T : class
{
return container.GetInstance<T>();
}
}
In Composition root:
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
// Set the service locator here
ObjectFactory.SetContainer(container);
}
So there is no limitation in the Simple Injector that prevents you from doing this, but frankly, you are already witnessing one of the reasons why Service Locator is a bad thing: you switched containers and now you have to change application code.
Perhaps for now it is easiest for you to save the container in a static field (as shown in the example above), but please take the time to understand why this pattern is bad, and do refactor away from this pattern towards dependency injection (and especially constructor injection).
I am used to IoC/DI in web applications - mainly Ninject with MVC3. My controller is created for me, filled in with all dependencies in place, subdependencies etc.
However, things are different in a thick client application. I have to create my own objects, or I have to revert to a service locator style approach where I ask the kernel (probably through some interface, to allow for testability) to give me an object complete with dependencies.
However, I have seen several places that Service Locator has been described as an anti-pattern.
So my question is - if I want to benefit from Ninject in my thick client app, is there a better/more proper way to get all this?
Testability
Proper DI / IoC
The least amount of coupling possible
Please note I am not just talking about MVVM here and getting view models into views. This is specifically triggered by a need to provide a repository type object from the kernel, and then have entities fetched from that repository injected with functionality (the data of course comes from the database, but they also need some objects as parameters depending on the state of the world, and Ninject knows how to provide that). Can I somehow do this without leaving both repositories and entities as untestable messes?
If anything is unclear, let me know. Thanks!
EDIT JULY 14th
I am sure that the two answers provided are probably correct. However, every fiber of my body is fighting this change; Some of it is probably caused by a lack of knowledge, but there is also one concrete reason why I have trouble seeing the elegance of this way of doing things;
I did not explain this well enough in the original question, but the thing is that I am writing a library that will be used by several (4-5 at first, maybe more later) WPF client applications. These applications all operate on the same domain model etc., so keeping it all in one library is the only way to stay DRY. However, there is also the chance that customers of this system will write their own clients - and I want them to have a simple, clean library to talk to. I don't want to force them to use DI in their Composition Root (using the term like Mark Seeman in his book) - because that HUGELY complicates things in comparison to them just newing up a MyCrazySystemAdapter() and using that.
Now, the MyCrazySystemAdapter (name chosen because I know people will disagree with me here) needs to be composed by subcomponents, and put together using DI. MyCrazySystemAdapter itself shouldn't need to be injected. It is the only interface the clients needs to use to talk to the system. So a client happily should get one of those, DI happens like magic behind the scenes, and the object is composed by many different objects using best practices and principles.
I do realize that this is going to be a controversial way of wanting to do things. However, I also know the people who are going to be clients of this API. If they see that they need to learn and wire up a DI system, and create their whole object structure ahead of time in their application entry point (Composition Root), instead of newing up a single object, they will give me the middle finger and go mess with the database directly and screw things up in ways you can hardly imagine.
TL;DR: Delivering a properly structured API is too much hassle for the client. My API needs to deliver a single object - constructed behind the scenes using DI and proper practices - that they can use. The real world some times trumps the desire to build everything backwards in order to stay true to patterns and practices.
I suggest to have a look at MVVM frameworks like Caliburn. They provide integration with IoC containers.
Basically, you should build up the complete application in your app.xaml. If some parts need to be created later because you do not yet know everything to create them at startup then inject a factory either as interface (see below) or Func (see Does Ninject support Func (auto generated factory)?) into the class that needs to create this instance. Both will be supported natively in the next Ninject release.
e.g.
public interface IFooFactory { IFoo CreateFoo(); }
public class FooFactory : IFooFactory
{
private IKernel kernel;
FooFactory(IKernel kernel)
{
this.kernel = kernel;
}
public IFoo CreateFoo()
{
this.kernel.Get<IFoo>();
}
}
Note that the factory implementation belongs logically to the container configuration and not to the implementation of your business classes.
I don't know anything about WPF or MVVM, but your question is basically about how to get stuff out of the container without using a Service Locator (or the container directly) all over the place, right?
If yes, I can show you an example.
The point is that you use a factory instead, which uses the container internally. This way, you are actually using the container in one place only.
Note: I will use an example with WinForms and not tied to a specific container (because, as I said, I don't know WPF...and I use Castle Windsor instead of NInject), but since your basic question is not specificaly tied to WPF/NInject, it should be easy for you to "port" my answer to WFP/NInject.
The factory looks like this:
public class Factory : IFactory
{
private readonly IContainer container;
public Factory(IContainer container)
{
this.container = container;
}
public T GetStuff<T>()
{
return (T)container.Resolve<T>();
}
}
The main form of your app gets this factory via constructor injection:
public partial class MainForm : Form
{
private readonly IFactory factory;
public MainForm(IFactory factory)
{
this.factory = factory;
InitializeComponent(); // or whatever needs to be done in a WPF form
}
}
The container is initialized when the app starts, and the main form is resolved (so it gets the factory via constructor injection).
static class Program
{
static void Main()
{
var container = new Container();
container.Register<MainForm>();
container.Register<IFactory, Factory>();
container.Register<IYourRepository, YourRepository>();
Application.Run(container.Resolve<MainForm>());
}
}
Now the main form can use the factory to get stuff like your repository out of the container:
var repo = this.factory.GetStuff<IYourRepository>();
repo.DoStuff();
If you have more forms and want to use the factory from there as well, you just need to inject the factory into these forms like into the main form, register the additional forms on startup as well and open them from the main form with the factory.
Is this what you wanted to know?
EDIT:
Ruben, of course you're right. My mistake.
The whole stuff in my answer was an old example that I had lying around somewhere, but I was in a hurry when I posted my answer and didn't read the context of my old example carefully enough.
My old example included having a main form, from which you can open any other form of the application. That's what the factory was for, so you don't have to inject every other form via constructor injection into the main form.
Instead, you can use the factory to open any new form:
var form = this.factory.GetStuff<IAnotherForm>();
form.Show();
Of course you don't need the factory just to get the repository from a form, as long as the repository is passed to the form via constructor injection.
If your app consists of only a few forms, you don't need the factory at all, you can just pass the forms via constructor injection as well:
public partial class MainForm : Form
{
private readonly IAnotherForm form;
// pass AnotherForm via constructor injection
public MainForm(IAnotherForm form)
{
this.form = form;
InitializeComponent(); // or whatever needs to be done in a WPF form
}
// open AnotherForm
private void Button1_Click(object sender, EventArgs e)
{
this.form.Show();
}
}
public partial class AnotherForm : Form
{
private readonly IRepository repo;
// pass the repository via constructor injection
public AnotherForm(IRepository repo)
{
this.repo= repo;
InitializeComponent(); // or whatever needs to be done in a WPF form
// use the repository
this.repo.DoStuff();
}
}