The Spring classpath:-notation

As most of you probably know, the Spring Framework can load all sorts of resources into its application context from all sorts of sources. Especially it can do this from the classpath and the people over at SpringSource have even introduced their own URI “protocol” to make this easy: you can identify resources using the classpath-URIs, like so:

classpath:<relative path to resource here>

Most of you are probably familiar with this notation, because it is often used when loading the application context files themselves using the ContextLoaderListener.

What many people don’t realize, is that the classpath:-notation is far more versatile than just for use as a standard URI, because you can use wildcards. In fact I only recently learned this myself from a colleague (at least in part) — which is kind of dumb, because it’s mentioned quite clearly in the documentation.

The first thing you can do above and beyond loading resources by their full path (relative to the classpath) is use all the Ant-style wildcards. So instead of loading as follows:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:businessContext.xml
classpath:persistenceContext.xml
classpath:webFlowBeansContext.xml
classpath:etc.
</param-value>
</context-param>

you can simply load as follows:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:*Context.xml
</param-value>
</context-param>

or, as the case may be:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:**/*Context.xml
</param-value>
</context-param>

There is a catch to this strategy, however: if you have multiple resource repositories (directories, databases, online resources, whatever) on your classpath containing files that match your wildcard pattern, Spring will only look for matching resources in one of these locations. To illustrate this for yourself, try using maven to create a standard project structure, then put a context file in src/main/resources and src/test/resources and try to load both at the same time with a wildcard — you’ll only get one.

The classpath*:-notation

Of course the Spring guys wouldn’t be the Spring guys if they didn’t have a simple solution for this problem. It’s called the classpath*:-notation. Simply put, if you rewrite the snippet from above like so:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:**/*Context.xml
</param-value>
</context-param>

then Spring will load every matching context file from the entire classpath.

As the documentation points out, the combination of the classpath*:-notation with Ant-style wildcards makes it possible to organize your application into a neat component-assembly style: you can put all the code for each individual problem from your problem domain into its own component (a jar, say) and then “slot” as many jars into place as you like to make your application. You can even add components later on without making major adjustments to any other component (if you think about it carefully). Just make sure each component has an application context file that follows the general naming schema. Think of the possibilities if you include OSGi or even the new Service Provider spec.

Caveat emptor

There is a very specific sort of naming pattern that you can also create using the classpath*:-notation. This is the naming pattern whereby all application context files within the application have exactly the same name (e.g. classpath*:myAppContext.xml). This pattern allows you to expand your context completely transparently to all others without even having to think very hard about the naming convention.

DO NOT EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER, EVER DO THIS!!!

If you give all your context files the same name, you lose precise control over what gets loaded and what doesn’t. This can hurt if you create components that you want to reuse across applications (especially if you are using Maven and have transitive dependenciesto deal with) and it can hurt in creating integration tests that involve partially loaded contexts. It also makes it harder to find naming conflicts in your contexts if you introduce them accidentally (especially if you are not the only developer on your project). Always make sure each context file on the classpath has a unique name!

Conclusion

The Spring Framework includes a very flexible notation for loading resources from the classpath, using wildcards to identify resources. This notation, if used correctly, gives you considerable freedom in creating component-assembly style applications. However, you must still guard against using unwise naming of your context files.

Spring application context loading tricks
Tagged on:     

