Applying same annotation on multiple fields - java

Is it possible to apply same annotation on multiple fields (if there are many private fields and it just looks awkward to annotate them all.
So What I have is like
#Autowired private BlahService1 blahService1;
#Autowired private BlahService2 blahService2;
#Autowired private BlahService3 blahService3;
and so on
I tried the following but it won't work
#Autowired{
private BlahService1 blahService1;
private BalhService2 blahService2;
}
Some thing fancy with custom annotations perhaps?

No, but you could annotate your constructor rather than your fields. This would have the additional benefit to make your class more easily testable, by injecting mock dependencies when constructing the instance to test (which is the main reason why dependency injection is useful) :
#Autowired
public MyClass(BlahService1 blahService1, BlahService2 blahService2, BlahService3 blahService3) {
this.blahService1 = blahService1;
this.blahService2 = blahService2;
this.blahService3 = blahService3;
}

There's nothing built-in to the language that allows that kind of multi-annotations.
Many frameworks however opt to allow some kind of "default-annotation" on the class level.
For example, it would be possible for the framework to allow an #Autowired annotation at the class level to imply that each field should be auto-wired. That's entirely up to the framework to implement, however.

You can try extending AutoWired annotation interface with setting default values of fields, setting its target type to fields, and whenever it is not required you can turn it of by passing appropriate values to annotations on only those fields.

Related

Eclipse RCP - Injecting interfaces marked with #Singleton

I have the following code:
public interface DummyInterface {
}
and
#Singleton
#Creatable
public class DummyInterfaceImpl1 implements DummyInterface {
}
And when I want I can simply inject this, and it works just fine, (see below):
#Inject
DummyInterfaceImpl1
However I can't do
#Inject
DummyInterface
Because I get an
Unable to process "ClassWhereIInject.dummyInterface": no actual value was found for the argument "DummyInterface".
So, I am trying to understand, if I use the combination of #Creatable and #Singleon, without adding the instance that I want to inject in the IEclipseContext, then I can only inject implementation classes and not interfaces?
I can see how this can get problematic, especially when one has multiple implementation classes for the same interface, and the dependency injection framework doesn't know which to inject...that is if you don't use the #Named annotation to specify...
The injection system only looks for something with the name you specify. It does not try and find a class that happens to implement that interface. So no you can't use an #Creatable class with a different name to the interface.
An alternative is to use a 'ContextFunction'. This is a function which is called when the injection system is looking for a name. The context function can create an instance of something suitable and put it in the context for the injector. Full details on context function are here

Any differences between 3 ways of dependency injection?

