I am implementing some classes in my application and I am little bit confused on choosing AppContext vs AppConfiguration.
My application configs are in YAML files which are parsed in application startup. Currently we are planning AppContext for just simple properties and AppConfiguration for getting complex properties/arrays.
ApplicationContext is basically backbone of running Spring, while configuration is definition how to do that. So context must know how to instantiate a bean - that is why bean factory is mandatory. Also context can have parent context. There are some other things that context is responsible for - please read the doc.
Configuration can define context, or provide other static information used by the app to do what is needed. That information can be taken from many sources, can be refreshed, and so on - but still - that is more like parameter, input for context.
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.
The definition of the spring ApplicationContext is very ambiguous, I almost finish a whole book of tutorial but still cannot understand what is the ApplicationContext stand for.
According the Spring API, ApplicationContext is:
Central interface to provide configuration for an application. This is read-only while the application is running, but may be reloaded if
the implementation supports this.
The root interface for accessing a Spring bean container. This is the basic client view of a bean container.
From above, my questions are:
1) I keep seeing the book mentioned "container", what is the container refer to? One container does it mean one java process? or one container refer to one ApplicationContext object?
2) If i instantiate two ApplicationContext in one java application (both in main body), are these two interfaces to one central container? Or two separate instances? See the code below, what is the difference between context1 and context2? If there is a Singleton in Beans.xml, it is invoked by context1 and context2, are they two separated instances or the same instance?
ApplicationContext context1 = new ClassPathXmlApplicationContext("Beans.xml");
ApplicationContext context2 = new ClassPathXmlApplicationContext("Beans.xml");
First you questions :
1) I keep seeing the book mentioned "container", what is the container refer to? One container does it mean one java process? or one container refer to one ApplicationContext object?
The ApplicationContext is the central interface, but the underlying container is a BeanFactory. More exactly, BeanFactory is a lower level interface implemented by all Application contextes from which you get the Beans. In that sense, I think that the word container stands here for the BeanFactory - one per ApplicationContext.
2) If i instantiate two ApplicationContext in one java application (one Main body), are these two interface to one central container? Or two separate different instance? See the code below, what is the difference between context1 and context2? If there is a Singleton in Beans.xml, it is invoked by context1 and context2, are they two separated instance or same instance?
ApplicationContext context1 = new ClassPathXmlApplicationContext("Beans.xml");
ApplicationContext context2 = new ClassPathXmlApplicationContext("Beans.xml");>
With that instanciations, you will get 2 totally independent application contexts. One bean declared in first will not be found in the other.
BUT
It is common to have more than one application context in a Web application, because Spring has a notion of hierachies of ApplicationContext. You could declare them as :
ApplicationContext context1 = new ClassPathXmlApplicationContext("Beans.xml");
ApplicationContext context2 = new ClassPathXmlApplicationContext("Beans.xml", context1);>
Here you can retrieve from context1 only beans declared in it, but from context2 you will retrieve beans from context2 and context1. Specifically, beans are first looked for in context2 and if not found then looked for in context1.
This is used in Spring MVC where you normally have one root context (for all beans not directly related to the MVC DispatcherServlet) and one child context dedicated to the DispatcherServlet that will contain the beans for controllers, views, interceptors, etc.
By container they refer to the core spring Inversion of Control container. The container provides a way to initialize/bootstrap your application (loading the configuration in xml files or annotations), through use of reflection, and to manage the lifecycle of Java objects, which are called beans or managed objects.
During this initial phase, you do not have (normally, yet it is possible) control in your application, instead you will get a completely initialized state for the application when the bootstrapping is done (or nothing, in case it fails).
It is a replacement, or possibly an addition, to what is called an EJB3 container; yet, the spring provided one fails to adhere to the EJB defined standard. Historically, adoption of EJB has been limited by the complexity of that specification, with spring being a newly created project for having EJB3 comparable features running on a J2SE jvm and without an EJB container, and with much easier configuration.
ApplicationContext (as an interface, and by the direct implementation flavours) is the mean of implementing this IoC container, as opposed to the BeanFactory, which is now (a sparsely used and) more direct way of managing beans, which by the way provides the base implementation features for the ApplicationContext.
As per your second question, you can have multiple instances of ApplicationContexts, in that case, they will be completely isolated, each with its own configuration.
I keep seeing the book mentioned "container", what is the container
refer to? One container does it mean one java process? or one
container refer to one ApplicationContext object?
Here container means spring container which is nothing but ApplicationContext. This internally reads spring configuration and loads the classes based on configuration. You may think it as SpringProcessor which provides the various functionality like bean initialization, injection, i18n, bean Post processing etc off the shelf
with
ApplicationContext context1 = new
ClassPathXmlApplicationContext("Beans.xml"); ApplicationContext
context2 = new ClassPathXmlApplicationContext("Beans.xml");
There will be two conatiners , hence two singleton beans. Here singleton means singleton instance per container. Ideally you should have only one container until and unless you have a reason for two. For learning purpose it makes sense to understand the concepts
ApplicationContext is an implementation of a Spring container. In simple words Spring container manages the entire Spring application via an ApplicationContext. Spring container via ApplicationContext manages the life cycle of a Spring bean i;e from initiation to destruction.
A spring container is nested inside a J2EE container.
I keep seeing the book mentioned "container", what is the container
refer to? One container does it mean one java process? or one
container refer to one ApplicationContext object?
A container manages the life cycle of an object. Tomcat is a an example of a container. Just like Spring container manages the app via ApplicationContext a J2EE container Tomcat manages the app via web.xml
A container provides communications support. Security in a web application. JSP support, Internationalization, event-propagation & many other features. It supports multithreading, spawns a new thread for every request for a resource. You don't have to explicitly write the code for that. Just like a spring container, a J2ee container manages a servlet life cycle.
If i instantiate two ApplicationContext in one java application (one
Main body), are these two interface to one central container?
If you want to instantiate multiple ApplicationContexts in your application. It will be in a parent child hierarchy. There will be one root ApplicationContext & then there will be child ApplicationContext respective to every DispatcherServlet. Beans global to the application will be defined in the root ApplicationContext. All the ApplicationContexts will be managed by only one spring container.
container is a Java object, an instance of one of ApplicationContext implementations like ClassPathXmlApplicationContext.
It is 2 different containers, if Beans.xml has a singleton bean B1, then context1.getBean("B1") and context2.getBean("B1") will return 2 different instances of B1
You added a "java-ee" tag. Spring is often used in web applications running on a application server. Typically each web application would have it's own application. The web applications are separated and probably that is what is called container in the documentation as you cannot regularly share variables with different applications / containers.
You can have two contexts within an application. If you have two contexts each will have its own singleton.
I keep seeing the book mentioned "container", what is the container refer to? One container does it mean one java process? or one container refers to one ApplicationContext object?
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.
The interface org.springframework.context.ApplicationContext represents the Spring IoC container. The container gets details or instructions i.e. what objects need to be instantiated, configure and assembly by reading configuring metadata.
Application classes are combined with configuration metadata so that after the ApplicationContext is created and initialized, you have a fully configured and executable system or application.
If i instantiate two ApplicationContext in one java application (one Main body), are these two interface to one central container? Or two separate different instance? See the code below, what is the difference between context1 and context2? If there is a Singleton in Beans.xml, it is invoked by context1 and context2, are they two separated instance or same instance?
As mentioned by others as well you can have multiple application contexts.
I'm attempting to use the spring-cloud stack for a project that would use Zuul. In my organization we have a custom configuration stack that is xml-based and does property composition and hierarchical overrides. Because of the way this configuration is handled, I've struggled to create a PropertySource for it.
My custom PropertySource must use my Config bean, but because the PropertySources are initialized during the bootstrapping of spring boot, the application context is not fully initialized yet and I can't get to my custom Bean that exposes our xml-based configuration system.
#ConfigurationProperties appears to be entirely biased toward .properties and .yaml files. The Config bean is initialized in an ApplicationContextInitializer. Is there a way to delay the resolution of the ConfigurationProperties within the various services so I can construct my custom property source using my Config bean after it is initialized?
I originally attempted (well before asking the question) to create a custom PropertySourceLocator in my config (as mentioned by Dave Syer and well documented in the link he gave) and register it with my own spring.factories (Again, demonstrated in the helpful link given by Spencer Gibb in the comment.) The problem is that my property source needs to be configured after some work that is done in an ApplicationContextInitializer and the property sources all seem to be resolved before that occurs (at least those wired in as a factory for org.springframework.cloud.bootstrap.BootstrapConfiguration). I guess I hinted at this by stating that I needed a particular bean in my PropertySource that I couldn't get from the ApplicationContext at the time.
Anyway, to get around that, I am now registering the property source in an PriorityOrdered ApplicationContextInitializer to take place after another one that initializes my config object. Something like: context.getEnvironment().getPropertySources().addFirst(myPropertySource);
This seems to get my property source into the environment at the correct time and allows me to perform customization of the context before hand as needed.
In Spring Cloud you would need to register some BootstrapConfiguration (per the user guide: http://projects.spring.io/spring-cloud/spring-cloud.html#customizing-bootstrap-property-sources) that has a PropertySourceLocator bean. It shouldn't be any harder than that.
P.S. #ConfigurationProperties is not biased toward .properties and .yaml files - it binds to the Environment which knows nothing about file formats.
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.
Upon starting my webapp within Tomcat 6.0.18, I bootstrap Spring with only what is necessary to initialize the system -- namely, for now, database migrations. I do not want any part of the system to load until the migrations have successfully completed. This prevents the other beans from having to wait on the migrations to complete before operating, or even instantiating.
I have a startup-appcontext.xml configured with a dbMigrationDAO, a startupManager which is a ThreadPoolExecutor, and lastly, a FullSystemLauch bean. I pass a list of configuration locations to the FullSystemLaunch bean via setter injection. The FullSystemLaunch bean implements ServletContextAware, gets a reference to the current WebApplicationContext and thus I can have a ConfigurableListableBeanFactory. Unfortunately, this bean factory isConfigurationFrozen() returns true, so by calling beanFactory.setConfigLocations(configLocations) has no effect.
Can I accomplish this or is Spring preventing me from doing so because it's a bit out of the ordinary? It seems reasonable if understood, but also a bit dangerous. And yes, I'm willing to blow away the current context b/c the currently loaded Singletons are not needed once initialization is complete.
Thank you for the help.
My opinion would be to allow Spring to initialise your beans is it sees fit - in the order of their declared dependencies.
If you need database migrations there are a couple of patterns to have them run first:
if you're using Hibernate/JPA make your sessionFactory/persistenceManager depend-on the migration beans;
if you're using plain JDBC create a wrapper DataSource and in its init-method invoke the migrations ( code sample)
The advantage is clear: simplicity.
You could use the existing context as parent context for the other contexts, although I doubt that you could replace the existing WebApplicationContext.
If you use EAR - WAR packaging, you get this out-of-the-box (sort of) by loading an application context from the EAR and then adding one in the WAR.
Not sure whether this is applicable in your situation.
Could lazy-initialization be an alternative for what you are trying to achieve?
Possible XmlBeanDefinitionReader can help you?
you can upcat the WebApplicatonContext to ConfigurableWebApplicationContext
then use the setConfigurations method.
dont forget refresh;
There was the same task and I created two contexts: startUpContext.xml and applicationContext.xml. In startUpContext.xml there is a bean, which triggers loading of appliationContext.xml. (application context location is configured in startUpContext.xml as a property of a trigger). And finally the trigger replaces locations of the current context and refreshes it:
applicationContext.setConfigLocations(locations);
applicationContext.refresh();
(startUpContext.xml is loaded with a standard spring context loader listener)