26 thoughts on “Spring application context loading tricks

  • Pingback:Spring Security – The big stuff « William Rey

  • February 8, 2012 at 4:18 am
    Permalink

    Hi, I’m making a project for college in wich I have to use a aspect to put more functions in a web application the is already deployed in the server. And I would gratefully thanks if someone can tell if, after a .war is deployed I could use an aspect (probabilly AspectJ) to add more sources to an already loaded spring context. You see I have a application the is running so I want to add f.e. a new module to it using an aspect, so I want to simply deploy the already running server and add more stuff to a specific .war without replacing the .war and just simply using my aspect to add the new library the application need and change on the fly the spring context of this application. Is that possible?

    • February 8, 2012 at 10:24 pm
      Permalink

      Yes… Sort of… But it’s tricky. And just to make it that little bit worse (since this is a college assignment), I’m not going to give you anything more than a few hints. 😛

      * What you want to do, can be done with and without an aspect (the aspect is only a place from which to hook the non-application code into your application).
      * You want to use code that is not on the classpath of your application at start time. Take a look at class loaders. There’s one in the standard class library in particular that will help you here. Also Google a bit for having classes from two classloaders interact.
      * You want to change the runtime definition of the application context. Tricky. If you want to be mean about it and literally change the context, check out Java reflection. Cleaner solution: check out the proxy design pattern.

      • February 9, 2012 at 4:43 pm
        Permalink

        Hi Ben, thanks for the fast reply. So asked around, this is actucally my graduation project, I wanted to show that aspect has other and better uses than just loggin. But for example is possible to have several .war share their classpath through an .ear (several .war in the same .ear)? For example, each .war have their own Spring context, and one of then is the mai module, so the others would use an aspect just to add a new menu during the construct of the servelt responde, and this menus point to another .war and there when this .war has the need to use the Spring context of the other use an advice aspect though a proxy to actually use the other Spring context? I’m new with this thing of aspect and not very smart with Spring, I use then only for the basics. This that I want to do I’ve actually done with a Swing app, but when it comes to a Web context, I’m tottaly noob.

        • February 9, 2012 at 11:55 pm
          Permalink

          Is it POSSIBLE? Yes, sure, you can hack anything I suppose. The question is: is it worthwhile?

          From your description it sounds to me like you’re trying to build some sort of plugin framework in which you want to allow different applications direct access to one another’s internals. Yes, I suppose you can do something to allow different WARs within an EAR to interact that way — but why do so?

          For starters, if you want to write a pluggable application, the simplest strategy is one that doesn’t fight the class loading rules of the JEE platform. That means doing something with plugin JARs and a single web app, not trying to hack multiple webapps into one.

          Second, if you’re trying to demonstrate the use of AOP beyond the obvious, I sort of fear that you’re going in the wrong direction. AOP is all about centralizing distributed aspects of an application into a single location and lending more structure to your design; AOP is not a tool meant to mix multiple applications into one large, new one (that’s exactly the kind of spaghetti code that AOP and OOP want to avoid).

          Third, AOP is about centralizing aspects and binding them together without creating static dependencies between them. A plugin framework is more or less the opposite of that: a main application expands its own functionalities by delegating requests for new functions to pluggable code, at the expense of having to manage the lifecycle of its pluggable modules. Sure, you CAN implement a plugin framework using AOP techniques, but it’s the hard way to do it (and not the best showcase for either concept).

          • February 10, 2012 at 2:21 pm
            Permalink

            Bean, thank you very much for your explanation, I have googled (A LOT) e realized that this easn’t the best aproach to do that, my only intention is to show how to modularize web apps, without the need to send all the source code of the app to the client, I’m currently using the company that I work software to try and demonstrate that and I thought the AspectJ could resolve that, but is to complicated and not worthwhile, I have search and found out that Spring Dynamic Modules could do that without much effort, so I’ll try to focus on that. But thanks very very very much for your help. It enlighted me a lot. know anywhere good to look for about modularization?

  • January 23, 2012 at 7:38 am
    Permalink

    In my web.xml we have mentioned contextConfigLocation twice like below in this order. Could you pls tell which one will be picked up as contextConfigLocation file

    contextConfigLocation
    /WEB-INF/config/web-application-config.xml

    dispatcher-servlet
    org.springframework.web.servlet.DispatcherServlet

    contextConfigLocation
    /WEB-INF/config/dispatcher-servlet-config.xml

    1

    • January 23, 2012 at 9:20 pm
      Permalink

      It’s a little difficult to see exactly what’s going on here, since your XML tags didn’t make it into the posted comment. But the way it looks to me right now, only the dispatcher-servlet-config.xml will be loaded since it is passed to the dispatcher servlet as a servlet init param (and all the beans will be loaded into the namespace of the servlet).

      The web-application-config.xml will NOT be loaded, since you have not defined a ContextLoaderListener. If you DO include such a listener, then both context files will be loaded. The beans from web-application-config.xml will be available to the dispatcher-servlet and any other servlet you load; the beans from the dispatcher-servlet-config.xml will only be available to the dispatcher-servlet.

  • December 3, 2011 at 8:02 pm
    Permalink

    Hi Ben,
    I have a issue with loading spring-aplication-context.xml.
    it is clealry mentioned in web.xml also as:
    classpath:spring/spring-aplication-context.xml
    where spring is a folder inside which spring-aplication-context.xml resides.
    The application is not getting loaded and says filenotfound for spring-aplication-context.xml.
    The project is a maven project.
    What can be the possible error?

    • December 5, 2011 at 7:31 pm
      Permalink

      Hi BenBourne,

      Sounds to me like that “spring” directory is not on your classpath.

  • September 20, 2011 at 11:40 am
    Permalink

    classpath refers to current directory in spring framework.

    • September 23, 2011 at 10:46 am
      Permalink

      Err, no, it doesn’t. The classpath: prefix refers to the application’s classpath and means that resources will be retrieved from locations on that classpath (although at a given point in time that might indeed include the current working directory). An absolute location without a classpath: prefix is an absolute location and a relative location is relative to the working directory of the application.

  • September 20, 2011 at 11:38 am
    Permalink

    ApplicationContext ctx =new ClassPathXmlApplicationContext(“../applicationContext.xml”);
    BeanFactory beanFactory=ctx;
    It works fine in my spring project

    the above code is in /WEB-INF/jsp/index.jsp
    but my applicationContext.xml is in /WEB-INF folder

  • April 27, 2011 at 8:38 pm
    Permalink

    Nice read! Thanks for taking the time out to compose this.

  • January 31, 2011 at 3:22 pm
    Permalink

    @Manish:

    one of the common errors with maven deployment is to keep the context xmls in resources instead of webapp/WEB-INF – make sure you’re not doing the same.

    Tapasvi

    • January 31, 2011 at 3:24 pm
      Permalink

      Sorry, I do not see this as a mistake. Maybe you can explain why that is a mistake?

      • January 31, 2011 at 10:04 pm
        Permalink

        Hey Jettro,

        It is a “mistake” in the sense that, in and of itself, /WEB-INF is not on the classpath. So if you put your context files there and then try to load them by doing something like “classpath:*context.xml” rather than “classpath:/WEB-INF/*context.xml”, then it won’t work. And this is an easy mistake to make, since the DispatcherServlet implicitly initiates the processing of a /WEB-INF/-servlet.xml file, sort of suggesting that /WEB-INF is where you should put the context files.

        Also, one might consider it a “mistake” against the style that SpringSource introduced with Spring Roo of always placing context files in the META-INF/spring directory (which, to be honest, is where you *should* put context files that are in a JAR).

        Finally, it is definitely a mistake if you put the files in a /webapps/WEB-INF directory when your maven project does not have a “war” packaging. But, uhhhh…… 😉

        • February 14, 2011 at 11:05 am
          Permalink

          Hmm, I see I mist the whole thread of comments. Did not notice it was a response to another comment. My bad 🙂

  • May 25, 2010 at 10:21 am
    Permalink

    related to SOM’s Question, I am trying to use 2 XML files in application context – one is in the same project and 2nd in another project. This 2nd project has been added to my current project and the context in web.xml is

    contextConfigLocation

    /WEB-INF/eu24ui-servlet.xml
    classpath:spring-ds.xml
    classpath:spring-hibernate-iocm.xml

    But when I try to start the jboss server.. it throws fileNotFoundException.
    Need help.

    • May 26, 2010 at 2:36 pm
      Permalink

      Manish,

      In my experience the JVM doesn’t lie to you when reporting errors. If it’s throwing a FileNotFoundException, the file simply isn’t being found.

      I’d start by checking out options to print the classpath on server and application start (there’s sure to be a diagnostic option for this), then take a good look at your package. From your description I’m willing to bet your second project package isn’t on the classpath of the first.

  • August 13, 2009 at 10:12 am
    Permalink

    Hi Ben,

    Very nice article. I was looking for the answer described in “Do not ever do this” where I have multiple modules with same application context name. I will use module specific names.

  • December 31, 2008 at 6:57 am
    Permalink

    What if I want to load two application context files with dependencies like applicationContextTwo uses beans in applicationContextOne and both are in different classpaths.

    • December 31, 2008 at 2:32 pm
      Permalink

      Som,

      If you want to load files from two different locations using wildcards, the classpath*:-notation is the way to go.

      As for your cross-contextfile dependencies, those will always work; that’s a function of the Spring container. The thing to understand is that you do not get a context PER FILE — no matter how many context FILES you have, the Spring container always loads them all together and makes one single CONTEXT out of them before initializing your beans. The only way to have multiple contexts in a program is to have the program start two separate instances of the Spring container.

  • May 26, 2008 at 3:49 pm
    Permalink

    Hehe Ben like always a great read 🙂 Thanks!

  • May 18, 2008 at 3:59 am
    Permalink

    I agree with Uri. Note that my post was intended as an overview and not so much as a recommendation.

  • May 14, 2008 at 8:04 am
    Permalink

    An advantage of explicitly defining the actual application context names (without wildcards) is that it provides you with yet another view of your layered architecture. I personally like to have an application context per layer (e.g. service-layer.xml, data-access-layer.xml, etc…) and each one of these application context is composed out of more functional ones. so all thing related to messaging I would put in messaging.xml and import it in the service-layer.xml context.

    cheers,
    Uri

Comments are closed.