[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.
I have started creating my own project and i have the following modules:

  • myProject-webapp
  • myProjectControllers
  • myProjectServices

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.
Todo this I first need to declare my beans, which means that within myProjectServices i need to declare an applicationcontext.xml where i could declare my beans.

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.
I have added all the application context files in the "ModuleName/src/main/resources/META-INF/spring"

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?
please note im still not using blossom for any of this as i dont believe i need it, but i would like to hear your thoughts on 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...
Lets say i have my rest-servlet.xml which only contains my configuration beans and is stored directly under the resources folder.
Then i have my applicationContext.xml which is also stored under resources folder which gets invoked by myProjectControllersModule class (exactly like in your code snippet example in previous comment)

The structure would look something like this:

-myProjectControllers
---src
------main
---------java
------------myProjectControllersModule.java (extends BlossomModuleSupport)
------resources
---------rest-servlet.xml
---------applicationContext.xml

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.
in this case i can create new modules and as long as i add .xml file in the right location i can be confident it will be picked up without me having to specifically go and specify somewhere that i added new spring file. Any ideas whats the best way of achieving something like this in magnolia ?

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.
I have a line like above

<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!

Generated at Sun Feb 11 23:31:15 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.