applicationContextProvider is not being called - java

I am using Spring 3.0.3.
I would like to use the applicationContextProvider so I declared:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-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/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
<context:annotation-config/>
<tx:annotation-driven/>
</beans>
and my ApplicationContextProvider:
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext _applicationContext) throws BeansException {
applicationContext = _applicationContext;
}
}
But the set is never being called!
and whenever I am using ApplicationContextProvider.getApplicationContext() returns null.
why is it?

Part of the problem may be that your getter is static. So its possible for you to call it before Spring has created an instance of ApplicationContextProvider.
You need to refer to the bean 'applicationContextProvider' that Spring has created for you when Spring is "ready" for you to use it. See Bean lifecycle
E.g. via a Junit test with your bean in 'app-context.xml' in src/test/resources
package com.mycompany.util;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#ContextConfiguration(locations="classpath:app-context.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationContextProviderTest {
#Autowired // Injected by Spring when bean is "ready"
ApplicationContextProvider contextProvider;
#Test
public void testContext() {
assertNotNull(contextProvider);
ApplicationContext context = ApplicationContextProvider.getApplicationContext();
assertNotNull(context);
System.out.println("My context has " + context.getBeanDefinitionCount() + " beans");
}
}
Then this gets a green bar for applicationContext being set.
Example output (don't leave System.out in the test btw).
INFO : org.springframework.test.context.TestContextManager - #TestExecutionListeners is not present for class [class com.mycompany.util.ApplicationContextProviderTest]: using defaults.
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [app-context.xml]
INFO : org.springframework.context.support.GenericApplicationContext - Refreshing org.springframework.context.support.GenericApplicationContext#4c331059: startup date [Sun Feb 27 13:38:13 GMT 2011]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#4b1c2b67: defining beans [applicationContextProvider,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
My context has 5 beans
INFO : org.springframework.context.support.GenericApplicationContext - Closing org.springframework.context.support.GenericApplicationContext#4c331059: startup date [Sun Feb 27 13:38:13 GMT 2011]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#4b1c2b67: defining beans [applicationContextProvider,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
app-context.xml:
<?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="applicationContextProvider" class="com.mycompany.util.ApplicationContextProvider"></bean>
</beans>

Seems like you are doing something the wrong way here... Do you want to get access to Spring beans from object not managed by Spring? How about WebApplicationContextUtils:
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
But WebApplicationContextUtils should always be treated as a last resort because this is not a Spring way. Are you sure you cannot integrate web services with Spring somehow? For instance with Apache CXF one can simply implement WS endpoint as a Spring bean or inject client proxy to other beans...
Using static fields is always asking yourself for trouble. I am sure you can achieve your goals in a more elegant fashion.

This is an old question with already accepted answer, but for me it wasn't really clear why the setApplicationContext() method wasn't being called on the applicationContextProvider. The answer provided how but really not the why.
Spring creates beans using lazy strategy: a bean will only be created the first time it is needed. That is why example in the accepted answer works: the bean is needed by ApplicationContextProviderTest and so it is created at that point, and not before, and setApplicationContext() method is being called at that point in time and everything works as intended.
However, if your bean is not auto-wired anywhere none of this will happen. In this case the solution is to tell Spring to not use lazy instantiation, i.e.:
<bean id="applicationContextProvider" lazy-init="false" class="com.mycompany.util.ApplicationContextProvider" />
This way, the bean will be created on application startup and method setApplicationContext() will be called at that time. You can then use the bean afterwords, provided that the usage happens after application startup is done.
Of course, much better way is to auto-wire the bean wherever you need it, but sometime it is not possible (read: legacy apps).

Related

Are we not encouraged to write XML configuration using Maven + Spring?

Currently learning to build spring apps. I have been quite sucessful deploying mock applications for now, but one thing has been annoying me, which is not understanding the mechanisms behind the numerous annotations we add to the code. Look, I'm not saying I don't know which purpose they serve, where they act, nor am I questioning their helpfulness.
My point is that I feel that skipping the changes that should be made (or are being made?) in the XML files actually makes me feel that at the end of the day I don't know what I am truly writing. Let me be more specific, so you could answer me with regards to the following example. This is from Spring manual.
Let’s assume we have the following configuration that defines firstMovieCatalog as the primary MovieCatalog
#Configuration
public class MovieConfiguration {
#Bean
#Primary
public MovieCatalog firstMovieCatalog() { ... }
#Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
With such configuration, the following MovieRecommender will be autowired with the
firstMovieCatalog.
public class MovieRecommender {
#Autowired
private MovieCatalog movieCatalog;
// ...
}
The corresponding bean definitions appear as follows.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
Okay, so, I think if you can answer me 2 questions regarding this example, It would clear a lot the understanding I am lacking here.
The first thing that is not clear for me: is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion?
Where actually IS this XML configuration file? All spring applications I generated through Initializr just generate the pom.xml file, and it does not include configuration. If I were not using the annotations, would I have to manually write an equivalent configuration in the pom?
is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion?
Spring is not generating any XML or annotation in any case. Spring use XML and annotation processing to get info about which components (classes) are available to use and which beans (instances) to create, inject and use for processing. Then, all these beans could be retrieved by application context (not to confuse with xml of the same name).
Where actually IS this XML configuration file?
Spring first version used XML to configure your app. Later (starting in Spring 3), Spring added annotation support and processing to ease application configuration. Annotations are just another way to configure your components and beans without the hassle of maintaining big XML files (over 1000 lines or even more) or just to avoid dealing with XML at all. Current Spring versions support both configurations, you could also use a mix: using XML and using annotations.
Note that Spring's ApplicationContext has several implementations with different entry points for configuration:
AnnotationConfigApplicationContext accepts a class decorated with #Configuration.
ClassPathXmlApplicationContext accepts the path of a XML file available in application classpath.
If I were not using the annotations, would I have to manually write an equivalent configuration in the pom?
First thing first: POM files are for maven processing, not for Spring. Since you're using Maven, and you want to try using a Spring Boot application without annotations, then you can have this project structure:
- src
- main
- java
/* your Java packages and files */
- com.example
+ App <--- Main entry point
- com.example.service
+ Car <--- Component 1
+ Engine <--- Component 2
- resources
+ my-beans.xml <--- XML configuration. Name can be anything
App class:
package com.example;
import com.example.service.Car;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
#Configuration
#ImportResource("classpath:my-beans.xml")
public class App {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(App.class, args);
Car car = ctx.getBean(Car.class);
car.move();
}
}
Car.class:
package com.example.service;
public class Car {
private Engine engine;
public void move() {
engine.start();
}
}
Engine.class:
package com.example.service;
public class Engine {
public void start() {
System.out.println("engine starts");
}
}
my-beans.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean class="com.example.service.Engine" />
<bean class="com.example.service.Car" />
<property name="engine" ref="engine"></property>
</bean>
</beans>
is the annotation process a SEPARATED process from the XML configuration, or is it GENERATING this equivalent XML configuration in some hidden fashion
When you initialize a Spring application, you instantiate an ApplicationContext: it's responsible to load all the context definition (the beans, services...).
ApplicationContext is actually an interface which has several implementations depending on how your context is defined:
ClassPathXmlApplicationContext which reads an XML file
AnnotationConfigApplicationContext for annotations based approach
...
Thus you can see it as a unique process, only the datasource is different: either XML or annotations. But they describe the same thing: a context.

Spring annotation #Inject doesn't work

I have the code #Inject works in one class but not in other.
Here's my code:
context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
<context:component-scan base-package="com.myfashions.services"/>
<context:component-scan base-package="com.myfashions.dao"/>
</beans>
SellerRetriever.java
public class SellerRetriever {
#Inject
UserDAO userDAO;
...
...
}
UserDAO class is present in com.myfashions.dao package.
#Inject is not working in Seller.java. Any reason why?
Make sure that both SellerRetriever and the implementation of UserDAO are annotated for the component scan. This will ensure that the latter is injected into the former:
#Service
public class SellerRetriever {
#Inject
UserDAO userDAO;
...
}
Annotate the UserDAO implementation with #Component.
When scanning multiple paths use:
<context:component-scan base-package="com.myfashions.services, com.myfashions.dao"/>
To be eligible to scan, your class must be annotated with either a more generic #Component, or #Service or #Repositories etc.. In your case, #Service logically better fits.
You could then (if you need) define some aspects (AOP) focused specifically on services call.
Besides, you may want to use #Autowired instead of #Inject to retrieve your bean.
For more information about differences concerning these two annotations:
What is the difference between #Inject and #Autowired in Spring Framework? Which one to use under what condition?
and you can see my comment just below explaining one good reason to keep #Autowired instead of #Inject.
I found my mistake, I'm posting this because in case anyone has the same problem. I used new operator to create an SellerRetriver object. Inject won't work if new operator is used to call that particular class.

Aspects are not executed

I'm trying to test a simple Aspect.
The app compiles and runs fine, BUT I do not get the Aspect executed. Or at least, I do not get the output the aspect should produce.
(my aim is to write an exception logger for any ex that occures in the app. but first this test aspect should run...)
Maybe someone who has more experience in aspects see's what I'm doing wrong?
package business;
public interface Customer {
void addCustomer();
}
import org.springframework.stereotype.Component;
#Component
public class CustomerImpl implements Customer {
public void addCustomer() {
System.out.println("addCustomer() is running ");
}
}
#RequestScoped #Named
//this is backing bean for jsf page
public class Service {
#Inject
Customer cust;
add() {
System.out.println("Service is running ");
cust.addCustomer();
}
}
#Aspect
public class AspectComp {
#Before("within(business..*)")
public void out() {
System.out.println("system out works!!");
}
}
Spring:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">
<context:annotation-config />
<context:component-scan base-package="business" />
<aop:aspectj-autoproxy />
</beans>
Output:
Service is running
addCustomer() is running
The Aspect statement is missing.
You are creating your Component with its constructor, and not getting it from Spring container! That's the problem, or you must use AspectJ's load-time weaver.
Just inject your component (CustomerImpl) in your service and then use the injected instance.
I remember having a similar problem once; Spring wasn't actually loading the proxy as it did not recognize the #Aspect annotation as being an annotation-scanable bean. I added the #Component annotation to the #Aspect notation and Spring started scanning it.
I never looked into the reasons why this happened, and why I needed to do that, so I cannot confirm that is the "proper" way of doing things. My gut would tell me that I had something missing in my config file; I can't imagine why Spring would not scan for #Aspect beans.
The other thing you can do, is to explicitly declare your Aspect bean in the XML config file as well to see if this the same type of problem you're having.
You can also enable debug logging in the Spring framework and see if your bean is being loaded by Spring. If not, then it gives you an idea where to start looking.

Spring DI - do not initialise all the dependent beans

I have a ServiceA which has a dependency on ServiceB. The serviceB comes from a spring bean file with lazy-init=true i.e, I only want serviceB to be initialised when and if I ask for that bean.
However I do use ServiceA throughout my application and when we do a setter based injection ServiceB gets initialised.
I want ServiceA to not initialise ServiceB until any method in ServiceA is called that needs ServiceB. One way of doing this was using the Aspects but I was looking at the simplest possible solution for this particularly in the Spring XML file for serviceB or some annotation in serviceB or any proxy flag.
I think LazyInitTargetSource does what you need.
Useful when a proxy reference is needed on initialization but the actual target object should not be initialized until first use. When the target bean is defined in an ApplicationContext (or a BeanFactory that is eagerly pre-instantiating singleton beans) it must be marked as "lazy-init" too, else it will be instantiated by said ApplicationContext (or BeanFactory) on startup.
Another approach that you might want to try is discussed at http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/aop/framework/autoproxy/target/LazyInitTargetSourceCreator.html:
[LazyInitTargetSourceCreator is a] TargetSourceCreator that enforces a LazyInitTargetSource for each bean
that is defined as "lazy-init". This will lead to a proxy created for
each of those beans, allowing to fetch a reference to such a bean
without actually initialized the target bean instance.
To be registered as custom TargetSourceCreator for an auto-proxy
creator, in combination with custom interceptors for specific beans or
for the creation of lazy-init proxies only. For example, as
autodetected infrastructure bean in an XML application context
definition:
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="customTargetSourceCreators">
<list>
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator"/>
</list>
</property>
</bean>
<bean id="myLazyInitBean" class="mypackage.MyBeanClass" lazy-init="true">
...
</bean>
If you find yourself doing this several times in an application context, this will save on configuration.
I don't know about Spring, but in Guice you would use a Provider<ServiceB>, so that when you were ready to use the service you'd go provider.get().callMethodOnB(...).
This is, I believe, part of the JSR-330 spec, so it's possible there's an equivalent thing in Spring (I haven't used an up-to-date version of Spring for quite some time).
You can also use method injection.
As a rule it's required to obtain a new instance of a singleton bean from a context, but it can be used in your case too.
Sample:
package org.test.lazy;
public abstract class ParentBean {
public abstract LazyBean getLazy();
public void lazyDoingSomething() {
getLazy().doSomething();
}
}
package org.test.lazy;
public class LazyBean {
public void init() {
System.out.println("Initialized");
}
public void doSomething() {
System.out.println("Doing something");
}
}
package org.test.lazy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#ContextConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
public class LazyTest {
#Autowired
private ParentBean parentBean;
#Test
public void test() {
parentBean.lazyDoingSomething();
parentBean.lazyDoingSomething();
}
}
<?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-3.0.xsd
">
<import resource="classpath:org/test/lazy/Lazy-context.xml"/>
<bean id="parentBean" class="org.test.lazy.ParentBean">
<lookup-method bean="lazyBean" name="getLazy"/>
</bean>
</beans>
<?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-3.0.xsd
"
default-lazy-init="true">
<bean id="lazyBean" class="org.test.lazy.LazyBean" init-method="init" />
</beans>
So you lazy bean will be initialized only once on demand.

How to add Spring Beans automatically to a TaskExecutor

I'm looking for a way to have spring beans registering themselves to a job processor bean who in turn will execute the registered beans on a schedule.
I'm hoping that the bean would just have to implement an interface and by some spring mechanism get registered to the job processor bean. Or alternatively inject the job processor bean into the beans and then somehow the job processor bean can keep track of where it's been injected.
Any suggestions appreciated, it might be that spring is not the tool for this sort of thing?
Use a spring context something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--Scans the classpath for annotated
components #Component, #Repository,
#Service, and #Controller -->
<context:component-scan base-package="org.foo.bar"/>
<!--Activates #Required, #Autowired,
#PostConstruct, #PreDestroy
and #Resource-->
<context:annotation-config/>
</beans>
And define a pojo like this:
#Component
public class FooBar {}
And inject like this:
#Component
public class Baz {
#Autowired private FooBar fooBar;
}
Spring has a powerful abstraction layer for Task Execution and Scheduling.
In Spring 3, there are also some annotations that you can use to mark bean methods as scheduled (see Annotation Support for Scheduling and Asynchronous Execution)
You can let a method execute in a fixed interval:
#Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
Or you can add a CRON-style expression:
#Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}
Here's the XML code you'll need to add (or something similar):
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Used together with
<context:component-scan base-package="org.foo.bar"/>
<context:annotation-config/>
as described by PaulMcKenzie, that should get you where you want to go.

Categories

Resources