3

I have a web-application which is dependent on two other modules.
For simplicity let's call them ServiceA module and ServiceB module.
Each of these modules has various different dependencies and also a common dependency on the Entities module.
Each of the above mentioned modules declares its own spring context file with information pertaining to its scope.
I'm trying now to decide how to "wire" these configuration files between the projects and I'm a bit stumped.

I know one option is just to declare all the "end" files (i.e. ServiceA, ServiceB and Entities) in the web.xml of the web-app (in the contextConfigLocation param) but I don't like that option particularly since my actual use-case is more complex and has more internal dependencies which are shared.

My original intent was to declare in the contextConfigLocation param only the config files for ServiceA and ServiceB since these are the only projects which the web-app is directly dependent upon (this is easy to see by looking at the maven pom), and then have both ServiceA and ServiceB to include this directive in their spring context configuration file <import resource="classpath:EntitiesContext.xml">. The advantage with this approach is that it is consistent with the maven transitive approach where I declare what I'm dependent upon and if that module is dependent upon something it will drag it along with it. The problem with this approach is that I read here that all the beans in the Entities module will be created twice (although only one instance will remain at the end) which is an expensive and unneeded action.

I'd like very much to hear how people solve this use-case since I don't think I've hit any corner case.

Thanks

Update The syntax I ended up using was classpath*:META-INF/*/*Context.xml since there are some issues with the syntax Thomasz suggested.
For additional reading see the bug report of spring (which partially resolved the issue) and a blog post regarding the issue

Community
  • 1
  • 1
Ittai
  • 5,625
  • 14
  • 60
  • 97

2 Answers2

2

What about following some naming convention of config files and simply picking up all that are available on the CLASSPATH?

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

This solution assumes that obviously all required modules are on the CLASSPATH but also that non-required modules aren't there.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Interesting, won't I hit a lot of issues with respect to loading order? – Ittai Dec 05 '11 at 08:41
  • No, as long as you don't have some hidden dependencies and everything is expressed via annotations and/or XML, Spring first merges all the files together and figures out what the correct order is. I think if two beans are independent then the order of their creation might vary depending on the order of JARs on the CLASSPATH. But since they are not dependent on each other, this shouldn't matter. – Tomasz Nurkiewicz Dec 05 '11 at 08:44
  • Excellent, I'll wait a bit more with accepting the answer in case someone has another excellent idea which I haven't thought about but if there won't be I'll accept your answer. Thanks! – Ittai Dec 05 '11 at 08:48
  • I just tried your solution because my current solution backfired (appraently some spring security definitions cannot be repeated) and it didn't work... I think this is related to the fact that many of the *Context.xml files are in jars which reside in WEB-INF/lib folder. Is that true? Is there a solution? thanks – Ittai Dec 05 '11 at 13:46
  • What do you mean that *it didn't work*? Some files are not found? Are you sure all your context files match `*Context.xml` pattern and are located in main CLASSPATH directory? It doesn't matter that some of them are in `WEB-INF/lib` (e.g. `WEB-INF/lib/client.jar`), as long as these JARs are put on CLASSPATH, `someContext.xml` in main directory of `client.jar` will be found. – Tomasz Nurkiewicz Dec 05 '11 at 13:51
  • 1
    Actually you're wrong. It does matter since apparently there are limitations on classloaders (https://jira.springsource.org/browse/SPR-7198). I resolved it with using classpath*:META-INF/*/*Context.xml. In any case your answer was correct and in the end rescued me (since my original method proved to not work). Thanks – Ittai Dec 05 '11 at 13:55
  • @Ittai: sorry, I was pretty sure this would work, thanks! Nevertheless glad I could help. – Tomasz Nurkiewicz Dec 05 '11 at 14:13
1

Have you considered using an annotation based configuration?

That should allow you to reduce the size of your XML config to just a few lines.

Alternatively, using top-level Java based config would allow you to pull in the parts that you want in a controlled way (without having to search the whole classpath) and without any duplicate beans or any XML files.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820