Programmatically instanciating objects thats classes have Spring life-cycle annotations - java

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

Related

initialize an instance without any field in spring

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).

Java best way to share an object across other objects without using static

I have class A which instantiate class B which in turn do same for class C and so on, forming a large tree. I now need to instantiate an object that should be available all across the tree and I don't want to individually inject this object manually in all classes. I don't want to use a static because there could be different instances of class A running concurrently in different thread and this shared object must be unique per thread. I don't have much experience with thread safe operations.
Use Spring to manage the instance. That way you can inject your instance into any class that needs it and, provided the creation of the parent class is spring managed, the injected bean will be populated.
In some more detail, what you can do is define a class.
public class MyBean {
// Add your class details.
}
And ensure that Spring is either scanning its package or you have defined the bean in your applicationContext.xml file like this. The next stage is to inject this bean where you need to, using the #Autowired annotation..
#Autowired
private MyBean myBean;
And on the creation of that class, myBean will be populated with the same instance of MyBean that was initially created.
Advantages
Doing it this way means that your solution scales well. You can inject it anywhere without constantly changing constructors (and when you're creating more and more sub classes and relationships between classes, this is a prime candidate for Shotgun Surgery.
It's always good to learn about technologies that are used in industry.
Managing a single instance of a class using other methods (like the Singleton pattern) is usually a bad idea.
Disadvantages
Spring does a lot more than just inject objects, and you're pulling down a lot of classes to do just this, which will increase the size of your solution, although not significantly.
Extra Reading
Have a look at a basic Spring tutorial to get you going.
Have a look at the different scopes that you can create beans with, in case some of them suit your needs better.
You either need a local reference in the context that you want to use the object or you need a static reference. Since you don't want to use static you need to get a local reference. You can do this by passing the object in in the constructor or by adding a setter method. Then higher up the tree where ever you construct the child node you pass in the needed object.
You can have kind of a "Parallel Singleton" so to say, i.e. instead of having only one instance it will keep as many instances as there are threads, in a hashmap with a thread-related object being the key.

How to do iPOJO instantiation

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.

Difference between creating new object and dependency injection

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.

Spring: How to assure that a class is only instantiated by spring and not by keyword new

Is it possible to assure that only spring can instantiate a class, and not by the keyword new at compile time? (To avoid instantiating by accident)
Thank you!
If you want to detect it at compile time, the constructor must be non-public.
Private is probably too strict (it makes code analysis tools assume it will never be called, and may even cause warnings in some IDEs), I'd say the default (no modifier, package protected) is best there. In cases you want to allow subclasses in other packages (but that's impossible without allowing calling the constructor directly from that subclass) you can make it protected.
Make sure to comment the constructor appropriately, so it is clear to anyone reading the code why the constructor is like that.
Spring will call this non-public constructor without any problems (since Spring 1.1, SPR-174).
The question if this not allowing anything else to call your constructor, the idea of forcing every user of a class to use the Spring dependency injection (so the whole goal of this question) is a good idea or not, is a whole different matter though.
If this is in a library/framework (that is just usually used with Spring), limiting the way it may be used might not be such a good idea. But if it's for classes that you know will only be used in your closed project, which already forces the use of Spring, it might make sense indeed.
Alternatively, if your real goal is just to avoid the possibility of someone creating an instance and not initializing it with its dependencies, you can just use constructor dependency injection.
And if your goal is only to prevent accidental usage of the constructor (by developers not aware that the class was supposed to be initialized by Spring), but don't want to totally limit possibilities, you can make it private but also add static factory method (with an explicit name like createManuallyInitializedInstance or something like that).
Bad idea: Another possible alternative is to make the constructor publicly available, but deprecate it. This way it can still be used (without resorting to hacks like using reflection) but any accidental usage will give a warning. But this isn't really clean: it is not what deprecation is meant for.
The only obvious way I can think of doing this is at Runtime via a massive hack; Spring works with normal Java after all (i.e. anything that can be accomplished in Spring must be accomplishable via standard Java - it's therefore impossible to achieve as a compile time check). So here's the hack:
//CONSTRUCTOR
public MyClass() {
try {
throw new RuntimeException("Must be instantiated from with Spring container!");
}
catch (RuntimeException e) {
StackTraceElement[] els = e.getStackTrace();
//NOW WALK UP STACK AND re-throw if you don't find a springframework package
boolean foundSpring = false;
for (StackTraceElements el : els) {
if (el.getDeclaringClass().startsWith("org.springframework")) {
foundSpring = true; break;
}
}
if (!foundSpring) throw e;
}
}
I really would not advise doing this!
While I can understand why you would want to ensure that a class is instantiated only by Spring, this is actually not a good idea. One of the purposes of dependency injection is to be able to easily mock out a class during testing. It should be possible, then, during unit tests to manually instantiate the various dependencies and mock dependencies. Dependency injection is there to make life easier, and so it is usually good to instantiate with DI, but there are cases where using new is perfectly sensible and one should be careful not to take any design pattern or idiom to the extreme. If you are concerned that your developers are going to use new where they should use DI, the best solution for that is to establish code reviews.
I'll tell you why not to do this - you won't be able to mock your classes. And thus you won't be able to make unit-tests.
Not sure if Spring supports this as I haven't tried, and haven't used Spring in quite awhile, however with another IOC container a sneaky route I once took was to make the class one wishes to be returned as your injected interface an abstract class, and have the IOC container return that as a derived class instance. This way no-one can create an instance of the class (as it's abstract) and the container can return a derived class of this.
The container itself will generate the definition of the derived class so there's no worry of someone trying to construct one of these
Write an aspect around the call to the constructor and abort if not via Spring
don't know about spring, but if you want to have some control on creating new instances, you should make constructor private, and create public static YourClass getInstance() method inside your class which will handle checks and return new instance of that object. You can then create new class with constructor whichi will call getInstance().. and hand that class to Spring. Soon you will discover places where you had that 'illegal' calls outside spring...

Categories