My spring-boot application has another library project included as a dependency. This library project has a spring.xml file where a number of beans defined. One of these beans has another external dependency injected which I don't need in my project. Hence this is throwing an error when I start my application. I want to define the same bean in my application as a java config and make spring-boot ignore the specific bean from spring.xml file. However I want all the other beans in spring.xml to be read.
Define a bean in your local java config with the same name and type as the one inherited in the spring.xml file.
Annotate your bean with #Primary which will make yours used over the imported one.
Your application will still use the definitions of all the other beans you inherit.
To prevent other defined beans loading that you do not actually need you have to change the bean creation to lazy configuration, that is, they only get created when explicitly used.
To do this in your main Spring boot class where the application is created, most likely annotated with #SpringBootApplication/ #Configuration/ #EnableAutoConfiguration/ #ComponentScan you should add #Lazy above it.
Usually you would explicitly annotate the Bean in question but here it cannot be done as it is originating in a spring.xml file in a 3rd party jar. The idea here is to cleanly state all beans are lazy from the highest point in the spring configuration.
It seems that you want to include spring.xml from other jar and exclude a bean in the xml.
I don't know spring framework provides some way.
I prefer to copy the spring.xml file to new project and remove the unnecessary bean.
Related
I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.
I would like to know how to copy one bean to an another using spring framework.
What configuration is required to be done in the beans.xml file for two beans
You can use BeanUtils class. http://docs.spring.io/spring-framework/docs/2.5.x/api/org/springframework/beans/BeanUtils.html.
No configuration required, just invoke:
BeanUtils.copyProperties(Object source, Object target);
My question is the following:
Is it possible to ignore XML configuration for HibernateValidator, i.e. exclude validation.xml parsing in a SpringBoot application?
I do not have the need for a validation.xml in my application, but I see that when the application starts up, it tries to parse this file.
I found this in the Hibernate Validator documentation (https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-xmlconfiguration.html):
It is even possible to ignore the XML configuration completely via Configuration.ignoreXmlConfiguration().
What I see is, that in the LocalValidatorFactoryBean.afterPropertiesSet() method, the configuration is created for the validator. This bean has a method called postProcessConfiguration(Configuration configuration), which is called before the validatorFactory is built from the configuration.
It seemed an ideal place to call the ignoreXmlConfiguration() method, what the documentation suggested.
I tried to extend this LocalValidatorFactoryBean, so that I can implement this call in the above mentioned method. Then I tried to load this bean via java configuration class.
Unfortunately some bootstrapping mechanism already uses the Spring provided bean, before it finds mine, the two beans run at the same time. I saw the message saying that XML configuration is ignored the with the bean I created, however, this solution did not help, because the Spring provided bean is not substituted with mine.
I also tried to find if there is any application property that I can use, or exclude some autoconfiguration, but no luck.
Any ideas? :)
UPDATE:
I tried excluding the HibernateJPAAutoConfiguration, it didn't help.
If you dont need hibernate validator then remove all dependency related to hibernate validator from pom.xml file.
you can also try #EnableAutoConfiguration(excludes=) annotation adding on your Application class to exclude default validation configuration.
like #SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class,DataSourceAutoConfiguration.class} })
Could you please list all possible sources of getBean?
BTW, If I just write context.getBean(SomeInterface.class), can I get the implementation of the interface class?
They come from the Spring application context (which is what you are calling the getBean method on).
Spring has this concept of an application context, which is an object that contains things such as all the beans managed by Spring.
You put beans in the application context by configuring them in a Spring XML configuration file or by annotating classes with annotations such as #Component, #Service etc. and then letting Spring find them by scanning packages for those classes.
If you write context.getBean(SomeInterface.class) and there is a Spring bean that implements that interface, then that method call will return the bean that implements the interface.
These are basic concepts of the Spring framework. See chapter 5, The IoC Container in the Spring documentation for a detailed explanation of how it works.
If you go into the ApplicationContext class hierarchy, you will find that all spring Application Context file are child of org.springframework.core.io.DefaultResourceLoader class.
What DefaultResourceLoader does is it get the current thread context class loader(if none is provided). So we can understand that all application context file first load the classes defined. Application Context load all the beans defined in xml file, marked using #Bean annotation or other available spring annotations. Once the context scan through the annotation and/ or xml and load all the beans in the class loader. Context first create the dependencies and inject them in dependent.
To get context.getBean(SomeInterface.class), please refer below documentation.
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/context/support/AbstractApplicationContext.html#getBean(java.lang.Class)
As per my understanding of documentation, you shall get the bean if exact one implementation bean class is defined.
Due to our requirements, we will have views and usecases that are deployment specific. Deployments will have generic and deployment specific parts (beans). This means that we would probaly need one context.xml file that would contain the generic beans for all deployments, and then deployment specific deploymentContext.xml for each deployment. This means that some POJOs exists in one deplyment, but not the other.
My questions:
1) is it possible to have deployment specific context files to extend the generic context file?
2) is it possible to describe a class in the deployment specific context file, that already exists in the generic context file? I.e. It would override the bean described in the generic context file, as in class inheritance.
3) is the approach described above feasible, or should the build descriptor instead dynamically generate the context.xml file? I would prefer the extension approach...
4) if I deploy all deployment specific contexts, but remove some of the POJO classes from the src directory, will the application break upon deployment or only after I try to instantiate the bean that does not exist?
Thanks a lot!
Not exactly the way you are asking, But Use of #Profile suits here
#Profile("dev")
public class SomeBean{
}
This bean will be only come to action if the profile set is dev
Document
spring-3-1-m1-introducing-profile
Also See
Is there any way to enable or disable the Spring bean definition in applicationContext.xml file?
How to set dynamically a bean reference in Spring?