Can I compose a Spring Configuration File from smaller ones? - java

I have a handful of projects that all use one project for the data model. Each of these projects has its own applicationContext.xml file with a bunch of repetitive data stuff within it.
I'd like to have a modelContext.xml file and another for my ui.xml, etc.
Can I do this?

From the Spring Docs (v 2.5.5 Section 3.2.2.1.):
It can often be useful to split up
container definitions into multiple
XML files. One way to then load an
application context which is
configured from all these XML
fragments is to use the application
context constructor which takes
multiple Resource locations. With a
bean factory, a bean definition reader
can be used multiple times to read
definitions from each file in turn.
Generally, the Spring team prefers the
above approach, since it keeps
container configuration files unaware
of the fact that they are being
combined with others. An alternate
approach is to use one or more
occurrences of the element
to load bean definitions from another
file (or files). Let's look at a
sample:
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
In this example, external bean
definitions are being loaded from 3
files, services.xml,
messageSource.xml, and
themeSource.xml. All location paths
are considered relative to the
definition file doing the importing,
so services.xml in this case must be
in the same directory or classpath
location as the file doing the
importing, while messageSource.xml and
themeSource.xml must be in a resources
location below the location of the
importing file. As you can see, a
leading slash is actually ignored, but
given that these are considered
relative paths, it is probably better
form not to use the slash at all. The
contents of the files being imported
must be valid XML bean definition
files according to the Spring Schema
or DTD, including the top level
element.

We do this in our projects at work, using the classpath* resource loader in Spring. For a certain app, all appcontext files containing the application id will be loaded:
classpath*:springconfig/spring-appname-*.xml

Yes, you can do this via the import element.
<import resource="services.xml"/>
Each element's resource attribute is a valid path (e.g. classpath:foo.xml)

Given what Nicholas pointed me to I found this in the docs. It allows me to pick at runtime the bean contexts I'm interested in.
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("modelContext.xml"));
xmlReader.loadBeanDefinitions(new ClassPathResource("uiContext.xml"));
ctx.refresh();

Here's what I've done for one of my projects. In your web.xml file, you can define the Spring bean files you want your application to use:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/modelContext.xml
/WEB-INF/ui.xml
</param-value>
</context-param>
If this isn't defined in your web.xml, it automatically looks for /WEB-INF/applicationContext.xml

Another thing to note is that although you can do this, if you aren't a big fan of XML you can do a lot of stuff in Spring 2.5 with annotations.

Yes, you can using the tag inside the "Master" bean file. But what about the why? Why not listing the files in the contextConfigLocation context param of the wab.xml or als locations array of the bean factory?
I think mutliple files are much easier to handle. You may choose only some of them for a test, simply add rename or remove a part of the application and you may boundle different applications with the same config files (a webapp and a commandline version with some overlapping bean definitions).

Related

Different spring configuration files roles

I am developing my Spring-based web application using Spring Framework + Spring Security + Hibernate for data access (ORM) + Maven as build manager. All data acces operations must be provided by Hibernate.
My goal is to integrate Spring Security, Spring Framework and Hibernate for work together. I read many corresponding tutorials but what is confusing to me is that there are (in tutorials code) many xml-configuration files that missing in my project. Here is the structure of my project
As you can see there are only two Spring related xml-files and web.xml - they all been automaticaly generated by Spring when I added Spring Framework and Spring Security support to my project.
But in mentioned tutorials there are also files named "spring-database.xml", "spring-security.xml". The first as I think is to configure Spring toget data from database and the second is just basic Spring Security config. file.
Questions:
1) Those two files have not been generated automaticaly, even "spring-security.xml". Is it ok - is it like it must be? Or something wrong with my project settings?
2) If I can name those xml config files as I wish - then how does Spring know about them all and distinguish them? I just have not found anything about config files with such names in official Spring refference docs.
Answering question 2 please give some examples if it is possible.
3) My applicationContext file is empty - is it ok? And what if difference between it and dispatcher-servlet?
Thank you in advance!
1) I general you need just one spring configuration file, which is normally placed in src/main/resources (or elsewhere on the classpath) and after called applicationContext.xml or similar. If you use several Spring modules (such as Spring Data, Spring Security etc) it is common practice to have one separate config file for each module, but its not necessary, you can place all config in the same xml.
2) The naming doesn't matter, Spring looks in the classpath for the files: https://softwareengineering.stackexchange.com/questions/145545/where-to-put-spring-configuration-file
3) Normally the applicationContext.xml contains the definition of your beans and packages to scan for annotation and should be placed in src/main/resources. I guess dispatcher-servlet.xml is for the URI/servlet mapping (spring mvc)
There is no problem with your project structure. It is not mandatory to have the file names as you have in your project. If you want to have your own names for the xml files you have to mention the names of the xmls in the in web.xml. See below
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
Coming to the third question. applicationContext.xml should not be empty. You need to specify the beans of your application (services, dao, etc..) in applicationContext.xml. In dispatcher-servlet.xml you need specify beans (handler mappings, controllers, view resolvers etc..) related to spring mvc.

Where exactly should I put ehcache.xml in my project?

