What is the best way to load spring config xmls? - spring

I have to load 3 spring config xml files in myproj spring mvc app named myproj-controllers.xml, myproj-services.xml and myproj-dao.xml. I have two options to load them.
Firstly Use import resources in myproj-servlet.xml
<import resource="myproj-controllers.xml"/>
<import resource="myproj-services.xml"/>
<import resource="myproj-dao.xml"/>
or secondly in the web.xml using context param like this
<context-param>
<param-name>contextConfigLocation</param-name>
<param-values>/WEB-INF/myproj-controllers.xml</param-values>
<param-values>/WEB-INF/myproj-services.xml</param-values>
<param-values>/WEB-INF/myproj-dao.xml</param-values>
</context-param>
and adding ContextLoader listener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Which approach is recommend? And why? In my opinion I find import approach easier as we only need to make changes to myproj-servlet.xml instead of web.xml.

Spring lets you declare multiple contexts in a parent-child relation so I always went for one root applicationContext.xml containing my application beans (services, DAOs etc) and one action-servlet.xml for servlet contexts (request mappings, view resolvers etc).
I once needed action-servlet-2.xml file but still had just one root applicationContext.xml for both servlet contexts.
So (for me) it was always parent context + child context.
The only need for splitting the files into more pieces was just to reduce the size of the XMLs (which is what <import> does best).
For me, the contextConfigLocation param refers to application context files being loaded together into a single application context instance. But your files (myproj-controllers.xml, myproj-services.xml, myproj-dao.xml) seem like parts of one application context file.
For this reason I would personally go for the <import> statements and have just one value (for the root application context) in the contextConfigLocation param.

I prefer the context loader listener approach, but perhaps that's because I've never considered the import method. I'll try it out. Thanks.
I don't see any performance advantages. The WAR file has to be redeployed in either case. It's modifying one file as opposed to another. I don't see any difference. It has a bike shed feel to me, but I could be wrong.

Related

How to configure logback context-param using jHipster?

Fact 1: in this answer it is mentioned that the web.xml file has been replaced by the (generated) WebConfigurer class.
Fact 2: in the logback documentation it is explained that, in order to avoid the logback facility shutting down before the application shutdown is completed, which would cause loss of logging messages, the web.xml file should be edited by adding the following stanza:
<web-app>
<context-param>
<param-name>logbackDisableServletContainerInitializer</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
Putting it all together, how can I set this configuration parameter while using jHipster?
Bonus question(s): how are the contents of the web.xml file mapped to the WebConfigurer class's contents? Can the WebConfigurer be customized during the generation phase, or should it be edited manually after generation?
As reported in the answer to this question, the web.xml file can be found (and edited) in the "src/main/webapp/WEB-INF" folder, although it is discouraged to use it. However, there does not seem to be another way to operate in this case.

Parametric file inclusion in struts.xml configurations, based on properties

I have a web application (built on Spring, Struts 2) and I am trying to dynamically include a struts configuration file inside the main struts.xml configuration, based on a property.
Having defined, in the property file:
key=foo
I try to use it inside struts.xml:
<struts>
...
<include file="/config/struts/struts-${key}.xml" />
</struts>
To include the "struts-foo.xml" file (or another file, depending on the value).
The property file is loaded at startup by Spring, and I am able to use it inside Spring's xml files to parametrize bean definition.
You could leverage the Struts2 plugin framework.
You basically create a jar based project where you include all of a particular client's action mappings, support classes, etc. If you're also deploying into a Servlet 3.0 or higher container, you can also elect to include the UI artifacts inside the jar's META-INF\resources directory too for clean packaging.
Now, the contents you typically place inside the struts.xml for action mappings, you simply place inside struts-plugin.xml and place this xml file in the root of the jar file.
When the Struts2 framework starts, the jar files will be scanned, the struts-plugin.xml files will be picked up and automatically included in your application.
I use the same setup in conjunction with my maven build process so that if a client's deployment isn't suppose to include a specific feature or if a standard feature is to be customized, I can customize the action mappings from the stock ones.
In our case, the stock app is a struts-plugin based jar that gets loaded before any other jars and then subsequent feature jars are loaded to extend or override functionality. The actual WAR project has little inside it and is mainly an artifact used to deploy combinations of other project artifacts.
As you know you can change the struts.xml config file name, as below:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>config</param-name>
<param-value>struts-config.xml</param-value>
</init-param>
</filter>
You can use this feature to change struts.xml dynamicly.
You need to extend the StrutsPrepareAndExecuteFilter and load your dynamic config here. Replace your new fildter with struts in web.xml.
public class MyStrutsPrepareAndExecuteFilter extends StrutsPrepareAndExecuteFilter{
#Override
protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
//load your config here
}
}
Please have a look at StrutsPrepareAndExecuteFilter source code. you can see how the config is loaded and you can how you can change it.
If you want to only dynamical change your application messages you can do it more easily by just calling LocalizedTextUtil.addDefaultResourceBundle ("messages/customize") in MyStrutsPrepareAndExecuteFilter

