I want to create a simple app built on Spring Boot. I don't have experience with the framework, and this issue is beyond me.
I want to use the Security module in my app, particularly the org.springframework.security.authentication.encoding.ShaPasswordEncoder class. I want to get this autowired as a bean.
How do I define that in Spring Boot? For instance, this answer explains how to use it in "regular" Spring - defining the bean in a XML file. However, when I was reading the Boot overview, it stated that there is no need for XML setup, so is it possible to somehow do this in code, not configuration? What is the Boot-ish way?
I have tried just using this code to get the encoder class.
#Autowired
private ShaPasswordEncoder passwordEncoder;
But I get an exception: org.springframework.beans.factory.NoSuchBeanDefinitionException -- it's not defined, but how do I define it?
Thanks
The beans can be defined in-code like this:
#Bean
public ShaPasswordEncoder passwordEncoder() {
return new ShaPasswordEncoder();
}
This method will create a bean named "passwordEncoder" which will be managed by Spring. It is the equivalent of the XML-styled
<bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" id="passwordEncoder" />
You can put this method in the #SpringBootApplication-annotated class, or any class annotated with #Configuration.
More info here
Related
I have been given a task to assign a property from .properties file to a non Spring bean class using #Value annotation. To do this, I created a method on a #Component annotated class and set the property into it, then called that method from the non Spring bean class. I thought this would work, however, still showing as null.
I was told this is because the #Component annotated class I used is not spring loaded. Question, how can I tell if a class is Spring loaded bean? I have been searching on google but can't find anything helpful aside from examples with #Component or #Configuration annotations. Thanks.
Spring Container is responsible for creating or managing beans. It all satisfy the dependencies by injecting them either through constructor or setter method. But in your case you want the #Value injection in your non spring bean which is really not possible as per my understanding. Because here the spring does not creating the object then how it satisfy the dependencies of it.
You have two options for this situation.
Either annotate class using #Component
Either read property file using Properties
https://www.mkyong.com/java/java-properties-file-examples/
I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.
With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.
Excuse me if this is has already been discussed, I could not find a satisfying answer.
I do not understand whats happening when i create a bean in Springframework and #Autowired it to a field in another bean. I understand the result of #Autowired and other annotations but i do not know how its done by Spring.
class Sample1{
//
}
class Sample2{
#Autowired
Sample1 sample1Bean;
}
<bean id="sample1Bean" class="...Sample1"/>
<bean id="sample2Bean" class="...Sample2"/>
My question is how does spring set the field sample1Bean in Sample2? i am not expecting a complete explanation, but a direction where i have to look would be great. Thanks.
The #Autowired, #Inject annotations are resolved by a BeanPostProcessor - specifically AutowiredAnnotationBeanPostProcessor. This bean post processor intercepts the creation(for cases where #Autowired is on constructors) of beans, setting of property on the beans to ensure that all the autowired fields are appropriately set.
Im no expert in Spring but I will answer what I know. When a spring powered web application starts up, Spring framework goes through bean instantiation process in the application context. While creating beans Spring checks the required dependencies for a given bean. It looks up a matching bean based on the required type of bean and autowires it when #Autowired annotation is specified.
In the above example, Spring will go through application context and create a bean(object) of type Sample1. When it will construct bean Sample2 it sees #Autowiredannotation and will look for instantiated bean of type Sample1. When it finds bean of type Sample1 it will inject that bean on Sample2 and finish creating Sample2. This is called dependency injection and is one of the very popular features of Spring framework.
Hope this helps.
I was reading Spring 3.0 documentation and I came to the sentence -
Annotation injection is performed before XML injection, thus the latter configuration
will override the former for properties wired through both approaches.
Next the question came to my mind:
If I use an annotation in a bean (like #Service("myService")), now I am using the other bean and it uses "myService", and "myService" would be injected through XML configuration.
Would this work? I tried but it is giving me
BeanCreationException (Cannot resolve reference to bean 'myService' while setting bean property 'myService')
Later, I went through this question Wiring Spring bean through annotations and xml context, but in the solution it is told that "Just leave all your annotated fields unspecified, and they'll get injected auto-magically." (I didn't try out this solution)
But what if I want to specify all annotated fields, like I specified #Service annotation above?
Any suggestions??
I figured out the answer, it works very well. Actually I forgot to add tag in xml configuration. We need to add this tag in each config file i.e. if you have written config file for service layer beans, add tag for service layer annotated beans. Similar for dao and controller layers.
You need to autowire your constructor like below...
#Autowired(required=true)
public UserService(DataSource dataSource){
this.userDS = new UserDS(dataSource);
}
So, in the above code the DataSource will be injected in the UserService automatically.