I am having some problems understanding the concept of component instantiation in iPOJO. I read this guide
and I get the analogy to classes and objects but I still have some concrete problems and some conceptual problems that I hope someone can clarify
I thought I needed to create instances via iPOJO (#Instantiate or factories) only for service providers since they never use new because the impl is always hidden. However, I have some consumers #Component that I instantiate myself (say in a main() method where I call new on them directly). I made them #Component because they need to have things injected. I was assuming that the ipojo bytecode manipulation would make it so that when the objects were constructed, they would have their dependencies injected (I'm using mostly method injection with #Bind) but it seems that is not the case. Can someone clarify this to me please. Now it seems to me that for iPOJO to do any injection at all I need to always use one of the iPOJO instantiation techniques. The problem I have is that then the constructors I made in the consumer classes are not called.
This is a simplified example to illustrate my confusion
#Component(name="test")
public class MyFoo {
private List<External> externals; //injected
private Bar bar; //passed via constructor. Bar is *not* a #Component
public MyFoo(Bar otherBar) {
bar = otherBar;
externals = new ArrayList();
}
#Bind(aggregate=true)
public addExternal(External service) {
externals.add(service);
}
}
So, as can be seen here, I need to have all the providers of interface External, but I also need a Bar object that I pass when I construct the object using new MyFoo(someBar)
My problem is that if I need to pass a Bar to the constructor then I need to use new; but If i use new, iPojo never invokes my injection method. On the other hand, if I use iPOJOs instantiation (say I add #Instantiate) then the injection does happen but the constructor is not invoked, so the bind throws a NPE because the list has not been created yet + bar will not be set. I know I can create the list inside the bind method, but my question is more conceptual.
How are you supposed to accomplish this (framework injection + argument passing in the constructor)?
How can iPOJO be calling addExternal (which means the object has been created) without calling my one and only constructor that creates the object? this is very counter-intuitive in standard java
Are you just not supposed to use constructors when using iPOJO components maybe?
iPojo works similar to other DI (dependency injection) frameworks such as Blueprint (OSGi), Spring, Guice, etc. That is, in order to allow DI to do it's job you have to let the container (iPojo) manage the lifecycle of the object you're interacting with. So, your inclination was correct: You have to use one of iPojo's instantiation techniques. If you choose to use new on your object, your code is then managing the lifecycle (and thus you will manually need to "inject" all parameters).
In the example, your constructor isn't invoked because out of the box iPojo will support two main cases: The default constructor (MyFoo()) or the constructor accepting a BundleContext (MyFoo(BundleContext c)). iPojo also supports constructor service and property injection if you're on version 1.7.0 or later using #Requires / #Property respectively on your constructor variable (or the equivalent in your metadata).
When iPojo bytecode manipulation kicks in, it manipulates the bytecode to make it manageable by iPojo, not managed by iPojo. It does this by adding a MyClass(InstanceManager) constructor among other things that is used internally by iPojo when instantiating your object.
So, to answer your questions:
You can accomplish this by defining injected variables as either properties or service requirements and delegating to iPojo to create them. iPojo has multiple methods for interacting with instance creation, but the two you may be interested in are via the OSGi ConfigurationAdmin or the iPojo factory (assuming publicFactory is set to true on your #Component, which is the default). As an example using the config admin and assuming Bar doesn't live in the OSGi service registry your MyFoo class would look like this:
#Component(name="test")
public class MyFoo {
private List<External> externals; //injected
private Bar bar; //passed via constructor. Bar is *not* a #Component
public MyFoo(#Property(name = "somebar") Bar otherBar) {
bar = otherBar;
externals = new ArrayList();
}
#Bind(aggregate=true)
public addExternal(External service) {
externals.add(service);
}
}
Then, you would use the configuration admin (or iPojo factory) to create an instance. So, your main method would pull in the ConfigAdmin or the iPojo factory from the OSGi service layer (e.g. by pulling it out from the BundleContext, etc.), create a configuration with the "somebar" property set to your "new Bar()" and save that configuration. The iPojo managed service factory that is created for you will then instantiate a version of MyFoo with the new Bar you supplied in the configuration, injecting it into the MyFoo constructor:
...
Configuration config = configAdmin.createFactoryConfiguration(
MyFoo.class.getCanonicalName());
Hashtable<String, String> properties = new Hashtable<>();
properties.put("somebar", new Bar()); // This is where you new
config.update(properties);
// do something useful with the config if you need to update
// the instance or destroy it later.
...
The first parameter to the config admin's createFactoryConfiguration specifies the pid. In this case the pid is the name of the class, which is what iPojo will use by default unless you override it in your #Component annotation. Then you add your somebar to the properties and update the configuration. The iPojo factory is similar to this, though I believe it uses the builder pattern to create instances. It may be preferable to use the iPojo factory instead if you don't want to add a dependency on the OSGi config admin.
I'm no expert on iPojo internals, and I'm drawing a conclusion here based on what I've experienced and what I read in their documentation. As mentioned, iPojo does bytecode manipulation to augment your class to make it manageable by iPojo. One trait it adds to your class is a constructor with an InstanceManager. Since the constructor you've added has no metadata bound to it (i.e., annotations -- i'm assuming there is no manual metadata in a manifest or xml file) it more or less completely ignores that constructor and instead chooses to use the one dynamically generated by the bytecode manipulation process. Once it's done, it will eventually call your #Bind method to add the external service (since that method is marked up) and you will find yourself in the state you described.
The key here is to let iPojo manage the lifecycle of your object, as explained above. By calling a constructor you're in effect managing the lifecycle of that instance, so iPojo is out of the loop. So, you can either use constructors and manually "inject" parameters into it or rely on iPojo to do that for you.
Related
I am trying to apply ioc into a school project. I have an abstract class Application without any field
public abstract class Application {
abstract public void execute(ArrayList<String> args, OutputStream outputStream, InputStream inputStream) throws IOException;
}
And I will call the concrete class that extends Application by
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Application app = (Application)context.getBean(appName);
My questions are:
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
UPDATE
Here is the code snippet of the class where the instance of Application is needed.
String appName = argument.get(0);
Application app = ApplicationFactory.getApplication(appName);
ArrayList<String> appArgs
= new ArrayList<String>(argument.subList(1, argument.size()));
app.execute(appArgs, outputStream, inputStream);
Further questions:
in my code the class X will call the instance of Application by specifying a concrete application class name. In this case, it is still not possible for Spring to inject the dependency to Application, right? As what I need is a concrete class but not Application itself.
if Application does have fields but these fields are initialsed somewhere higher than X (X receives them as inputs and passes them to Application), can I use DI in this case?
Is it a bad practice to initialise a bean without any field (or all the fields are constants) using Spring?
No, its totally fine. Its true that you won't be able to "take advantage" of the automatic dependency injection mechanisms provided by spring (because obviously there are no dependencies in the class Application in your example), however spring can still:
Make sure that the Application as a singleton "obeys" the rule of being a single instance in the whole application context. For "manually" maintaining singletons you need to write code. Spring does it for you.
Manages the lifecycle of the object. Example, Spring has "postConstruct"/"preDestroy" methods that can can be run in the appropriate time and make example any custom code of the class Application.
If this class does some heavy-lifting (even without spring) than it can make sense to define it "lazy" so that the initialization of this instance will actually be done upon the first request to it.
Sometimes you/or spring itself will create a proxy of this class in runtime (for many different reasons, for example this aforementioned lazy functionality, but there are also other use cases). This is something that spring can do for you only if it manages the Application and not if its defined outside the spring.
Ok, you don't have dependencies in the application, This means that this Application class has some useful methods (at least on method, like public void foo() for
simplicity). But this in turn means that there is some class (lets call it X) that calls this method. So this class has an instance of Application as a dependency. So now the real question is who manages this class X. Probably it makes sense to manage it in Spring as well, and then you will benefit of the Dependency Injection mechanisms in this class X only because Application is also managed by Spring. In general Spring can inject dependencies only if these dependencies are managed by Spring.
I know, this last paragraph may sound vague given the use case you've presented, but you've got a point, for example in real application people make an initial bootstrapping in very certain places. Usually also people use spring boot that kind of encapsulates this kind of things for you.
As there is no dependency to other classes in Application, are we still consider this as a dependency injection or IOC? If no, what is the difference between this and a normal factory pattern? It seems that what Spring does here is simply matching the class and initializing it.
So as you see, the concept of DI container goes far beyond of what the factory pattern has to offer. In short, factory pattern only specifies the way to create the objects. Spring on the other hand, not only creates the objects but also manages them.
First, I very strongly suggest that you use Spring Boot instead of manually manipulating Spring at a low level like this.
It's perfectly ordinary to use beans that don't have their own fields for settings, but this is usually so that other beans can have pluggable strategies or providers and you can define in your application setup which to use.
If your Application class doesn't need anything else, then there really is not much advantage to Spring. Most real-world programs get complicated soon, however, and that's where it becomes useful.
Finally, you should almost never pass ArrayList as a parameter; use List instead. In the code you showed, however, if you have String[] args, you couldn't say app.execute(Arrays.asList(args), System.out).
In the Spring Framework, it seems like beans are the preferred way of creating objects to use in business logic.
[Dependency injection] is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.
So from my simple understanding, the difference is something like this:
// Plain ol' Java
Foo f = new Foo();
// Using beans in Spring Framework
Foo f = FooFactory.get();
Is it an oversimplification to say that as a rule, in methods outside of #Configuration classes and #Bean definitions, developers should only get objects using beans? Specifically, in the case where I want a fresh object, should I inject a prototype bean instead of using the new keyword directly?
One example of code where I'm not sure I'm following Spring conventions is shown below.
// Construct a new object that will be created in the database
RecordDto record = new RecordDto();
// Or should I be using some bean factory?
RecordDto record = RecordDtoFactory.get();
Please read this Article from beloved martin fowler.
I think the IOC concepts is useful when some component in your application has a dependency to other component for some functionality to complete. IoC container will be responsible for managing creation and lifecycle of software components and also inject them in dependent components instead of manually get access to these components instances.
For example, when some Service require an instance of DAO, it will get it from container instead of creating it.
But in case of DTO, they will just hold the data and that is not a real dependency. So I think using "new" is better in this case.
I am testing a set of classes that will, ultimately, be used to create beans within Spring contexts. I am using JUnit for testing. I want to ensure that when instances of these classes are instantiated programmatically within a test that the life-cycle methods and the #Required setters are correctly called. I know I can do this via a plain-old-java-proxy but am wondering if there exists specific tools within Spring (or elsewhere) that will help me.
I am looking to write something like
X x = ???.newBeanInstance(X.class);
x.setFoo(foo);
x.setBar(bar);
x.$postConstruct();
...
x.$preDestroy();
x = null;
The other, less desirable, option is to just create the context's XML and use it to initialize the instances.
If you bring-up the whole context, you can use the spring-test package and its #ContextConfiguration.
If you want to handle things manually, you are on your own (almost). If you have field injection, you can use ReflectionTestUtils to set dependencies. But apart from that you:
instantiate the object with new X()
call setters
call the initializer method (you should know which one it is)
call the destruction method in the end
What is the difference between creating a new object and dependency injection? Please explain in detail.
Well, they're not exactly comparable. You will always have to create a new object by instantiating a class at some point. Dependency injection also requires creating new objects.
Dependency injection really comes into play when you want to control or verify the behavior of instances used by a class that you use or want to test. (For Test Driven Development, dependency injection is key for all but the smallest example).
Assume a class Holder which requires an object of class Handle. The traditional way to do that would be to let the Holder instance create and own it:
class Holder {
private Handle myHandle = new Handle();
public void handleIt() {
handle.handleIt();
}
}
The Holder instance creates myHandle and no one outside the class can get at it. In some cases, unit-testing being one of them, this is a problem because it is not possible to test the Holder class without creating the Handle instance which in turn might depend on many other classes and instances. This makes testing unwieldy and cumbersome.
By injecting the Handle instance, for example in the constructor, someone from the outside becomes responsible for the creation of the instance.
class Holder {
private Handle myHandle;
public Holder(Handle injectedHandle) {
myHandle = injectedHandle;
}
public void handleIt() {
handle.handleIt();
}
}
As you can see the code is almost the same, and the Handle is still private, but the Holder class now has a much loser coupling to its outside world which makes many things simpler. And when testing the Holder class a mock or stub object can be injected instead of a real instance making it possible to verify or control the interaction between the Holder, its caller and the handle.
The actual injection would take place at some other place, usually some "main" program. There are multiple frameworks that can help you do that without programming, but essentially this is the code in the "main" program:
...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...
In essence, the injection is nothing more than a fancy set method. And of course, you can implement the injection mechanism using that instead of in the constructor like the simple example above.
Of course, both create objects. The difference is in who is responsible for the creation. Is it the class that needs its dependencies or a container like Spring for example, which wires the component's dependencies? You configure the dependencies in a separate(typically XML) configuration file.
It is really a separation of concerns. The class says I need this, this, and this component to function properly. The class doesn't care how it gets its components. You plug them into the class with a separate configuration file.
To give you an example let's consider having a shopping class that needs a payment module. You don't want to hardcode which payment module will be used. To achieve this you inverse the control. You can change the used payment module with a few keystrokes in the configuration file of the container. The power is that you aren't touching any Java code.
Well,
creating a new object is as explicit as it can get - you create a new instance of the desired class.
Dependency injections is a mechanism that provides you with references where you need them.
Imagine a class that represents a connection pool to your database - you usually only have one instance of that class. Now you need to distribute that reference to all the classes that use it.
Here is where Dependency Injection comes in handy - by using a DI framework such as Spring you can define that the one instance of your pool will be injected into the classes that need it.
Your question itself is not easy to answer since the creation of an object and dependency injection can't be compared that easily...
Dependency injections adds a layer of configurability into your application. In the sense, when you hard code object construction, you need to re-build and re-deploy your app, but when you use dependency injection, you can re configure the XML and change the behavior without re-building and re-deploying. There are a large variety of use cases where this can save a lot of tie and effort.
When using an inversion-of-control container to perform dependency injection, the container creates the objects, and not the developer. This is done so that the container can "inject" these objects into other objects.
The answer to the following question may also give the answer you are looking for: Why is the new operator an anti-pattern? Well, the simple answer is that using the new operator may create a hidden, inaccessible dependency within the containing class. This makes testing the containing class more difficult because it involves testing the hidden dependency at the same time (barring MOCK frameworks of course). However, you can avoid this situation by not using the new operator and injecting the dependent object instead. This also has the following advantages:
For test purposes you can inject a different object.
The resulting containing class is more reusable because it can support different implementations of the dependent object.
I want to be able to call Interfaces in my class, but have spring instantiate them with the right implementation class behind the scenes.
I.e. Normally you can do:
IClass clz = new Class();
I want to have the line IClass clz; preferable in the middle of a method (or as one of the attributes if it can't be done), where clz is instantiated to the class I want by Spring.
The reason I'd like to do it this way is because I want to be able to be able to change which implementation I want to use simply by editing the context files.
Even better, would be knowing how to do the above with class contructors that expect parameters. i.e. new Class(ar1, arg2);
I hope this makes sense. Any help would be much appreciated.
You can make your class implement BeanFactoryAware and then Spring will inject the bean factory in your class. If you then want to get an instance of a class implementing your interface you say something like:
beanFactory.getBean(IClass.class);
If there are multiple beans that implement the same interface you will have to resolve by name. To create a new object each time you ask this, set the bean scope of the bean you're asking for to "prototype".
You can include code such as:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
IClass clz = (IClass) context.getBean("beanName");
Not saying this is better per se than Gerco's answer btw, just it's an option, depending what you want to do.
You can also implement the ApplicationContextAware interface: I've found that using ApplicationContext gives me beans with filled-in properties, e.g. if you have an app.properties file which contains key/value property pairs which you expect to be resolved within the Spring config, beans retrieved via BeanFactory calls may not resolve those.
See this previous SO topic for more info.