I have some code like this:
#Slf4j
#Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
ListableBeanFactory listableBeanFactory = factory;
ApplicationContext applicationContext = (ApplicationContext) listableBeanFactory;
AbstractApplicationContext context = (AbstractApplicationContext) applicationContext;
ConfigurableEnvironment environment = context.getEnvironment();
AbstractEnvironment abstractEnvironment = (AbstractEnvironment) environment;
abstractEnvironment.getProperty("business.bean.dependsOn");
// how to gain ApplicationContext
//.........
}
I want to obtain some config value from classpath:application.properties
and only ApplicationContext could getEnvironment.
how to gain ApplicationContext?
The ApplicationContext object can be obtained by implementing the ApplicationContextAware interface.
The Value annotation gets the attributes in application.properties.
Related
I have a requirement where I had to use Spring beans inside a POJO class to retrieve a MyDomainClass object. Since Autowiring the beans inside the class which is not managed by Spring isn't possible, I had to explicitly get the ApplicationContext from another util class and retrieve the bean from applicationContext object. Please find the code below
#Component
public class ApplicationContextUtils implements ApplicationContextAware{
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
applicationContext = appContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
The code for using the applicationContext and retrieving the bean is below
public class MyNonBeanClass{
public MyDomainClass retrieveMyDomainObj(){
ApplicationContext applicationContext=ApplicationContextUtils.getApplicationContext();
TestBean testBean=(TestBean)applicationContext.getBean("testBean");
return testBean.retrieve(param1,param2);
}
}
This code is working as expected and I am able to fetch the beans from the application context successfully. But writing the test case has been challenging to say the least. I am not even sure if we will be able to write the test case for my non bean class but I would still like to try. I am trying to use PowerMock to mock the static invocation of getApplicationContext() in ApplicationContextUtils. But I am unable to get the applicationContext necessary for getting the TestBean object. And a NullPointerException is thrown when the getBean() is called on applicationContext. Please help with this.
#RunWith(PowerMockRunner.class)
#PrepareForTest(ApplicationContextUtils.class)
#ContextConfiguration(classes= { BaseTestContext.class})
public class MyNonBeanClassTest implements ApplicationContextAware{
MyNonBeanClass myNonBeanClass;
ApplicationContext applicationContext;
#Test
public void test_retrieveMyDomainObj(){
myNonBeanClass=new MyNonBeanClass();
PowerMockito.mockStatic(ApplicationContextUtils.class);
when(ApplicationContextUtils.getApplicationContext()).thenReturn(applicationContext);
assertNotNull(myNonBeanClass.retrieveMyDomainObj(param1, param2));
}
#Override
public void setApplicationContext(ApplicationContext appContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext=appContext;
}
public ApplicationContext getApplicationContext(){
return this.applicationContext;
}
}
I'm trying to get the Spring application context and then call its method getBean("beanName") to get a specific bean but I'm having a null pointer exception indicating that the context is null. When I put a breakpoint inside the setApplicationContext() method, I found out that this method is never called which is weird since this method should be called after spring finishes beans instantiation. I looked for some similar questions here but none worked for me.
this is my code:
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CONTEXT = applicationContext;
}
public static Object getBean(String beanName){
return CONTEXT.getBean(beanName);
}
}
Set the ApplicationContext that this object runs in.
Normally this call will be used to initialize the object.
The ApplicationContext object to be used by this object.
Add #Component.
#Component
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CONTEXT = applicationContext;
}
public static ApplicationContext getApplicationContext(){
return CONTEXT;
}
}
Use ApplicationContext.
TheBeanInstance bean = SpringApplicationContext.getApplicationContext().getBean(requiredType);
ApplicationContextAware
Is there a way to retrieve the job beans declared within this location: classpath*/META-INF/spring/batch/jobs/*.xml ?
Tried the code below but I was not able to retrieve them.
#Autowired
private ApplicationContext applicationContext;
public void sometMethod() {
AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
String[] strings = ((BeanDefinitionRegistry) beanFactory).getBeanDefinitionNames();
}
I was able to able to merge the applicationContext and the job bean definitions with the following changes:
#Autowired
private ApplicationContext applicationContext;
public void sometMethod() {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"classpath:META-INF/spring/batch/jobs/*.xml"}, applicationContext);
AutowireCapableBeanFactory beanFactory = context.getAutowireCapableBeanFactory();
String[] strings = ((BeanDefinitionRegistry) beanFactory).getBeanDefinitionNames();
}
I have some web app with simple task:
public class CustomTask {
private final Logger logger = LoggerFactory.getLogger(getClass());
#Inject
private CustomDao customDao;
#Override
#Transactional(propagation = Propagation.REQUIRED, timeout = 600)
public int run() {
customDao.doSomething();
}
}
now it work with no problem. But now I want to add implementation of BeanFactoryPostProcessor (implements BeanFactoryPostProcessor)to this task and override this method:
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
logger.info(beanFactory.getClass() + "xxxxxxxxxx");
logger.info("The factory contains the followig beans:");
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (int i = 0; i < beanNames.length; ++i)
logger.info(beanNames[i]);
}
but now then I want to do something with customDao it throw NullPointException and I dont know why because in logger I see that this bean is registred. Can you explain me why this exception occurs and how should I fix it ?
This will not work because #Inject (just like #Autowired) is detected by AutowiredAnnotationBeanPostProcessor which is a BeanPostProcessor. BeanFactoryPostProcessors are instantiated BEFORE any other bean in the application context. So, when your post processor is created, the infrastructure that detects #Inject annotation isn't even created and cannot act on your bean factory post processor.
See the api docs for Autowired annotation where there is a note about the restriction for BeanFactoryPostProcessors.
You could make your task to implement BeanFactoryAware and inject the bean yourself:
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.customDao = beanFactory.getBean(CustomDao.class);
}
I need to load the applicationcontext in java class in which the applicationcontextaware bean is defined. I need to access the other beans inside the applicationcontext.xml using the applicationcontextaware. I dont want to load the context using
ClassPathXmlApplicationContext("applicationContext.xml");
I need to access the beans inside the applicationContext like this
ApplicationContextAccess.getInstance().getApplicationContext.getbean("BeanName");
Applicationcontextacess implemented as singleton class:
public class ApplicationContextAccess implements ApplicationContextAware {
private ApplicationContext applicationContext = null;
private static ApplicationContextAccess applicationContextAccess=null;
private ApplicationContextAccessor() {
}
public static synchronized ApplicationContextAccess getInstance() {
if(applicationContextAccess == null)
{
applicationContextAccess = new ApplicationContextAccess();
}
return applicationContextAccess;
}
public void ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationContext = applicationContext;
}
}
I need to access the beans inside the applicationContext like this ApplicationContextAccess.getInstance().getApplicationContext.getbean("BeanName");
But I have a doubt how the getApplicationContext loads the applicationContext.xml........?