Possible to autowire imported utility classes in Spring? - spring

I want to use data mappers, logger, transfromers, etc. in my Spring web projects. Is it possible to autowire an imported (jar) utility dependency, without wrapping it in some #Component or #Service class? Do we even want to do it that way, or should we just use a static reference?

If your utils, are based on not static methods, then this is simple:
If you use java based configuration, then just declare that util in an #Bean annotated method.
#Configuration
public class YourConfig {
#Bean
public YourUtil util(){
return new YourUtil ();
}
}
in xml it could been as simple as:
<bean id="util" class="org.example.YourUtil" />
The following is true, but it is not what was asked for:
There are at least two other ways to inject beans in instances that are not created (managed) by Spring:
(1) add #Configurable annotation to this class - this requires real AspectJ (compile-time or load-time -weaving)
#see Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
#see this answer of mine https://stackoverflow.com/a/7007572/280244 for a quick "guide" to enable the #Configurable support
(2) invoke SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
#see this question and its (two highes voted answers) for some ideas how to use

You can only #Autowire a bean managed by Spring. So you have to declare your instance through some configuration : a bean in an xml file, or a #Bean method in a java configuration.
#Component are just automatically discovered and registered in the spring context.

Related

How SpringBoot dependency injection works with different type of annotations

I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.

Spring framework #Configurable vs #Configuration

I seems have problem understanding these 2 annotation. I have try to read the javadocs but still cannot figure out. Can anyone help to explain with simple code about these 2 ?
Thank so much in advance.
You use #Configuration as a replacement to the XML based configuration for configuring spring beans. So instead of an xml file we write a class and annotate that with #Configuration and define the beans in it using #Bean annotation on the methods.
And finally you use AnnotationConfigApplicationContext to register this #Configuration class and thus spring manages the beans defined. Small example you can find at Spring Configuration Documentaion.
Quoting from the above link
It is just another way of configuration Indicates that a class declares
one or more #Bean methods and may be processed by the Spring container
to generate bean definitions and service requests for those beans at
runtime.
And #Configurable is an annotation that injects dependencies into objects that are not managed by Spring using aspectj libraries. i.e., you still use old way of instantiation with plain new operator to create objects but the spring will take care of injecting the dependencies into that object automatically for you.
#Configuration is the heart of the Java-based configuration mechanism and provides an alternative to XML-based configuration.
#Configuration classes are just like regular #Components classes, except that methods annotated with #Bean are used to factory beans.

Using proxy-target-class="true" with Spring beans

Im using Jersey Rest and want a Jersey filter to have access to some spring beans.
however as I've discovered from other threads, Jersey does not obtain Spring beans if they are Java proxies as opposed to generated java proxies. I want to add the proxy-target-class="true"
What are the impacts of doing so and also can this just be set on a single bean or does it need to be set on all referenced beans?
By setting proxy-target-class="true" you will be using CGLIB2 for your proxies, instead of jdk proxys.
The implications are the following, as described in the documentation:
final methods cannot be advised, as they cannot be overriden.
You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically
warn you when it needs CGLIB and the CGLIB library classes are not
found on the classpath.
The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass
is generated for each proxied object. For each proxied instance, two
objects are created: the actual proxied object and an instance of the
subclass that implements the advice. This behavior is not exhibited
when using JDK proxies. Usually, calling the constructor of the
proxied type twice, is not an issue, as there are usually only
assignments taking place and no real logic is implemented in the
constructor.
Also, you should be able to make a "target-proxy" for a specific component by using
proxyMode=ScopedProxyMode.TARGET_CLASS
Forcing a CGLib-Proxy although the controller formally implements an interface (SpringBoot 1.2.3.RELEASE with Spring 4.1.6.RELEASE):
#Controller
#Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class ServiceImpl implements ServiceIntf
{ .... }
This enables valid and working #RequestMapping and #Transactional annotations
Use the following annotation in Java Spring Config class:
#EnableAspectJAutoProxy(proxyTargetClass = true)
This is the way I made my test working:
MyTarget target = new MyTarget();
AspectJProxyFactory factory = new AspectJProxyFactory(target);
factory.setProxyTargetClass(true);

