Autowiring beans from a different module - java

I have a big application which i want to break up into manageable modules. I am using spring with Jpa (Hibernate as a provider). I came up with a structure where I have a core module containing all the entity and dao classes, and the other modules make use of the core module regarding persistence, and each one of them will have its own set of service classes and controllers.
All Jpa and spring configuration files are in the core module. With this setup I am facing a problem of autowiring dao beans in the modules making use of the core module. So my question is, is it possible to autowire beans from the core module in the other modules (or probably use a context across modules)? I am also open to suggestions regarding the structure, if there is a better way of doing it.
Thanks

The Core Module must be the parent Spring context that must be setted in each child context module. By this way there's no ploblem with autowiring
Every child context can reach all beans from parent, but be aware of that parent can't see the children
Depending on how you've configured your application, you can do this in several ways, i. e.
Distributing your core module in a separate jar to every module, as it's described in this article Sharing a spring context across multiple Webapps
Programatically, having your core spring xml in each child module, you can do this:
ClassPathXmlApplicationContext parentAppContext = new ClassPathXmlApplicationContext();
parentAppContext.setConfigLocation("spring-core.xml"); // this is your core spring xml
parentAppContext.refresh();
ClassPathXmlApplicationContext moduleAppContext = new ClassPathXmlApplicationContext();
moduleAppContext.setConfigLocation("others.xml");
moduleAppContext.setParent(parentAppContext);
moduleAppContext.refresh();

Related

Multi module Spring Boot project with different context paths

As the title says, I'm trying to create a multi module Spring Boot project that has different context paths for each module.
Let's say I have a bunch of core functionality in one module, and let's call it 'core'. This includes defining entities, DAOs and common functionality. I'd like to add two more modules, (for instance 'frontend' and 'admin'), and I'd like that those two modules could run independently from each other (both depending on 'core'). But I'd also like to have the possibility to run them together, and access frontend when the path is '/' and admin when the path is '/admin', which is the part I'm struggling to achieve.
What I've done so far:
I'm using Gradle. I've created a parent module at root level. This parent module contains the just the main method for Spring Boot to init, and depends on both 'frontend' and 'admin' (both which, in turn, depend on 'core'). I've created a Controller on each of these two modules, and if the path is different they work fine. But still, they work as they belong to the same application, and both are mapped to the same context path. I want to be able to map "/login" on each module and let Spring decide where to execute based on context path ("localhost:8080/login" should be mapped to 'frontend' module Controller, "localhost:8080/admin/login" should be mapped to 'admin' module Controller).
Just to clarify, if the approach I'm using is not the best for what I'm trying to achieve, I'm happy to change it.

ConditionalOnMissingBean and hierachical starters

I have two kinds of applications, one is a special case of the other and so I have two layers of starters, where one starter is providing a basic functionality for the more general application type and the other for the more specific type of application. The specific one inherits the behavior of the more general one and then modifies it according to its own needs.
I have the following components:
SA - starter for the general application (jar).
SAP - starter parent for general application with SA as dependency and some other dependencies (pom).
SCA - "child" starter, with SAP as parent (jar).
SCAP - "child" starter parent for the more specific apps with dependency to SCA and some further dependencies (pom).
General apps use SAP as their parent and specific apps use SCAP as their parent.
I want to define a bean in SCA that will replace a bean in SA. For this I put ConditionalOnMissingBean in auto configuration in SA and created a bean with the same name in SCA but I get BeanDefinitionOverrideException. I don't want to use primary, as I plan on adding this ConditionalOnMissingBean also on that bean from SCA.
How do I approach this? Is the hierarchy of starters/starter parents appriopriate?
It sounds like you need to use #AutoConfigureBefore and/or #AutoConfigureAfter on your auto-configuration classes in conjunction with #ConditionalOnMissingBean.
The auto-configuration in your child starters should be ordered before the auto-configuration in the parent. Any beans that the child may want to replace should be defined in the parent with #ConditionalOnMissingBean. This arrangement will allow the child starter to define beans first. When the auto-configuration in the parent is then processed it will back off where beans have already been defined.
Note that for this to work, you must be using auto-configuration classes declared in spring.factories. This is described in more detail in this section of the Spring Boot reference documentation.

Use of Bean configuration XML File

I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.

JPA EntityListener and persistence archive

we've a persistence archive containing only Entities and the persistence.xml. And we've an ejb module containing the ejb stuff.
Now for a specific use case we need to add an EntityListener which has access to some EJBs in the service layer.
The ejb module depends on the persistence module. However to declare the listener in the Entity the persistence module needs to know about the class in the ejb module. A cyclic dependency is not possible and having a third module containing only the JPA listener leads to cyclic dependencies as well.
So the only option I see is to merge the ejb module and the persistence archive into a single module. However that way we loose the flexibility to use the persistence archive in another application to connect to the remote interfaces without carrying the whole ejb jar's content.
Any ideas on how to solve this and stay modular (separate ejb and persistence modules?).
We're talking about a JEE7 application.
You could move the persistence.xml from your JPA project to your EJB project and then use the <jar-file>packedEntity.jar</jar-file> XML element. Check this answer.
One idea is to use your Source-Control-Management (git/svn/cvs) to import the entity package in your EJB project (+the persistence.xml file). This way, you have more flexibility on what/how you define them.
In SVN you have svn:externals. For git check out this answer.

Spring 3 Application Context loading

I am a bit familiar with Spring framework but am still having lots of question concerning use of spring from project architectural view point. Now I am setting up Spring 3 and a Maven web application and am willing to try out all the the fancy component-scan's and autowiring features however this is where I get confused.
I am trying to break the project into sub-modules. And at some point these sub-modules may include something-context.xml in classpath*:resource/META-INF, like for instance when I will want to define a datSource related stuff in a separate module. So that's fine spring let's you load context files from within class-paths of all of the jars.
But here is where it gets vague - say I am using component scan. I am obviously using spring DispatcherServlet and it needs a servlet context to be loaded, and then there is a global application context parameter specified in web.xml contextConfigLocation.
So now servlet context config has a component-scan feature enabled for com.mycom.project.controllers and context loaded in the global contextConfigLocation has a context loaded with component scan feature for package com.mycom.project also searches for classpath*:META-INF/spring/*-context.xml.
So my question is - does this load controller's twice given that component scan is used for a for com.mycom.project.controllers and com.mycom.project? Or is it all loaded into one huge container and the contextConfigLocation parameter for either DispatcherServlet or global declaration is sort of access issue ? As in DispatcherServlet will reach only what's defined in servlet-context.xml but won't be able to use anything else?
And if my assumption is wrong, could I have a suggestion on how to manage multi-module project issues?
Thanks.
Yes, you might run into trouble. See this link for how to solve your problem.
#Service are constructed twice
The way you proceed when creating modules seems valid to me. You have a context.xml file for each module and all will get loaded once you load the application. Your modules are self-contained and can also be used in different environments. That's pretty much the way I'd also do it.

Categories