[BLOSSOM-212] Spring application context in Magnolia Created: 03/Jun/15 Updated: 03/Jul/15 Resolved: 03/Jul/15 |
|
| Status: | Closed |
| Project: | Blossom |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Task | Priority: | Neutral |
| Reporter: | Gediminas Zalys | Assignee: | Tobias Mattsson |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Template: |
|
| Acceptance criteria: |
Empty
|
| Task DoR: |
Empty
|
| Date of First Response: |
| Description |
|
I have been struggling to get a grasp of the best practises when it comes to spring and magnolia.
myProjectControllers module holds controllers that are accessible externally, i.e used for ajax. to achieve that i followed Additional DispatcherServlets and AJAX calls example. Now what i want is that within my controllers i could @Autowired some beans that are in my myProjectServices module. So my question is where and how do i declare this applicationcontext.xml so that the beans within it can be accessible by myProjectControllers module ? P.S note i have not yet installed Blossom only added dependency to spring in all my modules, as i did not think i needed blossom yet. |
| Comments |
| Comment by Gediminas Zalys [ 04/Jun/15 ] |
|
So i think i found a neat solution, i would like to share it with you to see how supported it is. So I followed this design: As i mentioned earlier my myProjectControllers are used to serve ajax calls and this module has its own rest-serlvet.xml, created by following Additional DispatcherServlets and AJAX calls example. so within my rest-serlvet.xml I import all the context files from all the module that myProjectControllers is dependent on. so my rest-serlvet.xml looks something like this: <import resource="classpath*:/META-INF/spring/*.xml" /> Please advise whether this is a correct practise or is there a better way of doing this? |
| Comment by Tobias Mattsson [ 05/Jun/15 ] |
|
For what you want to achieve your solution is perfectly fine. You now have a single DispatcherServlet containing beans from both applicationContext.xml and rest-servlet.xml. Traditionally in Spring applications you have one or more DispatcherServlets, each with its own -servlet.xml file, as children to a root ApplicationContext containing beans from applicationContext.xml. If you want to add more DispatcherServlets you'll need to set it up that way so they can share the service bean instances in the root. To achieve this you need to start the root ApplicationContext in one of your modules. Afterwards when the DispatcherServlets start up they will find it and make themselves children of it. You can install the Blossom module even if you don't intend to use it for templating. It has many utility classes that might be useful. For instance it has a class called BlossomModuleSupport that you can use to start the root WebApplicationContext. public class MyModule extends BlossomModuleSupport implements ModuleLifecycle { public void start(ModuleLifecycleContext moduleLifecycleContext) { if (moduleLifecycleContext.getPhase() == ModuleLifecycleContext.PHASE_SYSTEM_STARTUP) { super.initRootWebApplicationContext("classpath:/applicationContext.xml"); } } |
| Comment by Gediminas Zalys [ 23/Jun/15 ] |
|
I am a little confused how this should be setup properly now... The structure would look something like this: -myProjectControllers The above works perfectly fine for myProjectControllers module, but now my question is how the beans from myProjectServices will be picked up by the myProjectControllers? I have tried adding below to applicationContext.xml located in myProjectControllers
<import resource="classpath:/META-INF/spring/myProjectServices-spring.xml
myProjectServices-spring.xml is located in myProjectServices module. unfortunately for some reason this did not work and the beans located in myProjectServices-spring.xml were invisible to my Controllers module. What is the right way of declaring beans in another modules and making sure that they can be used by other modules? Ideally i would like to declare spring files under each module in designated location, then one of the modules would scan each module and pick up all the spring files. |
| Comment by Tobias Mattsson [ 26/Jun/15 ] |
|
Is the rest servlet finding other beans defined directly in applicationContext.xml ? The import you mentioned earlier should do the trick:
<import resource="classpath*:/META-INF/spring/*.xml" />
|
| Comment by Gediminas Zalys [ 26/Jun/15 ] |
|
Thanks Tobias, The servlet finds other beans in applicationContext.xml, if the beans in applicationContext.xml are from the same module. <import resource="classpath*:/META-INF/spring/*.xml" /> Which should import my other spring files from other modules, however beans in those other files are not visible to the beans that have been declared in the same module as applicationContext.xml applicationContext.xml : <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <alias alias="beanA" name="defaultBeanA"/> <bean name="defaultBeanA" class="com.xyz.frontend.facades.impl.DefaultBeanA" autowire="byName" /> <import resource="classpath*:/META-INF/spring/*-spring.xml" /> </beans> |
| Comment by Tobias Mattsson [ 26/Jun/15 ] |
|
Have you tried without the slash before META-INF ? The class loader is picky about that and I'm not sure if Spring strips it off. I.e:
<import resource="classpath*:META-INF/spring/*-spring.xml" />
|
| Comment by Gediminas Zalys [ 26/Jun/15 ] |
|
Unfortunately that didn't work, i have tried a number of things, such as providing full file paths by referencing files individually. When spring application context loads if its unable to find the file it would just blow up on startup which it doesnt. So i dont believe the referencing is the problem. I have even tried just simply declearing the beans of another module within the applicationContext.xml which was no success, it feels to me that the applicationContext.xml is only aware of the module that is in, when it is invoked by Blossom. what i am trying todo here is something that i am used to, but how do you guys use spring in magnolia ? where normally do the spring files go? what would be a standard module structure and how spring context is shared across each module? i am happy just to follow the practice that is used by magnolia team! |
| Comment by Tobias Mattsson [ 26/Jun/15 ] |
|
You're doing it exactly as I would recommend, in fact the blossom sample app does the same thing. It has this in its applicationContext.xml:
<import resource="classpath:/info/magnolia/blossom/sample/webflow/webflow-config.xml" />
In this case it keeps the file in a package but that doesn't matter, META-INF is fine too. If it doesn't blow up on startup that would indicate that it does find the files on classpath. Are the imported beans instantiated too? Your servlet should be a child of the root application context, if you inject ApplicationContext into one of your controllers and put in a breakpoint you can inspect it too see that it has a parent and that it is the same as the one you created in the module class. |
| Comment by Gediminas Zalys [ 26/Jun/15 ] |
|
Thanks Tobias, I will investigate further in why other spring files are not getting picked up, the key question for this jira issue was regarding the best practise for the use of spring in magnolia, which you have answered! the rest is my headache now Many thanks for your support! |