Spring inheritance peculiarity - java

I have a question regarding Spring inheritance:
Let's say I have a class (bean) BraveKnight that implements the interface Knight. After I declare this bean in the xml file with the id->knight, I'm trying to get a reference of the bean:
Knight knight = (Knight) context.getBean("knight");
This is the way it works. But why isn't possible to get the bean reference from the bean's name itself: BraveKnight (and why doesn't work with no interface at all)?
BraveKnight knight = (BraveKnight) context.getBean("knight");

First of all please use:
public <T> T getBean(String name, Class<T> requiredType)
instead of:
public Object getBean(String name)
You will avoid this nasty class cast.
Secondly your question about why it is not working with no interface is a little bit unobvious. I guess you have some kind of problem getting BraveKnight when it is not implementing any interface at all. If you want do that you have to force Spring to use CGLIB instead of dynamic proxy mechanism. If you have a problem with ClassCastException though when casting your bean to BraveKnight it means that Spring used dynamic proxy and implemented a $Proxy0 class which is only implementing Knigh interface and does not extend BraveKnigh directly. Whatever your problem is please try to get to know CGLIB and JDK dynamic proxy mechanism better so that you will not be surprised next time what Spring will do in the future with your objects.
If that answer does not correspond to your problem please try to attach some more info, stack trace or explanation.

You are getting the bean using its name: "knight". You're using the Spring bean name as the key.
If your question is "Why can't I look up the bean using its type", the answer is that you can as long as there's only one bean of that type. It's called "autowiring". Spring can do it for you if you add annotations and a couple of required XML tags.
As for why it won't work with no interface, who said it didn't? You can wire concrete class types with Spring.
A better question would be "When and why should I prefer to use interfaces in Spring?" The answer is that designing to an interface for those cases where implementation is likely to change is a good practice whether you use Spring or not. It makes it possible for Spring to generate dynamic proxies as needed (e.g. adding transactions to persistence objects).

You can call been without interface from application context without any problem.
You will need interface only when you use AOP Proxy, in that case any object reference called not by interface will cause exception.

You can use BraveKnight as the bean name if that makes it simple and easier for you to understand your mappings. Craig Walls Spring In Action used Knight as the bean name to make it clear your mapping is calling an implementation of Knight.
Again it would not work with an interface because in java you cannot instantiate an interface.
Mapping directly to Knight is exactly as doing;
Knight knight = new Knight(); // This is illegal
You will instantiate against the implementation of Knight to make it work, example:
Knight knight = new BraveKnight()//legal Implementation to Knight
This is the reason why the implementation was used as the mapping in the context file.

Related

How to know when to use component annotations and when to initialize classes manually in Spring Boot?

I am learning Spring Boot and have quite a theoretical question. In this Udacity Example the
model class is initiated manually:
ChatMessage newMessage = new ChatMessage();
Is it good practice?
I will elaborate further on this. Let's say I have a DateUtil class that does some date conversions, should I register it using #Component annotation or manage its dependency myself (DateUtil dateUtil = new DateUtil())?
So the main summarized question: How to know when to use component annotations and when to initialize classes manually?
Thanks a lot!!!
The answer to the first question is, yes, it's still okay, because beans are assumed to be singletones, although not always. In this case, it makes no sense to mark the ChatMessage class as a bean, since instances of this class will be created many times and it is absolutely unclear what benefit will be obtained if they are all beans and are located in the application context.
Answer to the second question: I think the DateUtil class should be instantiated in the usual way, because it looks like a regular utility class like StringUtils. Perhaps you should make its methods static and then you won't have to instantiate it at all. But if this is a complex class that contains business logic and / or is initialized with some data received from outside the application when it starts and this object of this class is used in other classes of the application, then it may be worth making it a bean.
The answer to the third question: it is difficult to give an unambiguous answer. Beans are worth creating when you want to achieve an inversion of control and not depend on the class you are injecting. Declaring a class as a component so that its instances become beans must make sense, bring an advantage to the design of the application.
You need experience with Spring applications to understand when to make beans. Take a look at some well-known Spring applications to understand in which case and which class instances are beaned.
As I know, when you create class with #Component (I like use #Service), Spring will create bean inside IoC. Then you can use that bean by #Autowired, with #Component you create only one instance, that will be shared all over the application. When you use 'new' method to create object, you create object by yourself. Check more info in bean scope doc.

Why aren't javabean features built into the root JAVA object?

I'm having a hard time understanding why javabeans are necessary and why they didn't just place the javabean features directly into the object class(root class) in java?
My understanding is you turn an object(instance) into a java bean and that way you get all the benefits like serializable and so on for all the objects in the bean. But if that is the case, why even have a separate bean class for this, why not just have built into the root object class?
Or am I not understand this?
You are not understanding it correctly.
There is no actual Java class or interface that is a bean. It is merely a pattern, a convention.
The bean convention is basically that a class will publicly expose some or all of its properties via public getXxx and setXxx methods, where XXX is the name of the property.
Beans generally should be serializable, but any class can be serializable, and does not need to follow the bean convention.
Besides that answer by Grey: even if there would be a Bean interface or method - not every fruit is an apple!
Meaning: there are zillions of classes that are just fine NOT being beans.
Beyond that: serialization as java does it was often found to be not that helpful. There are good reasons why we mostly serialize into JSON nowadays. In other words: we are pretty happy now that not all classes implement Serializeable by default; because Object being a Bean.
Just to talk about the no-argument constructor part of the bean pattern: A class does have a no argument constructor by default, but as soon as you create another constructor, that effectively removes it, as you probably know. But if you were forced to always have a no-argument constructor, this would be really annoying if you had a class which had a final field which is assigned by an argument in the constructor. You would then need to have some no argument constructor which either assigns everything to null, or throws an exception to tell other developers not to use the no argument so, which is just ugly.

Spring 4 not automatically qualifying generic types on autowire

PROBLEM HAS BEEN IDENTIFIED, POST UPDATED (Scroll to bottom)
I am developing a desktop application currently using Spring (spring-context, 4.1.6.RELEASE) for IoC and dependency injection. I am using an annotation configuration, using #ComponentScan. The issue I am experiencing is supposed to be implemented as a feature in 4.X.X, as it states here and here, but I am getting the old 3.X.X exception.
I have a parameterised interface that represents a generic repository:
public interface DomainRepository<T> {
T add(T entity) throws ServiceException, IllegalArgumentException;
// ...etc
}
I then have two concrete implementations of this, ChunkRepositoryImpl and ProjectRepositoryImpl, which are parameterised accordingly. They share some common implementation from an abstract class, but are declared like so:
#Repository
public class ChunkRepositoryImpl extends AbstractRepositoryImpl<Chunk> implements DomainRepository<Chunk> {
// ...+ various method implementations
}
#Repository
public class ProjectRepositoryImpl extends AbstractRepositoryImpl<Project> implements DomainRepository<Project> {
// ...+ various method implementations
}
My understanding of the above links leads me to believe that I should be able to autowire these without needing to manually specify the beans via #Qualifier. However, when I do so:
#Autowired
private DomainRepository<Project> repository;
I get the following exception (preceded by a long stack trace of course):
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.foo.bar.repositories.DomainRepository] is defined: expected single matching bean but found 2: chunkRepositoryImpl,projectRepositoryImpl
Can anybody shine a light as to why this might be happening? I would expect this exception in 3.X.X, but it should not happen in 4.X.X. What is the difference between my situation, and the one described here?
UPDATE
I have discovered the source of the problem. One of the methods in my DomainRepository<T> interface is marked as #Async, and makes use of Spring's asynchronous capabilities. Removing this means that the beans are correctly qualified. I hypothesize that Spring transforms classes with #Async methods under the hood into some other class, and this process strips the type information, meaning that it can't tell the beans apart.
This means I now have two questions:
Is this intended behaviour?
Can anybody suggest a workaround?
Here is a project demonstrating the problem. Simply remove the #Async annotation from the DomainRepository<T> interface, and the problem dissappears.
I hypothesize that Spring transforms classes with #Async methods under
the hood into some other class, and this process strips the type
information, meaning that it can't tell the beans apart.
Yes. That's exactly what happens.
Spring 4 supports injecting beans by their full generic signature. Given the injection target
#Autowired
private DomainRepository<Project> repository;
and a bean of type ProjectRepositoryImpl, Spring will properly resolve and inject that bean into the field (or method argument, or constructor argument).
However, in your code, you don't actually have a bean of type ProjectRepositoryImpl, not even of type DomainRepository<Project>. You actually have a bean of type java.lang.Proxy (actually a dynamic subclass of it) that implements DomainRepository, org.springframework.aop.SpringProxy, and org.springframework.aop.framework.Advised.
With #Async, Spring needs to proxy your bean to add the asynchronous dispatching behavior. This proxy, by default, is a JDK proxy. JDK proxies can only inherit the interfaces of the target type. JDK proxies are produced with the factory method Proxy#newProxyInstance(...). Notice how it only accepts Class arguments, not Type. So it can only receive a type descriptor for DomainRepository, not for DomainRepository<Chunk>.
Therefore, you have no bean that implements your parameterized target type DocumentRepository<Project>. Spring will fall back to the raw type DocumentRepository and find two candidate beans. It's an ambiguous match so it fails.
The solution is to use CGLIB proxies with
#EnableAsync(proxyTargetClass = true)
CGLIB proxies allow Spring to get the full type information, not just interfaces. So your proxy will actually have a type that is a subtype of ProjectRepositoryImpl, for example, which carries with it the DocumentRepository<Project> type information.
A lot of the above are implementation details and defined in many separate places, official documentation, javadoc, comments, etc. Use them carefully.

Spring Injection - Interfaces and Classes

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.

Spring #Autowiring, how to use an object factory to choose implementation?

I am trying to let a piece of runtime state decide WHICH implementation of an interface to use, preferably solely by autowiring.
I have tried making an object factory for the interface thet uses dynamic proxies, and I used qualifiers to coerce the #Autowired injections to use the factory. The qualifiers are necessary because both the factory and the implementations respond to the same interface.
The problem with this is that I end up annotating every #Autowired reference with the #Qualifier. What I'd really want to do is annotate the non-factory implementations with something like #NotCandidateForAutowiringByInterface (my fantasy annotation), or even better make spring prefer the single un-qualified bean when injecting to an un-qualified field
I may thinking along the totally wrong lines here, so alternate suggestions are welcome.
Anyone know how to make this happen ?
You could use #Resource and specify the bean name of the factory.
I haven't looked at this myself but I noticed Spring JavaConfig is made it to M4 and it seems to allow more flexible configuration through a combination of annotations and Java code. I wonder if it would offer a solution to your problem.

Categories