I am using Spring Boot, and largely just using the autoconfiguration options for most of the components. However, I have found a few instances where I just want slightly different behaviour from the Beans.
What is the best/suggested approach to doing this? In many cases I don't want to have to turn off autoconfig just to change one property on the bean, so hoping there is some way I can sensibly update beans properties?
The case I have is the DispatcherServlet - I am happy with the autoconfig but I just want to change my DispatcherServlet so the DispatchOptionsRequest is set to true. I am hoping I don't need to turn off autoconfig and copy the configuration locally just to call that setter method?
The dispatcher servlet can be configured by declaring a bean of type DispatcherServlet named dispatcherServlet, then return an instance configured to your liking. This will override the previous declaration.
Example:
#Bean
public DispatcherServlet dispatcherServlet() {
DispatcherServlet servlet = new DispatcherServlet();
servlet.setDispatchOptionsRequest(true);
return servlet;
}
Related
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.
In app we have functionality of update configuration on fly. It overrides application properties and call:
((ConfigurableApplicationContext)applicationContext).refresh();
We are also using DelegatingFilterProxy to register Spring bean as a filter.
#Override
protected Filter[] getServletFilters() {
DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("myFilter");
delegatingFilterProxy.setContextAttribute(FrameworkServlet.SERVLET_CONTEXT_PREFIX + "dispatcher");
return new Filter[] { delegatingFilterProxy };
}
When I reload application.properties I see that Spring reccreate all beans but DelegatingFilterProxy still using first version of filter bean (so all requests are filtered by stale filter with stale autowired beans on it)
Do you know why it happens how to get rid of this?
I can tell you why it happens.
I'm assuming you're registering your DelegatingFilterProxy in a WebApplicationInitializer subclass, maybe an AbstractDispatcherServletInitializer subclass.
Regardless, this class is completely independent of actions to the ApplicationContext. The Servlet container scans your classpath and finds Spring's SpringServletContainerInitializer which finds your WebApplicationInitializer implementation and runs it. The DelegatingFilterProxy is then registered specifying a bean name.
When the first request comes in to your server, the DelegatingFilterProxy will attempt to find its delegate in the ApplicationContext and set it to its delegate field. It does this only if its current delegate is null. So a refresh of the context won't affect it.
There are possible solutions here.
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.
When I previously developed servlet applications without Spring, I could read configuration parameters like this in my servlet:
#Override public void init() throws ServletException {
ServletContext sc = getServletContext();
String someSetting = sc.getInitParameter("someSetting");
}
However, I'm developing an application with Spring MVC now, which means I no longer have a servlet myself, but use Spring's DispatcherServlet.
Now, how can I access those init parameters in spring-servlet.xml to pass them to one of my beans?
I'm using Spring 3, and am a n00b with it. Every time I see a bean without an id, my mind flips XD
I guess you can #Inject a ServletContext in your controllers, and take the params from there.
Of better, use #Value together with a specificPropertyPlaceholderConfigurer. See this answer
Do you really need these to be init-parameters in the Servlet context?
In Spring you can just inject values into your beans from a properties file using PropertyPlaceholderConfigurer.
I am using the Spring MVC for a project, and I am using the Spring DispatcherServlet to map the request's coming into the application to the controllers written elsewhere. I am looking for a way to have a default handler ( a catch all handler) if the request doesn't map to any of the exisiting controller-view maps. This currently shows a Resource not found exception, but I want to know if a catch all unmatched requests function is available in the Spring.
Every HandlerMapping strategy in Spring MVC has a defaultHandler property for just this purpose.
This is easy if your Spring config is already specifying a HandlerMapping object explicitly (e.g. a SimpleUrlHandlerMapping), but it's less obvious if you're relying on the defaults to supply a HandlerMapping for you.
For example, if you're using annotated controllers, then you're probably relaying on the default declaration of DefaultAnnotationHandlerMapping which Spring supplies automatically. However, you can provide your own bean to override the default:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="defaultHandler" ref="myDefaultHandler"/>
</bean>
This same pattern will work with any Handlermapping type, just substitute the class name.