I'm new to this and I want to understand when is it appropriate to use DI in Java. Suppose I need to ping different networks with different ping parameters:
The class PingParams:
public class PingParams {
int timeout;
int retries;
}
The class PingResult:
public class PingResult {
int ttl;
boolean available;
}
The class PingService:
public class PingService {
private PingParams pingParams;
#Inject
public PingService(PingParams pingParams) {
this.pingParams = pingParams;
}
public PingResult ping(String ip) {
// ping using timeout and retries from pingParams
return new PingResult();
}
}
The client:
public class Client {
#Inject
PingService pingService;
private List<PingResult> doPing() {
List<PingResult> ret = new ArrayList<>();
String[] ips = new String[] {"127.0.0.1","127.0.0.2"};
for (String ip : ips) {
PingResult pr = pingService.ping(ip);
ret.add(pr);
}
return ret;
}
public static void main(String[] args) {
List<PingResult> prs = new Client().doPing();
System.out.println(prs);
}
}
I have 2 injection points:
I inject PingParams in the constructor of PingService.
Is this correct? I mean, the DI container can not know the timeout and retries to inject into the PingParams unless you create some "Produces" annotated method, even in this case, it seams a looot of work just to create an object! But of course you need to create several, one for every network, how do you do that with DI?
I inject PingService in the client.
Seems legitimate, but PingService depends on PingParams, which takes us to injection point number 1.
Seems to me like the only appropriate way to use DI is with classes which have no dependencies (therefore useless) or with very simple service classes where you pass all the dependencies as parameters to service methods. For example a PingService which accepts the ip and the PingParams in the ping method, again this class would have no dependencies...
Am I missing something? How can you use DI with these "data" classes, classes which contain only fields for keeping data (PingParams)? Are suppose to avoid DI in these cases? Thanks
In general you should only use dependency injection for non-data classes. If you have classes that contain both data and non-data collaborators you can use assisted injection.
The ping params you talk about should indeed be bound to an instance on the start-up of your application and injected where necessary. For you example that is indeed much code but in the long run it keeps things nice and clean in bigger projects.
To summarize: bind PingParam when the application starts (as a Singleton for example), inject it into PingService, and create PingResult without DI (as you have done).
For Dependency Injection best practices, I recommend reading Dependency Injection by Prasanna
Assuming we're talking about CDI/Weld. Let's say your PingParams class were stored in the DB, as configuration loaded from some table. It would make a lot of sense to abstract that away, and simply provide a producer method for the PingParams class that reads the data from the DB and provides back this data element. It's not a bad idea to use a data object for this configuration, and provide a producer for it.
Related
Here is snippet of intrested case:
We have some configuration class it can have multi instances. It suppose that we supply several configurations in one bundle. It's one scope.
#Service
#Component
public class SampleConfigurationImpl implements SampleConfiguration {
// declaration of some properties, init method and etc...
}
Also we have a service which uses these configurations:
#Service
#Component
public class SampleServiceImpl implements SampleService {
#Reference(
referenceInterface = SampleConfiguration.class,
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC)
private Map<String, SampleConfiguration> sampleConfigurations = new ConcurrentHashMap<>();
private void bindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.put(sampleConfiguration.getName(), sampleConfiguration);
}
private void unbindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.remove(sampleConfiguration.getName());
}
#Activate
private void init() {
System.out.println(sampleConfigurations.size());
}
}
So, can I get some guarantees that on invocation of init method all configurations are injected (at least of current bundle)? Maybe there is some alternative way to do this. I understand that another bundles can bring new configurations and it's unreal to get guarantees but it's intrested in case of only one bundle.
On practice it can be case when in init method there are only part of configurations. Especially if it's more difficalt case when you have several types of configuration or one service uses another one which has dynamic references and first service relies on fact that everything is injected.
The most unpleasant is that it can bind/unbind configurations both before and after init method.
Maybe there is some way to guarantee that it bind always after init method...
I'm interested in any information. It will be great to get answer on two questions (guarantees before or after). Probably someone has experience how to resolve such problem and can share with me.
Thanks.
No, not that I know of. What I usually do in that case (depending on your use case, it depends on if your activation code is ok with running multiple times) is to create a 'reallyActivate' method I call both from the regular activate and from the bindSampleConfigurations (+ setting an isActivated flag in activate). Then I can perform some logic every time a new SampleConfiguration gets bound, even if it's after the activation. Does that help for your case?
So I have a class like so:
public class HBaseUtil {
private final String fileName = "hbase.properties";
private Configuration config;
private HBaseUtil() {
try {
config = new PropertiesConfiguration(fileName);
} catch (ConfigurationException e) {
// some exception handling logging
}
}
// now some getters pulling data out of the config object
public static String getProperty(String fieldKeyName) {...}
public static String getColumnFamily(String fieldName) {...}
// ... some more getters
// NO setters (thus making this a read-only class)
}
Thus, basically I have for myself a Singleton class, that the very first time that it is put to use, sets up a configuration object, and then simply keeps listening for get calls. There are a number of problems with this class:
Unit testing the static methods within class HBaseUtil becomes difficult because of a tight-knit coupling between the Singleton and the configurations file.
What I really want is me being able to supply the filename/filename+path to the class so that it can go in there, read the configuration properties from that file and offer them to incoming read requests. One important note here though: I need this flexibility in specifying the properties file ONLY ONCE per JVM launch. So I certainly don't need to maintain state.
Here is what I was able to come up with:
Instead of a Singleton, I have a normal class with all static methods and no explicit constructor defined.
public class HBaseUtil {
// directly start with getters
public static String getProperty(Configuration config, String fieldKeyName) {...}
public static String getColumnFamily(Configuration config, String fieldKeyName) {...}
// ...and so on
}
And then, instead of using the class in my other code like such:
HBaseUtil.getProperty(String fieldKeyName)
I'd use it like so:
Configuration externalConfig = new PropertiesConfiguration("my-custom-hbase.properties");
HbaseUtil.getProperty(externalConfig, fieldKeyName)
My questions:
Am I even thinking in the right direction? My requirement is to have the flexibility in the class only ONCE per JVM. All that needs to be configurable in my project for this, is the location/contents of the HBase .properties file. I was thinking having a Singleton is overkill for this requirement.
What other better approaches are there for my requirement (stated in above point)?
Thanks!
Note: I've read this StackOverflow discussion, but now it's gotten me even more confused.
You should avoid all static methods and instead design a class which does not mandate its lifecycle: it can be a typical immutable POJO with a public constructor.
Then, when you need it as a singleton, use it as a singleton. For testing, use it in some other way.
Usually, dependency injection is the preferred avenue to solve these problems: instead of hard-coding a pulling mechanism for your configuration object, you have the object delivered to any class which needs it. Then you can decide late what bean you will deliver.
Since you are probably not using Spring (otherwise dependency injection would be your default), consider using Guice, which is a very lightweight and non-intrusive approach to dependency injection.
I'm new to OSGi and I'm interested in retrofitting some of my jars as OSGi bundles.
However I do not want to introduce additional dependencies to any osgi-specific libraries.
As such annotations are out of the question as are programmatic calls to bundle contexts and what not.
I have found a near match to my requirements in declarative services which allows me to expose my lower level bundles without impacting dependencies however at the higher level (where i actually need to consume the services) i'm still a bit stuck.
I understand that the component xml can be used to declare implementations of services (which i already use for my lower level jars) but also to inject service instances into a specific POJO.
Now my question: how do I get access to the osgi-managed POJO which has the services injected into it? Is it at all possible without introducing new dependencies or do I have to do it programmatically?
If the latter is the case can someone point me in the direction of some code to do it, in other words the component-equivalent of bundleContext.getServiceReference()?
UPDATE
To clarify, if you take the fifth part of this tutorial: http://www.vogella.com/articles/OSGiServices/article.html
He declares a component.xml file which uses reference binding to inject a service into the object QuoteConsumer.
Great, now how do I get an instance of QuoteConsumer that has the necessary services injected into it, I can't very well do "new QuoteConsumer()" right?
UPDATE2
Currently I am registering the instance created by osgi as a static variable which can be requested, I'm thinking this is not the best method especially because I can't set the constructor to private. (the latter would at least result in a true singleton)
Basically the Factory class has:
private void activate() {
instance = this;
}
UPDATE3
A full example of a factory:
public class Factory {
private static Factory instance;
public static Factory getInstance() {
if (instance == null)
instance = new Factory();
return instance;
}
private MyInterface implementation;
public void setMyInterface(MyInterface implementation) {
this.implementation = implementation;
}
public void unsetMyInterface(MyInterface implementation) {
implementation = null;
}
public MyInterface getMyInterface() {
if (implementation == null) {
ServiceLoader<MyInterface> serviceLoader = ServiceLoader.load(MyInterface.class);
Iterator<MyInterface> iterator = serviceLoader.iterator();
if (iterator.hasNext())
implementation = iterator.next();
else
implementation = new MyInterfaceStub();
}
return implementation;
}
#SuppressWarnings("unused")
private void activate() {
instance = this;
}
#SuppressWarnings("unused")
private void deactivate() {
instance = null;
}
}
Any client code can then do:
Factory.getInstance().getMyInterface();
and receive the OSGi loaded service, the SPI loaded one or a stub.
You can still manually set the service instance if necessary.
UPDATE4
To clarify further: this pattern is not meant for applications that are designed from the ground up to be run in an OSGi container but rather for low level libraries that have to run everywhere and even when on an OSGi container must not assume that all consumers are actually using OSGi.
You sound confused ... :-) A service is a replacement for static factories so your factory should not have to exist.
The whole idea of DS is that for each component:
wait until its dependencies are met
create an instance
bind the instance to its dependencies
call activate on the instance
register the instance as a service
So whenever you get a service managed by DS it already is injected (bound) with its dependencies. So as long as you stay with service dependencies you never need static factories ... The whole idea of service is that you do NOT have static factories and can only work with (injected) instances. One of the best parts of OSGi is that you rarely work with factories.
One remark about the requirement not to use annotations. The OSGi annotations are class time only, they do not create a runtime dependency. I strongly suggest to use them since they make services as lightweight as a class and are typesafe in contrast to XML.
One trick to use the annotations and not clutter your code is to create extend your implementation classes that you want to be an OSGi component and add the annotations on this class.
To access a service, you declare a reference to it from another component:
#Reference
public void setFoo(Foo foo) {
this.foo = foo;
}
You might find the Bndtools tutorial will help to clarify the concepts.
I'd say you are on the right track. You can use a static field if it is convenient.
The important thing is that you make the rest of your code deal with the QuoteConsumer appearing and disappearing. So, put in your activator the code to do what you need to do when the QuoteConsumer is available (register it in some field, call some initialization code, I don't know) and put in your deactivate the code you need to indicate that the QuoteConsumer is no longer available.
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.
I am often confused by these three terms. These three look similar to me. Can someone please explain them to me clearly, with examples.
I have seen similar posts and don't understand completely.
Dependency Injection refers to the pattern of telling a class what its dependencies will be, rather than requiring the class to know where to find all of its dependencies.
So, for example, you go from this:
public class UserFetcher {
private final DbConnection conn =
new DbConnection("10.167.1.25", "username", "password");
public List<User> getUsers() {
return conn.fetch(...);
}
}
to something like this:
public class UserFetcher {
private final DbConnection conn;
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
This reduces coupling in the code, which is especially useful if you want to unit test UserFetcher. Now, instead of UserFetcher always running against a database found at 10.167.1.25, you can pass in a DbConnection to a test database. Or, even more useful in a fast test, you can pass in an implementation or subclass of DbConnection that doesn't even connect to a database, it just discards the requests!
However, this sort of primitive dependency injection makes wiring (providing an object with its dependencies) more difficult, because you've replaced accessing the dependency using a global variable (or a locally instantiated object) with passing the dependency around through the whole object graph.
Think of a case where UserFetcher is a dependency of AccountManager, which is a dependency of AdminConsole. Then AdminConsole needs to pass the DbConnection instance to AccountManager, and AccountManager needs to pass it to UserFetcher...even if neither AdminConsole nor AccountManager need to use the DbConnection directly!
An inversion of control container (Spring, Guice, etc) aims to make dependency injection easier by automatically wiring (providing) the dependencies. To do this, you tell your IoC container once how to provide an object (in Spring, this is called a bean) and whenever another object asks for that dependency, it will be provided by the container.
So our last example might look like this with Guice, if we used constructor injection:
public class UserFetcher {
private final DbConnection conn;
#Inject //or #Autowired for Spring
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
And we have to configure the IoC container. In Guice this is done via an implementation of Module; in Spring you configure an application context, often through XML.
public class MyGuiceModule extends AbstractModule {
#Override
public void configure() {
bind(DbConnection.class).toInstance(
new DbConnection("localhost", "username", "password"));
}
}
Now when UserFetcher is constructed by Guice or Spring, the DbConnection is automatically provided.
Guice has a really good Wiki article on the motivation behind dependency injection, and further using an IoC container. It's worth reading all the way through.
The strategy pattern is just a special case of dependency injection, where you inject logic instead of an object (even though in Java, the logic will be encapsulated in an object). It's a way of decoupling independent business logic.
For example, you might have code like this:
public Currency computeTotal(List<Product> products) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = beforeTax.times(1.10);
}
But what if you wanted to extend this code to a new jurisdiction, with a different sales tax scheme? You could inject the logic to compute the tax, like this:
public interface TaxScheme {
public Currency applyTax(Currency beforeTax);
}
public class TenPercentTax implements TaxScheme {
public Currency applyTax(Currency beforeTax) {
return beforeTax.times(1.10);
}
}
public Currency computeTotal(List<Product> products, TaxScheme taxScheme) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = taxScheme.applyTax(beforeTax);
return afterTax;
}
Inversion of control means that a runtime framework wires all components together (for example Spring). Dependency injection is a form of IoC (I don't know if another form of IoC exists) (see: http://en.wikipedia.org/wiki/Inversion_of_control).
Strategy pattern is a design pattern (defined by the GoF) where the algorithm can be replaced by another (see: http://en.wikipedia.org/wiki/Strategy_pattern). This is archived by provided several implementation of a same interface. When using an IoC like Spring, if you have several implementations of an interface, and if you can switch from an implementation to another by configuration, you are using the strategy pattern.
I also recommend reading the introduction chapter of Spring's documentation, which focuses on this issue: Introduction to Spring Framework
The first few paragraphs should do.
And this also links to: Inversion of Control Containers and the Dependency Injection pattern
Which also provides a motivational view of these very important core concepts.