I've recently began using EHCache for caching purposes. I know, how to use it in Java code, but I'm still not sure about the configuration file.
So, I have an ear project, that includes several war modules. If all these modules use ehcache, should I put a copy of ehcache.xml in WEB-INF for each module, or put it somewhere in ear file itself (META-INF maybe?)
Also, it's not clear from the documentation, whether or not all these modules will use the same cache instance? The application is deployed at glassfish, will EHCache run the same cache for each module in ear, or each module will get his own singleton instance when used like this:
CacheManager singleton = CacheManager.create();
According to ehcache.xml file. There is no rule where you will put this file, but if you are working on a big project I presume that you have several profiles (e.g. for QA, DEV, PROD). As ehcache may differ depending on profile (for example, if you have ehcache jms replication enabled) you can have different JMS Server IPs set up there or amount of objects in cache regions may differ, so I suggest to put in where you have profile-dependent file (e.g. web.xml, log4j.properties). Then if you have context configuration in a separate xml file like:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/context-config.xml</param-value>
</context-param>
then you may add in that context-config.xml file:
<import resource="context-config.xml"/>
That context-config.xml file may contain description of cacheManager bean, that you will be able to Autowire where do you need it. So the context-config.xml may look like:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
</beans>
Answering your second question. From my example, it will depend on how you will define this bean, you can define it as a singleton and then you will have only one instance of cacheManager or you can leave the instantiation to Spring.
In my opinion, you can autowire cacheManager to the class with general logic for cache invalidation or cache "creation" and that will make a lot of sense. Hope that I helped you.
There is no hard and fast rule for putting in your ehcache configuration file.
But, personally I keep my ehcache config file with all the other configuration
and properties file.
For example, I will store the path to my ehcache config xml file in some static final variable, (helps in keeping the path configurable )
private static final String EHCACHE_CONFIG = "<path to this file>/ehcache.xml";
And then when I initialize the cache manager, I give in the path to config
file as a parameter
CacheManager manager = new CacheManager(EHCACHE_CONFIG);

off-the-shelf web application working directory

I've just started working with Spring/java web. I'm wondering how to accomplish following scenario:
Let's say that I'm creating an application which supports file upload, uses a database connection and maybe a web service. This is an off-the-shelf system, so all the settings are customer specific and should be configured by customer's IT people on the deployment time.
More general in the web.xml file I would like to point the application working directory containing uploaded files, license key file, configuration files, other customer specific resources and maybe even fragments of spring context.
<context-param>
<param-name>workdir</param-name>
<param-value>/var/r2/</param-value>
</context-param>
In my application I would like use the workdir value in order to include configuration files ...
<import resource="wordir_param_value/settings.properties" />
context config fragments
<import resource="wordir_param_value/security.xml"/>
And how may I later use these values in the java code? What is "the best" approach in case like this anyway (off-the-shelf application config)?
Best Regards,
Alek
You can use Spring's property support for that. This allowed two different approaches:
Having a property file outside the application (at a fixed location), the admin can edit it, and the application loads it
In a Tomcat you can write properties in the application specific context.XML file
In the code use #value annotation to inject the properties in a variable.
In the spring XML file you use it with ${name}
Of course you need to configure the proprtyPlaceholderConfigurer

How to extend Spring container to be deployment specific?

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?

Spring 3.0 not finding the applicationcontext.xml

I'm working on web application that uses a database storage system and I chose to keep the dataAccess-applicationcontext seperate from the rest. However when I run the following line of code it says it does not exist.
ApplicationContext ac = new ClassPathXmlApplicationContext("dataAccess-applicationContext.xml", UsageDataDAO.class);
I have even moved the xml file to the same directory only to get the same error as posted below.
nested exception is java.io.FileNotFoundException: class path resource [com/foobar/bar/foo/dataAccess-applicationContext.xml] cannot be opened because it does not exist
Any Idea what is going on here?
This is hard to debug without all of the details, but it has to be one of two issues.
First, the file really isn't in your classpath. This is a web application, so you should consider how your particular servlet container works when you're checking the classpath. For example, in a servlet environment, WEB-INF is not in the classpath, but WEB-INF/classes is.
Second, the file is in your classpath, but you're referring to it incorrectly. Based on the information that you provided already, I don't think this is the case, but this possibility can be expanded on later.
Regardless, why are you trying to load a file manually? You should reference the configs in your web.xml. If you provide more details about how you're running your web application, then we can help you with this part. In the meantime, this example might be enough information. It illustrates how to configure the root spring container that's shared by all of the Servlets and Filters in the container (configuring a specific Servlet requires a slightly different approach):
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config1.xml, /WEB-INF/config2.xml</param-value>
</context-param>
please edit your file name with underscore dataAccess_applicationContext.xml instead dataAccess-applicationContext.xml. And try again.
Try with the classpath*: prefix . "classpath*:dataAccess-application-context.xml" if it is in the root classpath else use "classpath*:/folderName/dataAccess-application-context.xml"
Your 2nd parameter to:
ApplicationContext ac =
new ClassPathXmlApplicationContext("dataAccess-applicationContext.xml",
UsageDataDAO.class);
Includes UsageDataDAO.class. According to the spring javadoc for this class, this is requesting the context search start in com/foobar/bar/foo/.
Instead put dataAccess-applicationContext.xml in WEB-INF/classes and try:
ApplicationContext ac =
new ClassPathXmlApplicationContext("dataAccess-applicationContext.xml");
UsageDataDAO myDao = (UsageDataDAO) ac.getBean("MyDaoBeanName");

Categories