I have a working call to a web service; we implement the logic to call the web service with a Spring bean configured with annotation:
#ManagedResource(objectName = "bean:name=XServiceMBean")
#Service("xService")
public class XServiceImpl implements XService
{
// working code here
}
For testing purposes, I would like to extend this class and inject the subclass instead of this one, so I made:
#ManagedResource(objectName = "bean:name=XServiceMBean")
#Service("xService")
public class XServiceImplTest extends XServiceImpl
{
// working code here
}
and commented out the two annotation lines from the superclass.
Spring doesn't like it. When I run, I get:
Error creating bean with name 'xService':Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'xService' must be of type [com.hsc.correspondence.rules.XService], but was actually of type [com.hsc.correspondence.rules.impl.XServiceImplTest]
I tried it again putting an explicit "implements XService on my subclass, with the same result.
Am I doing something illegal in Spring? The original XServiceImpl has a number of #Resource annotations in it; I didn't think that would matter, I expected them to get injected just like they did before.
Is there a way to do what I want to do, which is have a test class with absolute minimized changes to the original? (I would consider configuring in XML except I don't make those decisions in the project I'm on, but I didn't think it would matter to what I'm trying to do.
additional puzzlement: the error message says "Bean named 'xService' must be of type ...XService, but was actually of type XServiceImplTest". But XServiceImplTest implements XService, just like XServiceImpl does.
additional puzzlement #2: I copied the entire XServiceImpl to the class XServiceImplTest, commented out the annotations from XServiceImpl, and cleaned and rebuilt and ran. Got the same result. Now the only difference between the two classes is their class names. It gets stranger and stranger. Can anyone suggest why Spring might care what the class name is?
I see three possible causes for this:
Your code doesn't look like the one you are showing, and the inheritance hierarchy isn't there. (Since you say you directly added the interface this is unlikely, but you might want to double check your imports)
There is old compiled classes on the classpath. If there is an old compiled version lying around of XServiceImplTest this might get picked up. Try a clean of all class/target folders.
You are running in some kind of classloader issue, and the interface gets loaded by a different classloader than the test implementation. Put a breakpoint on the line where the execption is thrown and inspect the classloaders of the various classes involved.
You can do that by doing x.getClass().getClassLoader() on any instance of interest. In a plain vanilla application this will return the same instance for all x. In OSGI applications and web application you might get different ClassLoaders. The type of the ClassLoader and their parent relation ship should give some hint about what is going on.
They can't have the same name. You are calling "xService" to both classes.
You can give the subclass a diferent name "xServiceTest" for instance and inject that using #Qualifier.
Other thing, I'm not 100% sure but I think that you could have problems with this kind of inheritance. If you have, just create an abstract class that has all the common implementation and then create 2 sub-classes, the service and the test.
Hope this helps.
[UPDATE]
Can anyone suggest why Spring might care what the class name is?
You can check in your configuration for weird context:component-scan entries. Check if you have defined something like this:
<context:component-scan resource-pattern="<path>/*Impl.class" ...>
and/or some specific include/exclude criterias.
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).
I have a Spring bean class which requests dependencies to be injected. However, in my class, I am manually wiring different dependencies to the same private class variable. What happens in this scenario? Which injection takes precedent?
Details:
I have created a Spring bean class called BadmintonCoach.
It relies on an IfortuneService helper. IfortuneService is an interface with TWO different implementations. The two implementations are:
FortuneService_RESTful
FortuneService_Random
In my badmintonCoach class, I have created a private variable to receive the injection from Spring:
private IFortuneService theFortuneService
That is to say, I am manually wiring up the the injected dependency to this private member, theFortuneService
I am injecting these iFortuneService dependencies using method injection.
BUT here is the problem: I have TWO methods, both of which request an injection from Spring of the type iFortuneService. One method requests one implementation (FortuneService_RESTful) and the other method requests a bean of the other implementation (FortuneService_Random).
Both of these methods set this.theFortuneService equal to its respective requested helper. So what I have within my BadmintonCoach class is:
private IFortuneService theFortuneService
#Autowired
#Qualifier("fortuneService_Random")
public void randomMethod_ONE(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_ONE!");
this.theFortuneService = theFortuneService;
}
#Autowired
#Qualifier("fortuneService_RESTful")
public void randomMethod_TWO(IFortuneService theFortuneService) {
System.out.println("Code inside randomMethod_TWO!");
this.theFortuneService = theFortuneService;
}
My question then, is:
Which of the two wirings wins out? Why? How does Spring decide the ORDER of its injections? What determines the order of the injections? Is it random? Is it injected in alphabetic order of the method names? Is there an order of injection between constructor, setter, field and method injections?
What am I seeing when I run my program? I am seeing the injection of fortuneService_RESTful win out, but it is unclear to me whether this is by chance or by design from within Spring's logic.
Here is another thought:
What if, instead of requesting different implementations of the IFortuneService interface, the two methods above asked for the same bean but that bean was prototyped? Clearly, there would be a new incarnation created for each request and there would only be one helper class assigned to my BadmintonCoach class. But which incarnation would win out?
I can provide the whole of my code if it will make my question clearer.
If you are wondering WHY I have written conflicting code? It is plain and simple curiosity to try and understand how Spring works behind the scenes.
OK folks, it has taken a day for me to see this but I can confirm that what happens here is indeed random!
Yesterday, I was exclusively seeing method_ONE win out. Today, I am seeing method_TWO win out. I can therefore conclude that the order of injections by Spring is indeed random!
Thomas Klager had provided a suggestion in the comments above which may explain this phenomenon:
One obvious reason [for this] is that using annotation based injections, spring
needs to list the methods of a class using Class.getDeclaredMethods()
or Class.getMethods(). Neither of these methods return the methods in
any particular order.
I still find it a mystery how execution of the same logic by Spring (ie: Class.getDeclaredMethods() or Class.getMethods()) can yield random results like this.
It is very important to be aware of this limitation! When writing code, you may find yourself wanting to use the services of injected dependencies which in turn depend on the services other injected dependencies. It is clear from this experiment that this could potentially be dangerous and therefore you should not layer your wiring in this manner. That is to say, your wiring should always be single tiered if it spans multiple methods, otherwise, you risk spurious output from your program. An illustration of this danger can be seen in Slim's answer in this link.
My Spring app depends on a library that I need to override a class from, let's say com.dep.A. I want to create class B which extends A, and tell spring that every time A is trying to be loaded (by any code or dependency) I want to load B instead.
Is there a spring setting that would achieve this ? If not, would AspectJ be an option (I think Spring has an AspectJ feature) ?
EDIT: a bit more specific on the use case
If I were only able to plug myself into the execution flow of a specific method of class A, I'd be pretty please. In fact, forget about B extending A: what I am really trying to achieve is to intercept the execution of method A.originalMethod(MyObject o), and use o in my custom method B.interceptOriginalMethod().
Since the class is from a different library, it does not sound like it is a spring bean, and then Spring can't help you. It basically comes down to how the object is constructed, if the new operator is not called by you, but code inside the library you only have two options (Unless the Jar is signed, then I think there are no options).
Load time weaving. Which allows you to insert a cutpoint and replace the code of the method. This requires starting the JVM with a java agent, and should be a last resort.
If you have the source code, you can use class shadowing. You simply copy the class source into your source tree (same package name). This works because /classes is almost always before libraries in the classpath, so when the classloader try to load the class it will find your modified version, hence shadowing the original.
I have used option 2 a couple of times to fix minor issues in different open source libraries, when I was too lazy to rebuild the entire library from source. You have to be carefully when you upgrade the library, in case they have change the underlying code.
Use #Autowired with #Qualifier to load a bean by name instead of type. Below is the example
#Autowired
#Qualifier("b")
private A a;
The above code will load the reference of class B, provided B is also a spring bean.
Though #Klaus Groenbaek answer is correct (and I'll mark it as so), I have resolved my problem using another approach.
I was lucky enough that com.dep.A is annotated with Spring's #ConditionalOnMissingBean.
Therefore, simply create bean Bextending A and in your main application class declare:
#Bean
public A a(){
return new A();
}
Spring will load your class instead of the original one.
I'm having some troubles understanding how Guice's singleton instantiations works. I've read the available documentation (here - http://code.google.com/p/google-guice/wiki/Scopes ), but I still can't figure out some things:
I've integrated Guice with Tomcat, and I've set up some bindings in a ServletModule:
bind(MyServlet.class).asEagerSingleton();
serve("myUrl").with(MyServlet.class);
serve("myOtherUrl").with(MyOtherServlet.class);
(where MyOtherServlet class has a #Singleton annotation above it)
My intention here was to have two servlets, where one is eagerly instantiated, while the other isn't. However it seems like the "serve... with..." line automatically instantiates servlets objects, even though that class is not bound as an eager singleton.
The link I attached above mentions difference between Guice running under Stage.Development and Stage.Production - however this still happened even when I explicitly used Stage.Development (which is the default one anyway).
Is there any way to avoid this?
(continues 1) Trying to ensure that MyServlet gets instantiated first even though all servlets instantiate eagerly now, I've modified the order of modules (and binding statements) when creating an Injector, so that the binding for MyServlet appears first. However, I found that it still gets instantiated later than some other bindings (of non-servlet classes), which were of the form:
bind(MyInterface.class).to(MyClass.class).asEagerSingleton()
even though those other bindings appeared later in the modules/bindings order.
I've looked into it, and found that Guice simply instantiates eager singletons which were bound by the form of "bind... to... asEagerSingleton()" before it does ones of "bind... asEagerSingleton()", and so I solved it by modifying the line:
bind(MyServlet.class).asEagerSingleton();
into:
bind(MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()
and that actually worked. Still, I'd rather avoid having a dummy interface just to solve this, so I was wondering if anyone had a better solution for this..?
I have two Guice modules - one ServletModule and one AbstractModule.
The ServletModule configureServlets() has the following binding in it:
serve("aUrl").with(SomeServlet.class);
The AbstractModule's configure() has the following bindings:
bind(SomeImpl.class).asEagerSingleton();
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class);
Additionally, The SomeServlet class has an injected field of type SomeInterface, and has a #Singleton annotation on top of the class.
Now, one would expect that upon creating an injector, the SomeImpl class will get instantiated, and the same instance will be injected into the SomeServlet instance. As mentioned before, servlets bounded with a "serve... with..." statement also seem to get eagerly instantiated, but either way there should still be only one SomeImpl object instantiated. Yet for some reason, I got two SomeImpl objects instantiated when doing this.
To get around it, I mixed the two lines in configure() a bit, and instead of the above I had there the following lines:
bind(SomeImpl.class).in(Singleton.class)
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton();
and then it worked fine, and I got only one instance of SomeImpl instantiated. I don't really get why the switch should matter - I can see how the latter way is "better", but I'd expect both to work correctly, so I'm just wondering if I'm getting something wrong here...
1) There is no way to avoid this, since Guice calls the init() method of all servlets on initialization of its own filter pipeline and thus constructs them all. If you really need such lazy initialization logic, you should place it into the servlet itself (or use a decoupled helper class, or... there are many ways, depending on your use case).
2) Generally said, the modules of Guice declare bindings, there are not designed to be bootstrap definitions with precise instantiation orders. If you need such a defined instantiation order, create the objects yourself in the desired order and bind them via bind(...).toInstance(...). If you need injection in the self constructed instances you may use requestInjection(...) (if field/method injection is sufficient, it's more cumbersome for constructor injection).
3) The scope of Guice applies to the binding key, not the binding value, Applying Scopes describes why only your second example is working as intended.
I have an extremely puzzling situation and looking for any ideas.
I'm running a small Spring MVC app, where I make use of the RequestMapping annotation on my controller "AnsController". When RequestDispatcher is scanning my beans for the RequestMapping annotation, at some point it comes down to this line:
clazz.getAnnotation(RequestMapping.class)
(clazz = AnsController.class)
The line above does not find the annotation, even though it is there.
I started investigating this in Eclipse debugger and found a very puzzling problem. The reason why the above line fails is b/c RequestMapping.class is returning a Class object which seems to describe the correct annotation, but has a different internal id and hashCode then the Class object stored in the annotations array on the AnsController.class!
I wrote a test servlet where I placed the above line of code, and I can see that the Class stored in the annotations array and the Class returned by RequestMapping.class are the same object.
Yet in the RequestDispatcher servlet, RequestMapping.class seems to instantiate another instance of the Class for that same annotation (I can tell b/c the internal id is much higher than the id of the Class object in the annotations map).
In other words, calling RequestMapping.class in my Test Servlet results in a different Class object than calling exactly the same code in RequestDispatcher servlet.
Should this be even possible, assuming the same classloader is being used? Is this sufficient evidence to conclude that these distinct instances of the Class object that are supposed to represent one and the same annotation must be produced by different classloaders?
I can't find anything in writing that would confirm my assumption that only one instance of Class object per class is allowed, but it seems reasonable... Or am I wrong?
It seems reasonable, yes, but unfortunately it does not always work that way. Quoth the Java Language Specification:
At run-time, classes and interfaces are loaded by the Java virtual machine using class loaders. Each class loader defines its own set of classes and interfaces. As a result, it is possible for two loaders to load an identical class or interface definition but produce distinct classes or interfaces at run-time.
They must have been loaded by different class loaders. That's usually not a problem - the loader of RequestDispatcher should be the parent of the loader of the Controller; and a child loader should ask the parent loader first when a class (RequestMapping here) is requested; therefore both should see the same RequestMapping class.
If this is broken, all hell break loose; any Spring class that the Controller sees are different, and the framework and the controller cannot possibly interact.
Examine the class loader of the controller and see why it doesn't have the framework class loader as the parent.
For a given class T, there can only be one instance of Class representing T per classloader. Your question was "Should this be even possible, assuming the same classloader is being used?", and the answer to that is "No".
But it's also not a very good assumption in a web server context - most webservers start up zillions of classloaders, and you might very well get multiple copies of a class, one from each classloader.
If you're trying to do this inside a HandlerInterceptorAdapter subclass, you should use the handler parameter to get the class. I've had no problem pulling annotations off of controllers with this approach.
...
public void preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler)
{
Class clazz = handler.getClass();
...
}
...
And there we have it. After being convinced by all the answers here that I have a classloader mess, I was able to find the problem. I was bit in the ass by a hack I did a year ago :).
At the time I wrote an Eclipse plugin that I used to launch the Jetty 6 server with the app deployed in-place. That plugin placed all of the web project build dependencies on the AppClasspath via the commandline -classpath switch. This was desirable for the app I was using it for, b/c it allowed me to greatly simplify the classloading strategy in development mode for that specific case. In this case, however, I ended up with Spring jars on the AppClassLoader and WebClassLoader, b/c the Spring jars were in WEB-INF/lib.
Once I realized that, I just had to set parentLoaderPriority on WebAppContext to true in my jetty config and the problem went away. It's still a hack of course, but good enough for the quick-and-dirty app I'm doing here.
Thank you for all the helpful responses!