How to get ApplicationContext inside a unit test class of non-spring managed class - spring

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;
}
}

Related

how to convert BeanFactory to ApplicationContext

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.

setApplicationContext(ApplicationContext applicationContext) never called

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

SingletonBean with PrototypeBean dependency

I am learning the scope dependency of injected beans in Spring framework. I was learning to solve the narrow scope bean dependency from websites. But I am not able to see the resolution as explained in the websites. I have tried using the method of Inject ApplicationContext bean into MySingletonBean to get instance of MyPrototypeBean. However I do not see any difference in the bean creation.
#SpringBootApplication
#ComponentScan("com.learning.spring.basics.scope.proxy")
public class SpringScopeProxyApplication {
public static void main(String...strings) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(SpringScopeProxyApplication.class, strings);
SingletonBean bean1=ctx.getBean(SingletonBean.class);
/**
* Singleton bean is wired with a proototypeBean. But since a singleton bean is created only once by the container
* even the autowired proptotyeBean is also created once.
*/
bean1.display();
SingletonBean bean2=ctx.getBean(SingletonBean.class);
bean2.display();
}
}
#Component
public class SingletonBean {
#Autowired
// prototypeBean is of scope prototype injected into singleton bean
private PrototypeBean prototypeBean;
//Fix 1 - Inject ApplicationContext and make the singletonbean applicationcontextaware
#Autowired
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public PrototypeBean getPrototypeBean() {
return prototypeBean;
}
public void setPrototypeBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
// Fix -1 - get the prototypeBean object from applicationContext everytime the method is called
public void display() {
applicationContext.getBean(PrototypeBean.class).showTime();
//prototypeBean.showTime();
}
PrototypeBean
package com.learning.spring.basics.scope.proxy;
import java.time.LocalDateTime;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeBean {
public void showTime() {
System.out.println("Time is "+LocalDateTime.now().toString());
}
}
Expected Results:The time stamp should be different as the prototype scoped bean should be a new instance
Actual results: The timestamps are same with no difference
This is not right way to validate SCOPE_PROTOTYPE bean because showTime is an instance methods that gets executed when you invoke it through object so you will always get the different timestamp.But i'm not sure how you are getting same timestamp, but below is an example
#SpringBootApplication
#ComponentScan("com.learning.spring.basics.scope.proxy")
public class SpringScopeProxyApplication {
public static void main(String...strings) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(SpringScopeProxyApplication.class, strings);
SingletonBean bean1=ctx.getBean(PrototypeBean.class);
System.out.println(bean1);
SingletonBean bean2=ctx.getBean(PrototypeBean.class);
System.out.println(bean2);
}
}
You will get the two different object references
com.learning.spring.basics.scope.proxy.PrototypeBean#48976e6d
com.learning.spring.basics.scope.proxy.PrototypeBean#2a367e93

Access spring component from servlet

I have a controller (for example. MyManager) where I invoke method (for example myMethod() ) of component class (bean), for example MyComponent. I have I servlet where I want to invoke myMethod() . In servlet I have annotated MyManager by #Autowired annotation , despite this I got NullPointerException. I saw this kind of topic but it is not useful for me. For imagination I write little code :
public class myClass extends HttpServlet {
#Autowired
private MyComponent component;
public void init(ServletConfig config) throws ServletException{
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
protected void doGet(HttpServletRequest req,HttpServletResponse res) throws ... {
List<MyObject> objects =component.myMethod(); // Here is the problem, component is null
}
}
}
I make Spring configuration file "context.xml" and I got bean (component) object, but now I have problem with injected EntityManager in bean object. Now it is null , can anyone help me to solve this problem ? Also update init() method.
public void init(ServletConfig config) throws ServletException{
ApplicationContext con = new ClassPathXmlApplicationContext("context.xml");
component = (MyComponent) con.getBean("myBean");
}
You cannot autowire dependencies like that because Servlets are not Spring Beans. You need to do something like the following:
#Override
public void init() throws ServletException {
super.init();
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
component= applicationContext.getBean(MyComponent.class);
}
Also drop the #Autowired annotation from component

How to use the appicationcontextaware in java 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........?

Resources