I'm putting a project together with Spring.NET and Caliburn v2. I have some objects that I'm trying to instantiate, but not sure how to go about it.
I have been using Caliburn's IoC aspect annotations (Singleton and PerRequest) to get objects into the Spring context. The problem with this is that I have two objects, A and B, where Object B is a subclass of Object A (meaning B is also an A). This means that if I register both, Spring complains of ambiguity when an object of type A is requested. To get around this, I could stop using Caliburn's IoC aspects to register the objects and instead register them in the Spring context XML files. That way I can specify a named object in the Spring context file to use in the constructor of object C, which needs an object of type B injected.
However, this creates a new problem. Object B needs the Caliburn window manager to be injected (which is not available to the Spring container at the time when the objects listed in the context XML files are instantiated, but only later, after Caliburn has loaded and added its own objects to the Spring container).
I could simply remove the inheritance and let some code duplication occur between objects A and B, but then what would be the point of doing OO programming? Otherwise I guess I'm looking for a way to specify objects in Spring.NET context XML, but keep them from being resolved until after Caliburn has loaded.
Any ideas?
I'm not familiar with Caliburn but if you want to delay instantiation then you could mark your objects in xml as lazy-init, like this:<object id="foo" type="..." lazy-init="true"/>
This way they will be instantiated when you first request them
I managed to solve this by maintaining a separate list of caliburn-dependent spring context XML files. I loaded these into the ApplicationContext object by adding the following code at the beginning of the overridden DisplayRootView() method in my application's bootstrapper:
var objectDefinitionReader = new XmlObjectDefinitionReader(applicationContext);
objectDefinitionReader.LoadObjectDefinitions(GetCaliburnDependentContextFiles());
applicationContext.Refresh();
Related
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.
I am starting a new project with JavaEE 7 and declared a Sessionscoped bean to maintain the web logged user information in session.
The UserSessionBean, as I named it, is intended to be lightweight - trying to avoid lots of data to be kept in the session by Weld. But in some cases I need to get all user information, so added a getUser() method which must query and retrieve a UserEntity from JPA. In order for the method to do its job, I need to #Inject other resources onto the UserSessionBean.
My question is: These dependant resources will be kept and serialised within the UserSessionBean by Weld until the context is destroyed?
The weld documentation says this:
An instance of a dependent bean is never shared between different
clients or different injection points. It is strictly a dependent
object of some other object. It is instantiated when the object it
belongs to is created, and destroyed when the object it belongs to is
destroyed.
That makes me think the all SessionBean tree is kept by weld during session life, but how can I keep a lightweight SessionBean and use injected CDI resources on it?
Since what you're injecting are also CDI beans, it is not the beans themselves that get serialised, but their lightweight proxies. Upon deserialisation, the proxies dynamically resolve the correct beans for whatever scope they are. See section 5.4 Client Proxies of the CDI1.0 spec. Hence, your bean is as lightweight as possible.
I am facing a problem with CDI on JBoss AS 7.1.1
I have two JSF-beas, where one has the CODI ViewAccessScope (Bean A) which shows all entities, and the second is plain RequestScoped (Bean B). Each Bean get a, so called, Presenter injected which takes care of all presentation logic. So far so good.
The Presenter from Bean B is responsible for creating a new entity (calling service...bla...blubb) and when everything is done Bean B is redirecting to another page but since Bean A now has to reload its content I introduced the JEE-6 Observer.
In detail: Both Beans (A & B) get a particular Presenter injected (which has a backrefrence to the jsf-bean via a interface). Bean-B-Presenter fires an event after the entity was successfully created, so that then Bean-A-Presenter (the Observer) can reload the data and notify Bean-A about the changes.
The Problem: I am getting as NullPointerException when the observing Presenter (A) reloads its data because the reference to Bean A is lost. The reason why this happens is because CDI is obviously creating a new Presenter-object (its annotated with #Named) instead of using the one that is coupled with Bean-A.
Workaround: when I use Bean-A as the Observer than everything works.
My code is pretty much the same as seen in the link I added. I don't understand why a new instance is created when firing the event.
UPDATE regarding LightGuards comment:
The presenter beans are just annotated with #Named (which should be Dependent-Scope by default).
I had a look at the Weld-Documentation and it looks like this scope is somehow isolating my beans from each other. I need the presenters to be a new instance, each time a view (jsf-bean) gets initialized (so no Singletons). On the other hand I want to be able to send events between them, meaning that only the already existing instances get notified (not that a new instance is created).
I just did a test with the presenters being RequestScoped. This doesnt work either because now on every HTTP-Request I get a new Presenter even though the view (jsf-bean) to which it belongs is ViewAccessScoped. SessionScope of course works...but this would result in the wrong design.
Sounds like you'll need to create your own scope for this usecase. None of the default scopes sound like they fit your need. Another option would be to look at MyFaces CODI and the conversation scope they're written.
Please ensure that your observers aren't private.
And you have to ensure that you redirect correctly.
I have an application using the Entity Framework code first. My setup is that I have a core service which all other services inherit from. The core service contains the following code:
public static DatabaseContext db = new DatabaseContext();
public CoreService()
{
db.Database.Initialize(force: false);
}
Then, another class will inherit from CoreService and when it needs to query the database will just run some code such as:
db.Products.Where(blah => blah.IsEnabled);
However, I seem to be getting conflicting stories as to which is best.
Some people advise NOT to do what I'm doing.
Other people say that you should define the context for each class (rather than use a base class to instantiate it)
Others say that for EVERY database call, I should wrap it in a using block. I've never seen this in any of the examples from Microsoft.
Can anyone clarify?
I'm currently at a point where refactoring is possible and quite quick, so I'd like some general advice if possible.
You should wrap one context per web request. Hold it open for as long as you need it, then get rid of it when you are finished. That's what the using is for.
Do NOT wrap up your context in a Singleton. That is not a good idea.
If you are working with clients like WinForms then I think you would wrap the context around each form but that's not my area.
Also, make sure you know when you are going to be actually executing against your datasource so you don't end up enumerating multiple times when you might only need to do so once to work with the results.
Lastly, you have seen this practice from MS as lots of the ADO stuff supports being wrapped in a using but hardly anyone realises this.
I suggest to use design principle "prefer composition over inheritance".
You can have the reference of the database context in your base class.
Implement a singleton for getting the DataContext and assign the datacontext to this reference.
The conflicts you get are not related to sharing the context between classes but are caused by the static declaration of your context. If you make the context an instance field of your service class, so that every service instance gets its own context, there should be no issues.
The using pattern you mention is not required but instead you should make sure that context.Dispose() is called at the service disposal.
I'm new to this IoC and DI business- I feel like I get the concept if you are passing along objects that are of a global scope, but I don't get how it works when you need to pass around an object that is of a specific logical state. So, for instance, if I wanted to inject a person object into a write file command object- how would I be able to choose the correct person object dynamically? From what I have seen, I could default construct the object, but my disconnect is that you wouldn't use a default person object, it would need to be dynamic. I assume that the IoC container may just maintain the state of the object for you as it gets passed around, but then that assuems you are dealing in only one person object because there would be no thread safety, right? I know I am missing something, (maybe something like a factoryclass), but I need a little more information about how that would work.
Well, you can always inject an Abstract Factory into your consumer and use it to create the locally scoped objects.
This is sometimes necessary. See these examples:
MVC, DI (dependency injection) and creating Model instance from Controller
Is there a pattern for initializing objects created via a DI container
Can't combine Factory / DI
However, in general we tend to not use DI for Entities, but mostly for Services. Instead, Entities are usually created through some sort of Repository.
When you construct an service object (e.g. WriteFileService), you inject into it things it needs internally to complete it's job. Perhaps it needs a filesystem object or something.
The Person object in your example should be passed to the service object as a parameter to a method call. e.g. writeFileService.write(person)