DI and inheritance - eclipse

Another question appeared during my migration from an E3 application to a pure E4.
I got a Structure using inheritance as in the following pic.
There I have an invocation sequence going from the AbstractRootEditor to the FormRootEditor to the SashCompositeSubView to the TableSubView.
There I want to use my EMenuService, but it is null due to it can´t be injected.
The AbstractRootEditor is the only class connected to the Application Model (as a MPart created out of an MPartDescriptor).
I´d like to inject the EMenuService anyway in the AbstractSubView, otherwise I would´ve the need to carry the Service through all of my classes. But I don´t have an IEclipseContext there, due to my AbstractSubView is not connected with Application Model (Do I ?).
I there any chance to get the service injected in the AvstractSubView?
EDIT:
I noticed that injecting this in my AbstractSubView isn´t possible (?), so I´m trying to get it into my TableSubView.
After gregs comment i want to show some code:
in the AbstractRootEditor:
#PostConstruct
public final void createPartControl(Composite parent, #Active MPart mPart) {
...
ContextInjectionFactory.make(TableSubView.class, mPart.getContext());
First I got an Exception, saying that my TableSubView.class got an invalid constructor, so now the Constructor there is:
public TableSubView() {
this.tableInputController=null;
}
as well as my Field-Injection:
#Inject EMenuService eMenuService
This is kind of not working, eMenuService is still null

If you create your objects using ContextInjectionFactory they will be injected. Use:
MyClass myClass = ContextInjectionFactory.make(MyClass.class, context);
where context is an IEclipseContext (so you have to do this for every class starting from one that is injected by Eclipse).
There is also a seconds version of ContextInjectionFactory.make which lets you provide two contexts the second one being a temporary context which can contain additional values.

Related

WCF with IOperationInvoker using Entity and Ninject

I have a WCF Service from which I need to log the calls to its methods. For this, I used this solution to be able to track the calls and call my internal audit service, which uses Entity 5.1 and injects the services/repositories/DbContext using Ninject.
My Invoke method looks like this:
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var methodParams = (instance).GetType().GetMethod(_operationName).GetParameters();
var parameters = new Dictionary<string, object>();
for (var index = 0; index < inputs.Length; index++)
parameters.Add(methodParams[index].Name, inputs[index]);
_auditService.TrackFilterParametersValues(_operation.Parent.Type.FullName, _operationName, _operation.Action, parameters);
return _baseInvoker.Invoke(instance, inputs, out outputs);
}
In my Ninject module I have the internal stuff registered like this:
Bind<IAuditService>().To<AuditeService>().InRequestScope();
Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<DbContext>().To<MyEntities>().InRequestScope();
Problem comes up when, inside the Repository, I call the dbContext to add the new Audit object like this:
_dbContext.Set<T>().Add(entity);
It errors out claiming that the DbContext has been disposed.
What would be the correct way of registering the DbContext on a WCF Service so it gets registered for an IOperationInvoker??
I have to mention that I have all this declaration the same for the main site I'm feeding up with this backend in MVC4 and it works perfectly (no WCF there). So I'm pretty sure something is needed to be corrected for the WCF lifetime cycle, but not so sure about what.
I found the reason of why this was behaving so nasty: in the chain formed by the IOperationInvoker, IOperationBehavior and IServiceBehavior, I was injecting the AuditService by the constructor of the first 2 of them, but in the latest (IServiceBehavior), since I was decorating the WCF class with it and couldn't overload the constructor, I was using the DependencyResolver to obtain the AuditService with a property like this:
public IAuditService AuditService
{
get { return DependencyResolver.Current.GetService<IAuditService>();
}
Then, when I started to debug, I noticed that the constructors were called when the WCF Test Client was querying the WCF for the WSDL data, but the Invoke method was never called because no web method was being invoked. So the AuditService instance (and DbContext) was all fine during the calls of the constructors, but by the time of invoking a web method and calling the Invoke method of the IOperationInvoker, the DbContext was already disposed long time ago.
My workaround for this was to delete all the references to the AuditService from all constructors and move the property with the DependencyResolver from the ServiceBehavior to the IOperationInvoker implementation. Once I did this, the AuditService is called right when it's needed, never before, and its DbContext is never disposed.
If MyEntities inherits from DbContext, then this should work:
Bind(typeof(DbContext)).To(typeof(MyEntities)).InRequestScope();

Workflow: Creating Dependency Chain with Service Locator Pattern

I'm trying to get dependencies set up correctly in my Workflow application. It seems the best way to do this is using the Service Locator pattern that is provided by Workflow's WorkflowExtensions.
My workflow uses two repositories: IAssetRepository and ISenderRepository. Both have implementations using Entity Framework: EFAssetRepository, and EFSenderRepository, but I'd like both to use the same DbContext.
I'm having trouble getting both to use the same DbContext. I'm used to using IoC for dependency injection, so I thought I'd have to inject the DbContext into the EF repositories via their constructor, but this seems like it would be mixing the service locator and IoC pattern, and I couldn't find an easy way to achieve it, so I don't think this is the way forward.
I guess I need to chain the service locator calls? So that the constructor of my EF repositories do something like this:
public class EFAssetRepository
{
private MyEntities entities;
public EFAssetRepository()
{
this.entities = ActivityContext.GetExtension<MyEntities>();
}
}
Obviously the above won't work because the reference to ActivityContext is made up.
How can I achieve some form of dependency chain using the service locator pattern provided for WF?
Thanks,
Nick
EDIT
I've posted a workaround for my issue below, but I'm still not happy with it. I want the code activity to be able to call metadata.Require<>(), because it should be ignorant of how extensions are loaded, it should just expect that they are. As it is, my metadata.Require<> call will stop the workflow because the extension appears to not be loaded.
It seems one way to do this is by implementing IWorkflowInstanceExtension on an extension class, to turn it into a sort of composite extension. Using this method, I can solve my problem thus:
public class UnitOfWorkExtension : IWorkflowInstanceExtension, IUnitOfWork
{
private MyEntities entities = new MyEntities();
IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
{
return new object[] { new EFAssetRepository(this.entities), new EFSenderRepository(this.entities) };
}
void IWorkflowInstanceExtension.SetInstance(WorkflowInstanceProxy instance) { }
public void SaveChanges()
{
this.entities.SaveChanges();
}
}
The biggest downside to doing it this way is that you can't call metadata.RequireExtension<IAssetRepository>() or metadata.RequireExtension<ISenderRepository>() in the CacheMetadata method of a CodeActivity, which is common practice. Instead, you must call metadata.RequireExtension<IUnitOfWork>(), but it is still fine to do context.GetExtension<IAssetRepository>() in the Execute() method of the CodeActivity. I imagine this is because the CacheMetadata method is called before any workflow instances are created, and if no workflow instances are created, the extension factory won't have been called, and therefore the additional extensions won't have been loaded into the WorkflowInstanceExtensionManager, so essentially, it won't know about the additional extensions until a workflow instance is created.

Using JasperReports with datasources which rely on CDI

I have some classes which use CDI injected beans in their getters, e.g.:
class MyBean() {
#Inject
private TranslationBean translationBean;
private String chosenValue;
public void setChosenValue(String c) { chosenValue = c;}
public String getChosenValue() {
return translationBean.getTranslatedValue(chosenValue);
}
}
The underlying chosenValue is loaded from and persisted into a database.
Now I want to create a JasperReport generated PDF with such beans as DataSource. I call:
JasperFillManager.fillReport("myFile.jasper", new HashMap<String, Object>(), new JRBeanCollectionDataSource(Arrays.asList(myBean));
Obviously, the error message from Weld will eventually be that no context is active.
I now see two possibilities:
create a wrapping class for MyBean especially for JasperReports in which all needed fields are filled with actual data and no CDI dependencies are needed. Problem would be: a LOT of coding with a lot of boilerplate and repeating code.
Somehow manage to wrap a context around the call to the JasperFillManager so it runs within an/the current active CDI context.
Would the second option be possible? Is there any other, nicer way than one of the proposed ones?
You're probably looking at creating a new scope, if its possible to wrap all the JasperStuff. Take a look at the Seam Reports stuff in https://github.com/seam/reports, it may be of some help or inspiration.

GIN #Inject on variable for Rpc Services

I'm a bit lost with the use of Inject on variable.
I got this code working :
private XXServiceAsync xxServiceAsync;
#Inject
protected IndexViewImpl(EventBus eventBus, XXServiceAsync tableManagementServiceAsync) {
super(eventBus, mapper);
this.xxServiceAsync = xxServiceAsync;
initializeWidgets();
}
With this code, I can call my RPC service wherever I need in the class (On click ...)
I would like to clear a bit the code by injecting direcly in the variable ; doing so :
#Inject
private XXServiceAsync xxServiceAsync;
protected IndexViewImpl(EventBus eventBus) {
super(eventBus, mapper);
initializeWidgets();
}
This always keep the Service to NULL.
Am I doing something wrong ? Is the GIN magic with rpc services meant to be done otherwise?
Thanks!
It is still null at that point, because Gin (and Guice, and other frameworks like this) cannot assign the fields until the constructor has finished running.
Consider how this would look if you were manually wiring the code (remember that Gin/Guice will cheat a little to assign private fields, call non-visible methods):
MyObject obj = new MyObject();//initializeWidgets() runs, too early!
obj.xxServiceAsync = GWT.create(xxService.class);
If you need something in the constructor, pass it into the constructor. If you wont need it right away (such as until asWidget() is called), then a field or setter annotated with #Inject can be helpful.
If you have field level injection you can use an empty #Inject method to do your post-inject initialization. The no-arg injected method will be run after field injections on the class are complete.
#Inject void initialize(){
...
initializeWidgets()
}
Edit: I previously stated that it was run after method injection as well, but testing shows that this is not always the case.

Creating new entities while enabling injection

I have a method on a stateless session bean which creates a new instance of an entity and persists it. You might normally use new MyEntity() to create the object but I would like injection to populate some of the properties of the entity for me.
I got partial success using
#Inject
#New
private MyEntity myNewEntity;
in the session bean and then using that instance in my method.
The problem I have now is that the second time the method is called, myNewEntity isn't a new object, its the same object as the one created the first time. As a result I'm getting
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '9' for key 'PRIMARY'
Or at least that's why I think I'm getting this exception. Certainly if I use new MyEntity() I don't get the exception but my injection doesn't happen.
Am I on the wrong track? How can I create a new local entity object while enabling injection?
Any help would be great!
First of all - I have serious doubts that it's a good idea to use CDI to control the lifecycle of a Entity. See this quote from the documentation (here):
According to this definition, JPA
entities are technically managed
beans. However, entities have their
own special lifecycle, state and
identity model and are usually
instantiated by JPA or using new.
Therefore we don't recommend directly
injecting an entity class. We
especially recommend against assigning
a scope other than #Dependent to an
entity class, since JPA is not able to
persist injected CDI proxies.
What you should do to create new instances of entities is adding a layer of indirection, either with #Produces or #Unwraps (Seam Solder, if you need it to be truly stateless), and thereby making sure that you code explicitly calls new.
I think I have a working solution now which seems okay, though I'm not quite sure why it works so I welcome your feedback on a better solution. I am now injecting a DAO-style bean into my stateless session bean:
#Stateless
public class PhoneService {
#Inject
protected ProblemReports problemReports;
An injecting my entity into the ProblemReports bean:
public class ProblemReports {
#Inject
#New
private ProblemReport newProblemReport;
I assume that ProblemReports defaults to #Dependant scope which as I understand it should be the same as the stateless session bean which containts it. I could understand this if the scope of ProblemReports was shorter, causing a new instance of ProblemReport to be created when the new ProblemReports is created; but it isn't.
Is this just an example of EJB and CDI not playing well together?