How to add beans loaded via FileSystemXmlApplicationContext to an existing context loaded via ClassPathXmlApplicationContext? - spring

I have an old application that has all its spring batch beans in class path; these beans get loaded in application context using ClassPathXmlApplicationContext. Now, there is a need where I can put these spring batch beans outside my war/classpath.
If you could please help me here? I can not change existing code and if I load these new definitions using FileSystemXmlApplicationContext, how could I merge them with existing context?
Thanks !

You could try using #ImportResource in your new application to load the bean definitions from an XML resource:
#Configuration
#ImportResource({
"classpath:your-old-applicationContext.xml",
"classpath:another-old-applicationContext.xml"
})
public class NewApplicationConfig {
}

Related

Using both WebApplicationInitializer and web.xml in spring mvc+spring security+spring session redis web application

I'm trying to implement Spring redis session in an existing Spring MVC (ver 5.1.6) application. In web.xml we have ContextLoaderListener, DispatcherServlet and contextConfigLocation are all defined.
After required dependencies are included and suggested code changes are done, i'm getting below error:
Caused by: java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader definitions in your web.xml!"}}*
As part of code changes i'm extending the class "AbstractHttpSessionApplicationInitializer",(from Spring session core library) which internally implements WebApplicationInitializer. Seems like that is trying to create another context and throwing the above error. We cannot avoid extending this class, as this does the job of registering redisHttpSession to context.
Most of the examples available are all with spring boot. So there they wouldn't have faced this issue.
Any solution, other than completely replacing web.xml and use only WebApplicationInitializer?
Just want to provide an update. Instead of extending AbstractHttpSessionApplicationInitializer abtract class, i have taken a different approach by initializing bean RedisHttpSessionConfiguration thru XML bean definition.
This approach worked.
Followed the steps mentioned in the below thread;
How to configure Spring sessions to work with Redis in xml?
Along with that we need to serialize the cookie as well;
#Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}

Spring boot #ConfigurationProperties not loading from external properties file or class path property file

Hi I am trying to use a reusable library that I have created using spring boot(2.0.5) from 2 applications I am able to bind properties from application.properties which is in my classpath to my bean as follows and I see the schemas being set through the setters in my debug in my first spring batch application which is also created with spring boot(2.0.5)
This is the property bean class in my library which holds some service api- this library is just a jar package created with spring boot.
package com.test.lib.config
#ConfigurationProperties("job")
#PropertySources({
#PropertySource(value = "${ext.prop.dir}", ignoreResourceNotFound = true),
#PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
})
public class ServiceProperties {
/**
* Schema for the service
*/
private String schema;
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}
And the config bean for this library is as follows in the same package.
#Configuration
#EnableConfigurationProperties(ServiceProperties.class)
#ComponentScan("com.test.lib")
public class LibraryModuleConfig {
}
This code works perfectly fine when called from a sprint boot spring batch application which includes this library as a dependency and the corresponding setters are called and I can see the schema set when I add job.schema=testSchema in application.properties
I try to use this same library in an existing spring mvc web application started from a tomcat server with external files directory as launch arguments( This application was not created with spring boot) and added the appropriate context:component-scan to include the beans (java config beans) from the library in the application-context(appn-context.xml). The job.schema property is passed from both application.properties file and even a external file in C drive as given by the ${ext.prop.dir}" in the #propertySources annotation. The schema property in ServiceProperties Bean never gets set and even the setters never get called in the debug. Why will this libray config bean not work in an existing spring mvc application but work with the spring batch application. Both of them add the library as a dependency. I have been at this at a long time and except for the spring property binding the other functionality seem to work.
#EnableConfigurationProperties is a handy annotation that Spring Boot provides. (Spring MVC doesn't provides in default)
For a legacy Spring MVC app (specifically for Spring 3.x), you can use #Value annotation for the properties.
#Value annotation also works in Spring Boot so I guess you can make a change so that it works with older version (Spring 3.x) and newer version just works without changing anything at all.
Hope this helps! Happy Coding :)

Delay spring xml imports

I have an application where I have to read all application properties from properties files. Then override them from a external cache framework. Then initialize spring beans.
I am using Java Config of spring to read properties and override them. And using #import to load xml files. But xml files import as soon as context starts loading, resulting all the xml beans being initialized.
So is there a way I can delay xml files import until I load all the properties first?
You can use the following code.
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
or individually add lazy-init on beans which you don't want to load.
Or
There are lot of ways you can achieve your requirement One of which can be use of depends-on or #DependsOn if you are looking for annotation based configuration,
You can read property file after that you can create a cache bean and use
depends-on to let the container know you bean is depending on some other bean you can initialise a cache bean and use the same as you see fit.
See this example for better clearity.
<bean id="primaryBean" depends-on="cacheBean"></bean>
Now IoC guarantees that depending bean will be created before the bean which depends on this bean, So you will have an instance of this bean, and can use it.
Other than this you can implement LifeCycle interface
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
For more references you can refer spring docs.

Purpose of using #Configuration annotation

I have created a spring mvc based application but I didn't use this #Configuration annotation. What is the purpose of using #Configuration annotation? By using this, what are we communicating to springMVC container?
Assuming your application is using xml configuration rather than AnnotationConfig so it is not loaded to ApplicationContext at all.
#Configuration is used when ApplicationContext has been initialized and bean registration.
#Configuration annotation is a core Spring annotation, and not Spring MVC. It is a core entry point to configuring Spring-based application using Java config instead of XML config.
Please, use Spring Documentation more often because it is a place where you will find answers to most of your questions. Like this one:
Indicates that a class declares one or more Bean #Bean methods and may
be processed by the Spring container to generate bean definitions and
service requests for those beans at runtime

Can't get Spring bean

I have a Spring project in which I want to get a specific Spring bean defined in my Spring beans XML File. My Spring bean XML file is located at /WEB-INF/spring/root-context.xml.
Here is my code in the Service class:
ApplicationContext context = new ClassPathXmlApplicationContext("/WEB-INF/spring/root-context.xml");
Here is the error I get when I compile :
parsing XML document from class path resource [WEB-INF/spring/root-context.xml]; nested exception is java.io.FileNotFoundException: class path resource [WEB-INF/spring/root-context.xml] cannot be opened because it does not exist
Probably WEB-INF is not inside your classpath. I suggest to move the xml file in the classpath (for example src/main/resources/spring/root-context.xml). Then you can access it with: ApplicationContext context = new ClassPathXmlApplicationContext("/spring/root-context.xml"); If you're inside web application, Spring Mvc looks for th context in WEB-INF/<the name of the dispatcher servlet>-servlet.xml
If you want to access the context from WEB-INF you can load it using
GenericApplicationContext ctx = new GenericApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new FileSystemResource(path));
A better way is using WebApplicationContextUtils or implement ApplicationContextAware. Not sure what your use case is...

Resources