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.
Related
This question already has answers here:
application context. What is this?
(4 answers)
What is Application context and bean factory in spring framework [duplicate]
(1 answer)
Closed 3 years ago.
I have a Spring Boot app and it's running with Spring Data, MySQL, Spring Security and MVC. The app is running for me just as fine.
However, I keep hearing about ApplicationContext a lot and I was wondering when do I need to use it and would like to know what it does. Can someone give me an example and an overview of ApplicationContext and its use?
ApplicationContext is a core interface that Spring framework built on. If you're building a Spring application, you're already using the ApplicationContext. You can have great insight about this from Spring Framework Reference Documentation. As per this document, Spring framework consists with these modules;
The Context (spring-context) module builds on the solid base provided
by the Core and Beans modules: it is a means to access objects in a
framework-style manner that is similar to a JNDI registry. The Context
module inherits its features from the Beans module and adds support
for internationalization (using, for example, resource bundles), event
propagation, resource loading, and the transparent creation of
contexts by, for example, a Servlet container. The Context module also
supports Java EE features such as EJB, JMX, and basic remoting. The
ApplicationContext interface is the focal point of the Context module.
spring-context-support provides support for integrating common
third-party libraries into a Spring application context, in particular
for caching (EhCache, JCache) and scheduling (CommonJ, Quartz).
Spring ApplicationContext also inherits BeanFactory super-interface. So technically ApplicationContext is capable of doing all the things, BeanFactory interface is capable and much more. BeanFactory interface along with ApplicationContext provide the backbone of the Spring IoC container (Core container). Which is Bean management for your application.
The interface org.springframework.context.ApplicationContext
represents the Spring IoC container and is responsible for
instantiating, configuring, and assembling the aforementioned beans.
The container gets its instructions on what objects to instantiate,
configure, and assemble by reading configuration metadata. The
configuration metadata is represented in XML, Java annotations, or
Java code. It allows you to express the objects that compose your
application and the rich interdependencies between such objects.
ApplicationContext uses eager loading mechanism. So, every bean declared in your application, initialize right away after the application started and after, this ApplicationContext scope is pretty much read-only.
Initiate a Spring IoC container with custom bean definitions is pretty much staright forward.
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"daos.xml"});
Following file shows this daos.xml file content;
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd">
<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for data access objects go here -->
</beans>
After that you can access the beans define in the .xml like this;
JpaItemDao obj = (JpaItemDao) factory.getBean("itemDao");
These instances are now being initialized and managed by the ApplicationContext. But most users prefer to use #Bean annotation define beans to do the binding and #Autowired annotation to do the dependency injection. So, no need to manually feed a bean .xml to custom initialized ApplicationContext.
#Configuration
class SampleConfig {
#Bean
public JpaItemDao getJpaItemDao() {
return new JpaItemDao();
}
}
and inject in;
#Component
class SampleComponent {
#Autowired
private JpaItemDao itemDao;
public void doSomething() {
itemDao.save(); // Just an example.
}
}
Besided the bean management, ApplicationContext does some other important thing in the Spring core container. As per ApplicationContect javadoc, they are;
Bean factory methods for accessing application components. Inherited from ListableBeanFactory.
The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface.
The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface.
The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface.
Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a
single parent context can be used by an entire web application, while
each servlet has its own child context that is independent of that of
any other servlet.
Also, checkout the sub-interfaces of ApplicationContext that specifically designed for work on different use cases like WebApplicationContext.
ApplicationContext is a core concept (arguably the most important one) of spring used also in spring boot of course but and ideally hidden from the programmers in both cases, meaning that the programmer should not directly interact with it in a business code of the application.
Technically its an interface that has many implementations, the relevant one is picked depending on in which environment you're running and how do you configure the application.
So does it do? Its a class that basically is a registry of all the beans that spring has loaded. In general, starting up the spring mean finding the beans to load and putting them in the application context (this is relevant for singletons only, prototype-scopes beans are not stored in the ApplicationContext).
Why does spring need it?
For many reasons, to name a few:
To manage lifecyle of the beans (when the application shuts down, all beans that have a destroy method should be called)
To execute a proper injection. When some class A depends on class B spring should inject class B into class A. So by the time of creating the class A, class B should already be created, right? So spring goes like this:
Creates B
Puts B into application context (registry)
Creates A
For injection goals: gets B from the application context and injects into A
// an illustration for the second bullet
class B {}
class A {
#Autowired
B b;
}
Now there are other things implemented technically in application context:
Events
Resource Loading
Inheritance of application contexts (advanced stuff, actually)
However now you have an overview of what it is.
Spring boot application encapsulates the application context but you can still access it from many places:
in the main method when the application starts it returns an application context]
you can inject it into configuration if you really need
its also possible to inject the application context into the business bean, although we shouldn't really do so.
In simple words:
Spring is popular for dependency Injection.
So all the bean definitions(Objects) will be created by the spring and maintained in the container. So all the bean life cycle will be taken care by spring container.
So ApplicationContext is a interface It has different implementations will be there to initialize the spring container.
So ApplicationContext is the reference to Spring Container.
Some popular implementations are:
AnnotationConfigWebApplicationContext,
ClassPathXmlApplicationContext,
FileSystemXmlApplicationContext,
XmlWebApplicationContext.
Reference: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html
If I have a bean defined in an xml file like so :
<bean id="myBean" class="com.myClass">
</bean>
Should "myBean" be autowired, ie should the class "com.myClass" be initialized by Spring ?
I have no Spring annotations in "com.myClass" but the class still seems to be initialized because it is declared in an xml file.
Yes, it is normal that your class to be initialised even though auto-wiring is not stated. The reason for this is:
Declared Spring beans have a life-cycle and the first step in this life-cycle is for Spring to initialise the bean.
The basic life-cycle is as follows:
Initialise Bean
Insert values
Calling certain methods depending on which interfaces you implement. This is useful for further custom initialisation and configuration.
Now your bean is ready for use by your application and will stay in the application context until your application context is destroyed.
Finally, if you implement the DisposableBean interface, the destroy method is called for any de-initialisation process that you may require.
This depends on whether you have any other beans that want Spring to inject myBean into them. If no one uses your bean, you can omit it.
I wonder if it is possible to have a bean form xml file injected by #Autowired somehow into Liferay hook. In this particular case I'm using UpgradeProcess hook. My project is already configured for using Spring with liferay, I can decode xml with ClassPathXmlApplicationContext's getBean("bean name") method, but it would be much nicer if this had happened automatically.
greetz!
It is possible denu.
Configure your application's web.xml listener class as org.springframework.web.context.ContextLoaderListener and place applicationContext.xml in the WEB-INF folder. It will pick the respective beans from your applicationContext.xml and you can autowire those objects in your beans.
Cheers
I have a dao jar file that contains all the domain objects and service classes. it has a config file dao-resource.xml with id=datasource.
I am using this jar file in another project which has its own app-context.xml, but i want to override the bean with id="datasource" in the jar file
how do i do this. I tried to add a bean with same id in app-context.xml and added both files to classpathxmlapplicat.... first dao-resource.xml then app-context.xml
but that did not seem to work.
how else can i override a bean
Having spring config files in jars makes things a bit harder to manage. If you have annotated your classes it would be easier.
But anyway, I'd suggest splitting the dao xml in two parts - your beans, and infrastructure-related beans (like the datasource). Then you can include only the ones you need in your app-context.xml.
Another way would be to use primary="true" on your overriding bean. This would mean all injection points that need a bean of type DataSource, would pick your primary bean. But that won't work if you refer to your datasource in your dao xml.
So in short - you can't override a bean, so split your xml file and include only the parts you need.
I'm trying to inject Spring beans into an EJB using #Interceptors(SpringBeanAutowiringInterceptor.class) but I cannot get it working with the beanRefContext.xml examples I've seen.
Here's my EJB:
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class AlertNotificationMethodServiceImpl implements
AlertNotificationMethodService {
#Autowired
private SomeBean bean;
}
I've provided a beanRefContext.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="...">
<!-- Have also tried with ClassPathXmlApplicationContext -->
<bean id="context"
class="org.springframework.web.context.support.XmlWebApplicationContext">
<property name="configLocations" value="/config/app-config.xml" />
</bean>
</beans>
But, it seems to be recreating the beans instead of obtaining the existing ApplicationContext. I end up with the following exception because one of my beans is ServletContextAware.
java.lang.IllegalArgumentException: Cannot resolve ServletContextResource
without ServletContext
When using the SpringBeanAutowiringInterceptor, shouldn't it obtain the ApplicationContext instead of create a new one?
I also tried changing my web.xml so the contextConfigLocation points to the beanRefContext.xml, hoping it'd load my Spring config but I end up with the same exception as above.
Does anyone know how to do this properly? The examples I've seen seem to use the same method I'm using which I assume means the beans are being recreated when the Interceptor is invoked (or is that how it's supposed to work and I've misunderstood).
When using the SpringBeanAutowiringInterceptor, shouldn't it obtain the ApplicationContext instead of create a new one?
Yes, and this is in fact what it does. It uses the ContextSingletonBeanFactoryLocator mechanism, which in turn manages a number of ApplicationContext instances as static singletons (yes, even Spring has to resort to static singletons sometimes). These contexts are defined in beanRefContext.xml.
Your confusion seems to stem from the expectation that these contexts have any relation to your webapp's ApplicationContext - they don't, they're entirely separate. So your webapp's ContextLoader is creating and managing a context based on the bean definitions in app-config.xml, and the ContextSingletonBeanFactoryLocator creates another one. They won't communicate unless you tell them to. The EJBs cannot get hold of the webapp's context, since EJBs sit outside of that scope.
What you need to do is to move the beans that need to be used by your EJBs out of app-config.xml and into another bean definition file. This extracted set of bean definitions will form the basis of a new ApplicationContext which will (a) be accessed by the EJBs, and (b) will act as the parent context of your webapp's context.
In order to activate the parent-child link between your webapp's context and the new context, you need to add an additional <context-param> to your web.xml called parentContextKey. The value of this parameter should be the name of the context defined in beanRefContext.xml (i.e. context, in your example).
The beans that stay behind in the webapp's context will be able to reference the beans in the parent context, as will the EJBs. However, the EJBs will not be able to reference anything in the webapp's context.
Also, you cannot use XmlWebApplicationContext in beanRefContext.xml, since that class requires awareness of the webapp, and ContextSingletonBeanFactoryLocator cannot supply that awareness. You should stick with ClassPathXmlApplicationContext there.