How do i create ServletContext in Spring - spring

I wanted to add some values to the servletcontext, but am not sure how to get the object in spring. Can anyone please help

Try this:
#Autowired
ServletContext servletContext;

See this answer.
Implementing the ServletContextAware interface will make Spring to inject the context.
#Controller
public class ServicesImpl implements Services, ServletContextAware{
private ServletContext context;
public void setServletContext(ServletContext servletContext) {
this.context = servletContext;
}

Related

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

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

How to add an object to application scope in Spring

We can set the request attributes using Model or ModelAndView object in Spring.
We can use #SessionAttributes to keep attributes in session scope.
Then how can I put an attribute in application scope in Spring, does spring has provided any annotation for that?
Basically all that is needed to configure an application scope is to use the ServletContext, and you can do it in Spring as follows:
public class MyBean implements ServletContextAware {
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
}
javax.servlet.ServletContext could be even injected to your bean implementation as follows:
#Component
public class MyBean {
#Autowired
private ServletContext servletContext;
public void myMethod1() {
servletContext.setAttribute("attr_key","attr_value");
}
public void myMethod2() {
Object value = servletContext.getAttribute("attr_key");
...
}
}
When you mention about storing your model at application scope then I would conclude you wish to store it at the ServletContext level.
For doing that you need to make your controller implements ServletContextAware interface.
import org.springframework.web.context.ServletContextAware;
// ...
public class MyController implements ServletContextAware {
private ServletContext context;
public void setServletContext(ServletContext servletContext) {
this.context = servletContext;
}
After getting access to ServletContext you can add it as a attribute
servletContext.setAttribute("modelKey", modelObject);
Kindly let me know if this is what you are looking for.
In the spring you can get application scope by using #Autowired annotation
#Autowired
private ServletContext servletContext;
Then you can access you element by using .getAttribute Method
Object someObj = servletContext.getAttribute("object",someObj);
if(someObj==null)
someObj = new Object(); //This will create new Object if it doesn't exists.
servletContext.setAttribute("object",someObj);

Create spring managed beans with factory

I have a spring application in which I am trying to inject many beans of the same type. I do not know how many of these beans there will be before runtime, so it seems natural to use the factory pattern, as I cannot configure each bean in my java config class. However, these beans need to have some of their fields wired by Spring, and when I create them with "new" in my factory, they are of course not Spring managed.
Is there a way to have the beans I create in my factory class be managed by Spring? Or is the factory pattern the wrong way to go about this?
I am fairly new to posting, so please let me know if any more information is necessary.
You can define a beanFactory wired with the dependencies needed for your bean, then manually injected them in each new bean created by the beanFactory. For example:
public class MyBean {
private Dependency1 dep1;
private Dependency2 dep2;
public MyBean(Dependency1 dep1, Dependency2 dep2) {
this.dep1 = dep1;
this.dep2 = dep2;
}
}
#Component
public class MyBeanFactory {
#Autowired
private Dependency1 dep1;
#Autowired
private Dependency2 dep2;
public MyBean createInstance() {
return new MyBean(dep1, dep2);
}
}
#Component
public class MyBeanConsumer {
#Autowired
private MyBeanFactory myBeanFactory;
public void foo() {
final MyBean bean = myBeanFactory.createInstance();
}
}
You can't use #Autowired because of the variable number of beans, but you can still make use of ApplicationContextAware to create obtain the beans.
Using that you can programmatically create prototype beans from your Java code if the type of bean has been defined before in the configuration, or alternatively you can create the new object in your factory using new, and then set the dependencies by using this same method.
This is an example of an implementation:
public final class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) {
return CONTEXT != null ? CONTEXT.getBean(beanName) : null;
}
public static <T> T getBean(Class<T> objectClass) {
return CONTEXT != null ? CONTEXT.getBean(objectClass) : null;
}
}

Why #Inject is not working when implement BeanFactoryPostProcessor

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

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

Resources