Can we use @autowired in jsp. If yes then how.?

Viewed 10126

I am building a web application using spring and hibernate. I wanted to build the server side table for that I need a method that is written in Service class. But to execute it successfully I need to autowire it to the repected class as for now it is giving a Null Pointer Exception accessing the table.

5 Answers

If you're using Tomcat, yes, but it takes some work.

The solution is to wrap the normal tomcat instance manager (what it uses to instantiate JSP instances) and then to inject the wrapped version through a listener.

First, the wrapping manager class. It's pretty simple and just injects beans in newly created objects before returning them.

public class SpringInstanceManager implements InstanceManager {

    ServletContext ctx;
    InstanceManager manager;

    public SpringInstanceManager(ServletContext ctx, InstanceManager manager){
        this.ctx = ctx;
        this.manager = manager;           
    }

    public Object processAnnotations(Object o) throws IllegalAccessException, InvocationTargetException, NamingException {
        if (o != null && o.getClass().getName().endsWith("_jsp")){             
            SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(o, ctx);
        }
        return o;
    }

    @Override
    public Object newInstance(Class<?> clazz) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException {
        return processAnnotations(manager.newInstance(clazz));
    }

    @Override
    public Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException {
        return processAnnotations(manager.newInstance(className));
    }

    @Override
    public Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException {
        return processAnnotations(manager.newInstance(fqcn, classLoader));
    }

    @Override
    public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, NamingException {
        manager.newInstance(o);
    }

    @Override
    public void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException {
        manager.destroyInstance(o);
    }
}

And then we add a listener to inject it on context startup:

public class SpringJSPEnablerListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext context = sce.getServletContext();
        InstanceManager oldManager =  ((InstanceManager) (context.getAttribute(InstanceManager.class.getName())));
        if (!(oldManager instanceof SpringInstanceManager)) {
            InstanceManager springInjectingInstanceManager = new SpringInstanceManager(context,oldManager);
            context.setAttribute(InstanceManager.class.getName(), springInjectingInstanceManager);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {}
}

Then in the JSP pages you can use something like this

<%! @Autowired MyClass myClassInstance %>

and it should work correctly.

Related