Eclipse 4 RCP did not inject object to my class - java

I'm trying to inject an object to my own class (OpenProjectItemHandler) as below context. But the injected object (eventBroker) is null. How can we inject the object?
public class ProjectExplorerPart {
protected TreeViewer viewer;
//#Inject IEventBroker eventBroker;
#PostConstruct
public void createComposite(Composite parent) {
//...
viewer.addDoubleClickListener(new OpenProjectItemHandler());
//...
}
}
public class OpenProjectItemHandler implements IDoubleClickListener {
#Inject IEventBroker eventBroker;
#Override
public void doubleClick(DoubleClickEvent event) {
//...
//IEclipseContext eclipseContext = E4Workbench.getServiceContext();
//eventBroker = eclipseContext.get(IEventBroker.class);
eventBroker.send("ta/project_explorer/open_item", Collections.EMPTY_LIST);
}
}
}

Objects created using new are not injected. You need to use ContextInjectionFactory.make to create the object.
public class ProjectExplorerPart {
protected TreeViewer viewer;
#PostConstruct
public void createComposite(Composite parent, IEclipseContext context) {
//...
OpenProjectItemHandler handler
= ContextInjectionFactory.make(OpenProjectItemHandler.class, context);
viewer.addDoubleClickListener(handler);
//...
}
}

Another option is to annotate the class you want to inject with the #Creatable annotation like this:
#Creatable
#Singleton
public class OpenProjectItemHandler implements IDoubleClickListener {
...
}
And then use standard injection in object managed by the framework to inject your instance
public class ProjectExplorerPart {
#Inject private OpenProjectItemHandler opih;
#PostConstruct
public void createComposite(Composite parent) {
//...
viewer.addDoubleClickListener(opih);
//...
}
}

Related

How to use Spring Constructor DI in classes implementing an interface

So I want to achieve something like this:
#Component
public class ComponentA {
public void doThis(){};
}
#Component
public class ComponentB {
public void doThat(){};
}
public interface MyInterface {
void doSomething();
}
public class MyInterfaceImplA implements MyInterface {
private final ComponentA componentA;
#Inject
public MyInterfaceImplA(ComponentA componentA){
this.componentA = componentA;
}
public void doSomething(){
componentA.doThis();
}
}
public class MyInterfaceImplB implements MyInterface {
private final ComponentB componentB;
#Inject
public MyInterfaceImplB(ComponentB componentB) {
this.componentB = componentB;
}
public void doSomething() {
componentB.doThat();
}
}
What I basically want is to inject different components into different classes implementing the same interface.
My question is if there is a good way to set this architecture up in this or a similar way? Or is there a pattern to achieve this in a better way?

Inject different instance for reusable component with Guice

I am new do dependency injection and I'm trying to solve the following problem with Google Guice:
In a web application I have got tabs which need to be reused multiple times but each time with different dependencies on their UI component and model. Something like the code here:
class MenuTabView
{
private MenuTab fooTab;
private MenuTab barTab;
}
class MenuTab
{
private UiComponent component;
#Inject
public MenuTab(UiComponent component)
{
this.component = component;
}
}
class UiComponent
{
private Model model;
#Inject
public UiComponent(Model model)
{
this.model = model;
}
}
class FooComponent extends UIComponent {}
class BarComponent extends UIComponent {}
class FooModel implements Model {}
class BarModel implements Model {}
How can I inject FooModel and FooComponent into fooTab
and BarModel and BarCompoment into barTab?
I've read a lot about the different techniques available in Google Guice but none of them seams to fit this problem which, to my naive eyes, should be a simple one. I've tried to give fooTab and barTab binding annotations but they will only work if I inject the tab but not the dependencies of the tab. What would be the most convenient way to solve this problem?
This sounds like the common "robot legs" problem to me ... this is covered in the FAQ and can be solved by using private modules:
class LegModule extends PrivateModule {
private final Class<? extends Annotation> annotation;
LegModule(Class<? extends Annotation> annotation) {
this.annotation = annotation;
}
#Override
protected void configure() {
bind(Leg.class).annotatedWith(annotation).to(Leg.class);
expose(Leg.class).annotatedWith(annotation);
bindFoot();
}
abstract void bindFoot();
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new LegModule(Left.class) {
#Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("leftie"));
}
},
new LegModule(Right.class) {
#Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("righty"));
}
});
}

Dagger 2 does not generate subcomponent implementation