Jetty spring profile programmatically

I'm looking for a way to set spring profile in jetty programmatically so that the application that the war file on the server used the given profile, this is my code:
final WebAppContext context = new WebAppContext();
context.setLogUrlOnStart(true);
context.setWar("target/deployables/myapp-rest/myapp-rest.war");
context.setContextPath("/" + TEST_APP_CONTEXT);
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
I tried a couple of things but none of them seem to work... I need to pass -Dspring.profiles.active=myProfile
This is tested with Jetty 9.3 but webdefault.xml seem to also be available for lower versions (it's placement might be different though).
Go to $JETTY_HOME/etc and open webdefault.xml. Search for context-param in the file. Add this code somewhere below:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>prod</param-value>
</context-param>
This will work if your web.xml (in the your-app.war file) doesn't contain this context-param.
Otherwise you could also use override-web.xml (docs) but you would need to configure it in jetty-web.xml and jetty-web.xml must be bundled inside the war... So YMMV, but I didn't want to change my war and webdefault.xml is an easier solution for me.

Cannot load /WEB-INF/applicationContext.xml

Saw same issues in others queries, but did not find the answer, hence posting it afresh.
Created a sample Helloworld service in Rest and deployed it in Tomcat-Jersey. Not using Maven.
Injecting a spring bean define in applicationContext.xml which is present in WEB-INF directory.
Deployed the service in Tomcat within Eclipse.
But when I execute the rest service, cannot find file applicationContext.xml.
Once I copy the file to WEB-INF/classes only, it works.
What is the way to make it work by keeping it only in WEB-INF?
web.xml :
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
Rest service code snippet :
ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
It seems reasonable to work when you drop the context descriptor under /WEB-INF/classes because this location is the root of classpath.
So try loading with below uri (without prefix) if you want to drop your applicationContext.xml under WEB-INF folder:
ctx = new ClassPathXmlApplicationContext("/WEB-INF/applicationContext.xml");
Otherwise, can you explain why are you trying to load your applicationContext.xml within your web application?
Alternatively, you can load your application context programatically as follows:
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
BR.
If you are using Intellj IDEA and having problem with ApplicationContext.xml path;
Go to File and click Project Structure. Under the Project Settings, click Facets, at the Web Section you will see Web Resource Directories. You should define Web Resource Directory to your /WEB-INF folder. If your /WEB-INF folder is in the subpath like below;
/web/WEB-INF/...
Then choose /web directory to cover all your files.

Component Scan not finding #Component's in a JAR in Tomcat webapp

I just filed a bug in the Spring bugsystem ( https://jira.springsource.org/browse/SPR-8551 ), but I am still unsure if I am missing something
I tracked down a problem with <context:component-scan/> to this statement.
Given the two following classes which are in the same JAR in WEB-INF/lib of a web application (The JAR file has the directory structure):
test/TheBean.java:
package test;
#Component
public class TheBean{
}
test/BeanSearcher.java:
package test;
public class BeanSearcher{
public void init(){
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("test");
ctx.refresh();
TheBean b= ctx.getBean(TheBean.class);
// What is the value of b?
}
}
If I run new BeanSearcher().init() in a jUnit test case or other type of standalone application, b is getting assigned an instance of TheBean, but if I run it, say, in a JSP, ctx.getBean() is returning null.
So, am I doing something wrong or not taking something into account, is this just a bug...?
EDIT 8/8/2011: It seems to work good as I tried to simplify the problem, but still, when I try to make it work, in the initialization of OpenCms, it fails. Now I am trying to look for the differences between working versions and the one which doesn't work. (Classloader, ubication of the relevant classes in different JARs or directly in WEB-INF/classes, calls via reflection, etc.)
As I wrote in the comment, the solution is given by the answer here:
Spring Annotation-based controllers not working if it is inside jar file
When you export the jar file using the export utility in eclipse there
is a option called Add directory entries.
The obvious question is whether you have things like these in your web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/foo.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Without these, Spring won't actually load at all, let alone properly build beans…

Resources