How to inject a Spring 3 Bean into a JSF 2 Converter

I am trying to #javax.naming.Inject a Spring 3 Bean called WtvrBean into a JSF 2 #FacesConverter.
Both the Bean and the Converter are on the same package. And, in my spring's applicationContext.xml, I am scanning this package:
<context:component-scan base-package="my-package" />
But this is not working. For sure, the JSF 2 internal class that uses the converter is
definitely not in my-package.
For instance, if I remove the #ManagedBean from a JSF 2 ManagedBean, and replace it to #org.springframework.stereotype.Component or #Controller, the WtvrBean can be #Injected on this ManagedBean, by using Spring WebFlow.
Well, as far as I know, there is no such thing as a #Converter stereotype in Spring.
I know I can use
FacesContextUtils.getWebApplicationContext(context).getBean("WtvrBean")
But, with that approach, the coupling between the web app and the spring is getting more tight. (annotations are metadata, and are not even considered dependency by some authors).
I am using FacesContextUtils so far, if there is no better solution.
Any ideas?
If you want to inject beans into instances of a class, these instances have to be spring-managed. I.e. spring has to instantiate them. And this is not happening, so - no, you can't inject there.
But this is because you register the converter within jsf. You can skip that:
#Component("myConverter")
public class MyConverter implements Converter { .. }
And then, if you are using the spring <el-resolver>:
converter="#{myConverter}"
So that will do it. It has worked for me.
(A workaround worth mentioning is that you can do it by using aspectj weaving and #Configurable, but I'd prefer your FacesContextUtils approach. The weaving modifies classes so that they become spring managed even if they are not instantiated by spring.)
#FacesConverter(value = "examTypeConverter")
#Named
Simple answer.
hey i was facing the same problem that spring beans are not getting injected in the JSF Converter.
then by googling about it i found the answers that after JSF 2.2 we can make converters as jsf managed bean. and then we can inject the spring dependency.
it solved my problem.
#ManagedBean
#RequestScoped
public class CustomerByName implements Converter {
#ManagedProperty(value = "#{customerDao}")
private CustomerDao customerDao;
and in your jsf page use it like a managed bean
converter="#{customerByName}"
Add #Scope annotation (eg with "request" parameter) to your managed bean.
#ManagedBean
#Scope("request")
public class MyBean {
....
}

How does Spring annotation #Autowired work?

I came across an example of #Autowired:
public class EmpManager {
#Autowired
private EmpDao empDao;
}
I was curious about how the empDao get sets since there are no setter methods and it is private.
Java allows access controls on a field or method to be turned off (yes, there's a security check to pass first) via the AccessibleObject.setAccessible() method which is part of the reflection framework (both Field and Method inherit from AccessibleObject). Once the field can be discovered and written to, it's pretty trivial to do the rest of it; merely a Simple Matter Of Programming.
Java allows you to interact with private members of a class via reflection.
Check out ReflectionTestUtils, which is very handy for writing unit tests.
No need for any setter, you just have to declare the EmpDao class with the annotation #component in order that Spring identifies it as part of the components which are contained in the ApplicationContext ...
You have 2 solutions:
To manually declare your beans in the XML file applicationContext :
<bean class="package.EmpDao" />
To use automatic detection by seeting these lines in your context file:
<context:component-scan base-package="package" />
<context:annotation-config />
AND to use the spring annotation to declare the classes that your spring container will manage as components:
#Component
class EmpDao {...}
AND to annotate its reference by #Autowired:
#Component (or #Controller, or #Service...)
class myClass {
// tells the application context to inject an instance of EmpDao here
#Autowired
EmpDao empDao;
public void useMyDao()
{
empDao.method();
}
...
}
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
Spring knows the existence of the beans EmpDao and MyClass and will instantiate automatically an instance of EmpDao in MyClass.
Spring uses the CGLib API to provide autowired dependency injection.
References
Usage of CGLib forum comment by Rod Johnson
3.3.1. Injecting dependencies
Pro Spring - Analyzing Spring Dependencies
Further Reading
Introduction to the Spring Framework by Rod Johnson

Resources