I've started to setup Dagger 2 and faced a strange issue that looks like a bug to me.
I have 1 main component and 2 subcomponents which I 'plus' in parent component. I use different scopes for each subcomponent. The problem is that I can easily do fields injection for the 1st subcomponent but I can't do the same for the second. The injected fields stay nulls.
Main component:
#Singleton
#Component(modules = { WalletSaverAppModule.class })
public interface MyAppComponent {
TrackingComponent plus(TrackingModule module);
DashboardComponent plus(DashboardModule module);
}
1st subcomponent (works well):
#PerActivity #Subcomponent(modules = { DashboardModule.class })
public interface DashboardComponent {
void inject(MainActivity activity);
}
2nd subcomponent (fields injection -> null):
#PerService #Subcomponent(modules = { TrackingModule.class })
public interface TrackingComponent {
void inject(IntentService context);
}
How I do fields injection for the 2nd subcomponent:
public class TrackingService extends IntentService {
#Inject CallCase mCallCase;
#Inject CallModelMapper mCallModelMapper;
...
#Override protected void onHandleIntent(Intent intent) {
((MyApp) getApplication()).getAppComponent().plus(new TrackingModule(this)).inject(this);
// ---> here the both fields are null
...
Objects that I'm injecting:
#Singleton public class CallCase {
private CallRepository mCallRepository;
#Inject public CallCase(final CallRepository userRepository) {
mCallRepository = userRepository;
}
public Observable<Call> execute() {
...
}
}
#Singleton public class CallModelMapper {
#Inject CallModelMapper() {
}
public CallModel transform(#NonNull final Call callEntity) {
...
}
}
Both objects have #Singleton scope (as their constructor fields). Could it be a scope conflict?
--- UPDATE ---
I've checked the class generated by Dagger2 (DaggerMyAppComponent) that I'm using in MyApp to build application component. I found the difference between implementations of 1st and 2nd components.
1st:
private final class DashboardComponentImpl implements DashboardComponent {
private final DashboardModule dashboardModule;
private Provider<DashboardMvp.Presenter> providesPresenterProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DashboardComponentImpl(DashboardModule dashboardModule) {
this.dashboardModule = Preconditions.checkNotNull(dashboardModule);
initialize();
}
private void initialize() {...}
#Override
public void inject(MainActivity activity) {...}
}
2nd:
private final class TrackingComponentImpl implements TrackingComponent {
private final TrackingModule trackingModule;
private TrackingComponentImpl(TrackingModule trackingModule) {
this.trackingModule = Preconditions.checkNotNull(trackingModule);
// ---> look, missing call initialize() <---
}
#Override
public void inject(IntentService context) {...}
}
Why Dagger 2 takes different the subcomponents that implemented in the same way? Only one difference I can see is the scope. I would appreciate any inputs about this problem.
Thanks in advance!
In TrackingComponent why are you inject to IntentService. Maybe changing to TrackingService will help
void inject(TrackingService context);

One interface multipe implementations. How get the right one at runtime

Lets say I have an Object with one boolean field.
public class AnyPojo {
private boolean b;
}
An interface DoAnything
public interface DoAnything {
void doAnything();
}
And two #Service annotated implementations of DoAnything
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
In another #Service class the boolean field of AnyPojo determines which implementation of DoAnything should be called. How can I achive that? I can use ApplicationContext here and make the decision like below. But not sure if there are better ways.
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowire
private ApplicationContext context;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo.getB()){
context.getBean(DoAnythingOneImpl.class).doAnything();
} else{
context.getBean(DoAnythingTwoImpl.class).doAnything();
}
}
First things first, if your class requires particular implementations, why don't you simply inject these classes?
If you have several implementations of an interface, you have to inform Spring framework which one you would like to inject into a class. You can distinguish implementations by their unique bean names:
#Service("oneImpl")
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
#Service("twoImpl")
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
And then inject both instances to the client service by marking which implementation should by assign to particular fields:
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowire
#Qualifier("oneImpl")
private DoAnything doAnythingOneImpl;
#Autowire
#Qualifier("twoImpl")
private DoAnything doAnythingTwoImpl;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo){
doAnythingOneImpl.doAnything();
} else{
doAnythingTwoImpl.doAnything();
}
}
Note that I would not call a service component from another service component to make sure I avoid potential redundant cycle in the future.
I would keep the following flow :
Controller ---canCall---> Services ---canCall---> Repositories
And if you need services with a more complex logic, then introduces the concept of Facade
Controller ---canCall---> Facades ---canCall---> Services ---canCall---> Repositories
However, here is a solution :
#Service("myServiceOne")
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
#Service("myServiceTwo")
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
You can autowire both services and choose the best one based on your boolean :
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowired
#Qualifier("myServiceOne")
private DoAnything serviceOne;
#Autowired
#Qualifier("myServiceTwo")
private DoAnything serviceTwo;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo){
serviceOne.doAnything();
} else{
serviceTwo.doAnything();
}
}
}

Java Bean Composite injection

I have an interface
public interface Abstraction {
void execute();
}
I have built a composite implementation and want to registered this object as the bean, #Named
#Named
public class Composite implements Abstraction {
private List<Abstraction> list;
#Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
How do I set it up so that the set of implementations to the abstraction gets injected properly into the Composite above? I will be having another object that takes the abstraction as a dependency and I want it to receive the #Named Composite above with the 2 Implementations below injected into the ctor.
public class Implementation1 implements Abstraction {
public void execute() { }
}
public class Implementation2 implements Abstraction {
public void execute() { }
}
If you create a bean for each of your implementations, your example will work out of the box. For example, annotate your implementations with #Named or #Component and mark them for scanning (component scan their package)
#Configuration
#ComponentScan
public class StackOverflow {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StackOverflow.class);
System.out.println(ctx.getBean(Composite.class).list);
}
}
interface Abstraction {
void execute();
}
#Named
class Composite implements Abstraction {
List<Abstraction> list;
#Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
#Named
class Implementation1 implements Abstraction {
public void execute() {
}
}
#Named
class Implementation2 implements Abstraction {
public void execute() {
}
}
The Composite's list will contain both implementations.
Alternatively, since you only have two implementations, you could name their beans and inject them separately. For example
#Component("one")
class Implementation1 implements Abstraction {
public void execute() {
}
}
#Component("two")
class Implementation2 implements Abstraction {
public void execute() {
}
}
and inject them in the Composite
List<Abstraction> list = new ArrayList<>(2);
#Inject
public Composite(#Qualifier("one") Abstraction one, #Qualifier("two") Abstraction two) {
list.add(one);
list.add(two);
}
I suggest this solution just because the order of initialization of Abstraction beans might mess up your context initialization. For example if Implementation1 somehow depended on the initialization of Composite, the context would complain. This is rare and you can control it in other ways. Still, being explicit about the beans might be clearer in this case.

Categories