I am a bit familiar with Spring framework but am still having lots of question concerning use of spring from project architectural view point. Now I am setting up Spring 3 and a Maven web application and am willing to try out all the the fancy component-scan's and autowiring features however this is where I get confused.
I am trying to break the project into sub-modules. And at some point these sub-modules may include something-context.xml in classpath*:resource/META-INF, like for instance when I will want to define a datSource related stuff in a separate module. So that's fine spring let's you load context files from within class-paths of all of the jars.
But here is where it gets vague - say I am using component scan. I am obviously using spring DispatcherServlet and it needs a servlet context to be loaded, and then there is a global application context parameter specified in web.xml contextConfigLocation.
So now servlet context config has a component-scan feature enabled for com.mycom.project.controllers and context loaded in the global contextConfigLocation has a context loaded with component scan feature for package com.mycom.project also searches for classpath*:META-INF/spring/*-context.xml.
So my question is - does this load controller's twice given that component scan is used for a for com.mycom.project.controllers and com.mycom.project? Or is it all loaded into one huge container and the contextConfigLocation parameter for either DispatcherServlet or global declaration is sort of access issue ? As in DispatcherServlet will reach only what's defined in servlet-context.xml but won't be able to use anything else?
And if my assumption is wrong, could I have a suggestion on how to manage multi-module project issues?
Thanks.
Yes, you might run into trouble. See this link for how to solve your problem.
#Service are constructed twice
The way you proceed when creating modules seems valid to me. You have a context.xml file for each module and all will get loaded once you load the application. Your modules are self-contained and can also be used in different environments. That's pretty much the way I'd also do it.
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 am not exposed to Spring as yet. I saw the below code in one of the standalone java projects that I have in my system. Can you please help me understand the below code.I am unable to see spring.xml in the project - is it something that must be there and is missing?
appContext = new ClassPathXmlApplicationContext(new String[] {
"classpath*:/META-INF/spring.xml",
"classpath*:myapplication-application-context.xml"
});
The classpath* syntax means that Spring will search the classpath for all resources called /META-INF/spring.xml and myapplication-application-context.xml, and will amalgamate them into the context. This includes looking through JAR files inside the project, so there may not be any visible within your main project files.
The core functionality of Spring revolves around the ApplicationContext which is the "Central interface to provide configuration for an application. " This interface is implemented by the ClassPathXmlApplicationContext which helps you take the context definitins from your classpath .Hence you specify classpath* .
As #skaffman explains , your application get loaded from the context definitions in the above mentioned files . i.e, all the Spring beans are initialized and Dependency Injection is performed as required .
If you deal with web applications , Spring has got a corresponding web application context loaded by XmlWebApplicationContext
I'm developing a Spring application which shall be used by any kind of other application, no matter if that is a Spring project, a web application or even a simple single-class console application. The application who uses my project will just have to add the JAR file with my application.
So my project has a static factory class that gets and returns a bean from its Spring context which acts as an access object to access all public available functions of my project.
That part is already working.
But I need the developer of the application that uses my JAR to be able to overwrite certain configurations in my project without editing the config files in the JAR itself. At the moment those settings should be overwritable:
- the data source and hibernate bean configuration
- the jasypt (encryption) bean configuration
- the log4j settings
How do I make those settings overwriteable with configs from outside the jar?
Greetings
touchdown
Maybe a good solution would be a configuration that the user could override, for this take a look into:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
Specially to #Configuration and #Bean
Maybe you could have a configuration class implemented and the user can override it. After extending the class and overwrite some methods that provides some beans the user shall inform it to your factory that will do nothing else than
new AnnotationConfigApplicationContext(userConfigurationClass);
If you want to replace the complete configuration, than the easyest way would be to have a parametrized factory that takes an alternative configuration file as its argument.
If you need it a bit more fine grain (lets say up to 10 parts), than you can split your application xml in several smaller once, and use again a configurable factory that allows to exchange the smaller xml files.
So I got a solution that is working for me.
I put an general import for override context-XMLs at the bottom of my main application context:
<import resource="classpath*:project/package/config/override/or-*.xml" />
So all the user has to do is to create the package "project/package/config/override" in his classpath (e.g. resource folder) and place matching XML files in it with new bean definitions.
I have just finished building my up from bottom (database) over DAO and business layer. Now I am getting warm with the presentation layer for which I chose Spring MVC.
I have checked out the example delivered with spring-webflow-samples/booking-mvc. I was wondering why all spring configs are located in webapp/WEB-INF/config rather than java/resources. Since I have mine in latter, I wonder if it is required to have them in one particular place.
Thanks & Cheers
ER
The WebApplicationContext loads resources by default relative to WEB-INF. You can always prefix your resources with classpath:/ to force loading from the class resources, or instantiate your own instance of WebApplicationContext, passing in a ResourceLoader that manages loading resources from the classpath by default.
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)