Is the 3rd one most common way to inject a bean? Any differences between them?
Bean constructor parameter injection:
public class Checkout {
private final ShoppingCart cart;
#Inject
public Checkout(ShoppingCart cart) {
this.cart = cart;
}
}
Initializer method parameter injection:
public class Checkout {
private ShoppingCart cart;
#Inject
void setShoppingCart(ShoppingCart cart) {
this.cart = cart;
}
}
Field injection:
public class Checkout {
private #Inject ShoppingCart cart;
}
An opinion-based answer, but it would seem that injecting through the constructor is best for the following reasons.
You can null check in the constructor, which might save you some error handling elsewhere in your class.
You can more easily inject mocks into your class for testing.
You can't forget to supply a dependency.
It doesn't look like magic.
Field injection is probably the most common. The reason is pretty obvious - it's the fastest way to connect things make it do something.
As for differences, there are some:
constructor injection
the only way to access other beans while you initialize this one
otherwise while instantiating beans, your bean field (field injection) will not yet work
example: you need data from other beans while creating this one; based on such data you determine for instance what strategy will this bean use for data storage
field injection
leads to lazy injection of beans (might be Weld specific, not sure now)
means if you don't do any extra work to make it eager, the bean will only actually be accessible once you first invoke a method on it
this is a go-to approach if you "just want the bean"
initializer method parameter injection
you will want this, if you need some extra work done at the moment you inject the bean
this event might happen more than once per bean lifecycle (that's what you have scopes for)
example of usage: you might want to fire an event once the injection happens
All in all, you are free to use any approach. The story here is that there are some use-cases which couldn't be covered by simple field injection.
This is just from the top of my head and is not exhaustive. I hope it sheds some light on the topic.

Dagger 2: When to use constructor injections and when to use field injections?

I was kind of lazy and used to use almost entirely field injections. I was just providing empty constructor, put my #Inject fields I everything was looking nice and simple. However field injection have its trade-offs so I've devised some simple rules that help me to decide when to used field and when to use constructor injections. I will appreciate any feedback if there is mistake in my logic or if you have additional considerations to add.
First some clarification in order to be on the same page:
Constructor injection:
#Inject
public SomeClass(#Named("app version") String appVersion,
AppPrefs appPrefs) {...
Same with the field injection:
public class SomeClass {
#Inject
#Named("app version") String mAppVersion;
#Inject
AppPrefs appPrefs;
Rule 1: MUST use field injection if I don't control creation of the object (think Activity or Fragment in Android). If some (non-dagger aware) framework is creating my object and handles it to me I have no choice but to inject it manually after I receive the instance.
Rule 2: MUST use constructor injection if the class is/may be used in another project that does not use Dagger 2. If the other project(s) do not use Dagger they cannot use DI so the user have to create the object the "old" way using new.
Rule 3: PREFER constructor injection when working with class hierarchies because it is easier to create unit tests.
Clarification:
Considering the following structure that uses field injection:
package superclass;
public class SuperClass {
#Inject
HttpClient mHttpClient;
...
}
.
package differentpackage;
public class SubClass extends SuperClass {
public SubClass() {
}
}
When I am creating unit test for SubClass in directory test/java/differentpackage I have no choice but to bring up the entire DI infrastructure in order to be able to inject the HttpClient. In contrast, if I was using constructor injection like this:
public class SuperClass {
private final HttpClient mHttpClient;
#Inject
public SuperClass(HttpClient httpClient) {
mHttpClient = httpClient;
}
}
in my unit test I could simply:
HttpClient mockHttp = mock(HttpClient.class);
Subclass tested = new Subclass(mockHttp);
// tests
So basically now I am in the other extreme: I tend to rely mostly on constructor injections and use field injections only when 'Rule 1' applies.
The only 'problem' that I have with the constructor injects is that for 'end' classes constructors sometimes become quite overloaded with parameters and they look verbose and ugly like this:
#Inject
public ModelMainImpl(#Named("app version") String appVersion,
AppPrefs appPrefs,
LoginPrefs loginPrefs,
#ForApplication Context appContext,
NetworkInfoProvider networkInfoProvider,
AndroidEventPoster androidEventPoster,
Session session,
ForgeExchangeManager exchangeManager,
HttpFunctionality httpFunctionality,
#Named("base url") String baseUrl,
#Named("forge result producer") ResultProducer<ForgeExchangeResult> resultProducer
) {
Guys, what are your rules to choose between constructor and field injects? I am missing something, are there errors in my logic?
Use constructor injection. if you can't, use property injection.
Rule 1 seems ok, like decorations or attributes you can use Property(field) injection.
Rule 2 seems ok, because who uses your class they have to follow your constructor. They may not know they have to intilaize your property also.
Rule 3 It's not just good for unit test. It's good for applying Single Responsibilty. It's easier to see your object graph.Otherwise you will hide it with property.
If we come in your question, yes there a lot of parameters in your constructor. But the solution is not property injection. You can refactor your code and use aggregate services

Using guice for a framework with injected classes, proper way to initialize?

I'm trying to write a framework where arbitrary bean classes are injected with classes from my API, and they can interact with both those classes as well have triggered callbacks based on defined annotations. Here's an example bean:
#Experiment
static class TestExperiment {
private final HITWorker worker;
private final ExperimentLog log;
private final ExperimentController controller;
#Inject
public TestExperiment(
HITWorker worker,
ExperimentLog expLog,
ExperimentController controller
) {
this.worker = worker;
this.expLog = expLog;
this.controller = controller;
}
#SomeCallback
void callMeBack() {
... do something
log.print("I did something");
}
}
I'm trying to use Guice to inject these beans and handle the interdependencies between the injected classes. However, I have two problems:
One of the classes I pass in (HITWorker) is already instantiated. I couldn't see how to move this to a Provider without significantly complicating my code. It is also persistent, but not to the Guice-defined session or request scope, so I am managing it myself for now. (Maybe if the other issues are overcome I can try to put this in a provider.)
More importantly, I need a reference to the other injected classes so I can do appropriate things to them. When Guice injects them, I can't access them because the bean class is arbitrary.
Here's some really bad code for what I basically need to do, which I am sure is violating all the proper dependency injection concepts. Note that hitw is the only instance that I need to pass in, but I'm creating the other dependent objects as well because I need references to them. With this code, I'm basically only using Guice for its reflection code, not its dependency resolution.
private void initExperiment(final HITWorkerImpl hitw, final String expId) {
final ExperimentLogImpl log = new ExperimentLogImpl();
final ExperimentControllerImpl cont = new ExperimentControllerImpl(log, expManager);
// Create an experiment instance with specific binding to this HITWorker
Injector child = injector.createChildInjector(new AbstractModule() {
#Override
protected void configure() {
bind(HITWorker.class).toInstance(hitw);
bind(ExperimentLog.class).toInstance(log);
bind(ExperimentController.class).toInstance(cont);
}
});
Object experimentBean = child.getInstance(expClass);
expManager.processExperiment(expId, experimentBean);
// Initialize controller, which also initializes the log
cont.initialize(expId);
expManager.triggerStart(expId);
tracker.newExperimentStarted(expId, hitw, cont.getStartTime());
}
Am I screwed and just have to write my own injection code, or is there a way to do this properly? Also, should I just forget about constructor injection for these bean classes, since I don't know what they contain exactly anyway? Is there any way to get the dependencies if I am asking Guice to inject the bean instead of doing it myself?
For context, I've been reading the Guice docs and looking at examples for several days about this, to no avail. I don't think I'm a complete programming idiot, but I can't figure out how to do this properly!
Your "experiment" seems to be something like a "request" in the sense that it has a defined lifecycle and some associated stuff the experiment can pull in at will.
Therefore I think you should wrap all that into a custom scope as described in the docs about Custom Scopes. This matches your case in several points:
You can "seed" the scope with some objects (your HITWorker)
The lifecycle: do "enter scope" before you setup the experiment and "exit scope" after you finished your work.
Access to "shared" stuff like ExperimentLog and ExperimentController: Bind them to the scope. Then both the framework and the experiment instance can simple #Inject them and get the same instance.

Can I annotate an inherited final property with #Autowire?

Resolution: No I'm no longer extending the original parent.
Original:
Is there a way to annotate an inherited final setter method? I am extending a class which has a final setter which I would like to #Autowire with Spring. The parent class is from a library and cannot be modified.
A workaround I have found is to write a proxy method, but this seems like more work than necessary.
public abstract class SqlMapClientDaoSupport ... {
public final void setSqlMapClient(SqlMapClient smc) {
...
}
}
#Component
public class AccountDao extends SqlMapClientDaoSupport {
// all this just to annotate an existing method?
#Autowire
public final void setSqlMapClientWorkaround(SqlMapClient smc) {
super.setSqlMapClient(smc);
}
}
Edit 1: Above example modified to reflect use case:
The use case is implementing DAO objects for Ibatis/Spring
which extend a common base class. Each DAO needs the same
property set, and each needs to be configured as a bean. I currently
do this by configuring each individually in applicationContext.xml.
<bean id="accountDAO"
class="com.example.proj.dao.h2.AccountDAOImpl"
p:sqlMapClient-ref="sqlMapClient" />
<bean id="companyDAO"
class="com.example.proj.dao.h2.CompanyDAOImpl"
p:sqlMapClient-ref="sqlMapClient" />
<!-- etc... -->
I would prefer to use component-scan to discover and autowire the DAO
objects automatically, which I can't copy/paste botch.
<context:component-scan base-package="com.example.proj.dao.h2" />
I do not see in the annotation guide how one would annotate a
property/member other than where declared. I'm hoping that is
something I'm missing though.
Edit 2: I am no longer extending the SqlMapClientDaoSupport class, instead my AccountDao is a POJO which implements what little functionality was being provided by the Support class. This allows me to use #Autowire at will.
Have you tried configuring it with xml? Because it's an existing class which it looks like you can't change, it's a definite candidate for configuring it with xml. Then you can specify it as autowire", or even configure the property in the xml.
It sounds to me like you shouldn't be trying to set a final field.
There is usually a good reason why fields are final.
Have you setup a SqlMapClientFactoryBean object ?
See here for help
No, there is no way to annotate an inherited final method.
Rather than extend the support class (SqlMapClientDaoSupport) I reimplemented it in my project (it's behavior is minimal) annotating the methods as needed, and my DAO extend that support class.
You could create a new constructor with params for all the setters that are final and #Autowired the constructor, then call the setters in the constructor.

Categories