Announcement Announcement Module
Collapse
No announcement yet.
WebApplicationContext Newbie. How to Wrapp it? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • WebApplicationContext Newbie. How to Wrapp it?

    All Veterans,
    I am a newbie,

    I am writing a wrapper class that will be used in either Servlet
    or Struts Action class.

    First my wrapper class will returns all DAO beans and ApplicationContext will be hidden and won't called directly from client.

    for example:
    in servlet or Action class, it will be called something like this:

    Code:
    TestDAO dao = MySpringWebWrapper.getInstance().getDao("TestDAO");
    Wrapper Class code will be looks like this.

    Code:
    ApplicationContext appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(
    				servletContext);
    
    public TestDAO getDaoBean(String bean){
          appContext.getBean(bean);
    }
    However, I don't know how to make servletContext works. I am totally lost because I am not that familiar with Servlet stuff.

    Should I extends some class or is there anyway that i can get the reference of servletContext that use /WEB-INF/web.xml?

    What is the best way to do this?

    Thanks in advance

  • #2
    Hi

    in web.xml

    Code:
    <listener>
    		<listener-class>com.test.spring.CustomServletContextListener</listener-class>
    	</listener>
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/classes/spring/spring-context.xml</param-value>
    	</context-param>
    here adjust the pacakge name to whatever you call this class, and adjust the location of your spring config. personally i have one file in that directory, which does a few <import s to pull in the rest of the beans from other files in that same dir.

    Code:
    package com.test.spring;
    
    import javax.servlet.ServletContextEvent;
    
    import org.springframework.web.context.ContextLoaderListener;
    
    import com.test.spring.SpringUtil;
    
    /**
     * Extension of springs context listener:
     * gives the servlet context to SpringUtil.
     */
    public class CustomServletContextListener extends ContextLoaderListener {
    
    
    	/**
    	 * Called when context is loaded.
    	 * Does whatever spring does first,
    	 * and then passes the context to our
    	 * spring util so we can lookup beans
    	 */
    	@Override
    	public void contextInitialized(ServletContextEvent event)  {
    		super.contextInitialized(event);
    		SpringUtil.getInstance().setServletContext(event.getServletContext());
    	}
    }
    ^ that gets invoked when your web app starts. it sets up this singleton class down here V with the spring context. this is what you'll use from your actions, etc.


    Code:
    package com.test.spring;
    
    
    import java.util.Map;
    
    import javax.servlet.ServletContext;
    
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    
    /**
     * Custom utility class for getting beans
     * from the spring context.
     *
     * A lot needs to be done in here, I'm
     * not even sure if this is good practice
     * but it works fine for now.
     */
    public class SpringUtil {
    
    
    	private static SpringUtil instance;
    
    
    	private WebApplicationContext ctx;
    
    
    	public static SpringUtil getInstance()  {
    		synchronized (SpringUtil.class) {
    			if (instance == null)  {
    				instance = new SpringUtil();
    			}
    			return instance;
    		}
    	}
    
    	/**
    	 * Provide this class with the servlet
    	 * context in which the web app is running.
    	 * Must be called before getting beans.
    	 * @param context
    	 */
    	public void setServletContext(ServletContext ctx) {
    		this.ctx = WebApplicationContextUtils.
    				getRequiredWebApplicationContext(ctx);
    	}
    
    
    	/**
    	 * Get a bean of the given class from spring context,
    	 * in the case of multiple beans of same type returns
    	 * first instance.
    	 * @param <BeanClass>
    	 * @param beanClass
    	 * @return
    	 */
    	public <BeanClass> BeanClass getBean(Class<BeanClass> beanClass)  {
    		BeanClass bean = null;
    		for (BeanClass firstBean : getBeans(beanClass).values())  {
    			bean = firstBean;
    			break;
    		}
    		return bean;
    	}
    
    
    	/**
    	 * Returns a map<String, BeanClass> of all the
    	 * beans of a given type.
    	 * @param <BeanClass>
    	 * @param beanClass
    	 * @return
    	 */
    	public <BeanClass> Map<String, BeanClass> getBeans(Class<BeanClass> beanClass)  {
    		@SuppressWarnings("unchecked")		// needed because springs method is not generic
    		Map<String, BeanClass> beansOfType = ctx.getBeansOfType(beanClass);
    		return beansOfType;
    	}
    
    
    	/**
    	 * Get a bean by a given name.
    	 * @param beanId
    	 * @return
    	 */
    	public Object getBeanById(String beanId)  {
    		return this.ctx.containsBean(beanId)
    					? this.ctx.getBean(beanId)
    					: null;   
    	}
    
    
    
    	public <BeanClass extends Object> void outject(String beanId, BeanClass bean)  {
    		ConfigurableApplicationContext outjectCtx = (ConfigurableApplicationContext) getCtx();
    		DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) outjectCtx.getBeanFactory();
    		beanFactory.registerSingleton(beanId, bean);
    	}
    
    
    	public WebApplicationContext getCtx() {
    		return this.ctx;
    	}
    
    
    	public void setCtx(WebApplicationContext ctx) {
    		this.ctx = ctx;
    	}
    }
    these classes have worked very well for me. the getBean(Class) method is a bit strange, but has proven to be very useful and safe.

    Comment


    • #3
      If you do end up using Struts, I would have a look at this article. You can then just do normal DI into your Struts actions.
      http://www-128.ibm.com/developerwork...ary/j-sr2.html

      Comment


      • #4
        ^ yes that is a better approach. I use stripes, so my spring beans are automatically injected into my actions with the @SpringBean annotation.

        I use that SpringUtil class sparingly but it certainly has its place. Usually in testing where i'm too lazy to setup all the DI stuff and I just want to pull a bean out. Other than for quick tests I do use it inside of a servlet filter where I can't do DI. For cases like that it's a great thing to have in the toolbox, but I wouldn't recommend overusing it.

        Comment


        • #5
          What about implementing ServletContextAware?

          Thank you all for replies.

          lloy, i did little research last night and found out implementing ServletContextAware is one way to do it and much easier but you have to add Wrapper class as SprinngBean.
          But this leads to another problem. Singleton issue.

          And i am not so sure how do I make this wrapper class as singleton if this is going to springbean? springbean has to have public constructor. right?
          singleton can't have public constructor.

          Any idea?

          Comment


          • #6
            Originally posted by kawaii369 View Post
            i did little research last night and found out implementing ServletContextAware is one way to do it and much easier but you have to add Wrapper class as SprinngBean.
            But this leads to another problem. Singleton issue.

            And i am not so sure how do I make this wrapper class as singleton if this is going to springbean? springbean has to have public constructor. right?
            singleton can't have public constructor.
            A singleton can have a public constructor, it's just if you have one you kind of make the singleton aspect pointless. Spring can actually access a no-arg public constructor though. I really wouldn't lookup beans though unless you really have to, I would prefer DI. Even then the reference manual has some information on this e.g. within a web context you can use WebApplicationContextUtils.
            http://www.springframework.org/docs/...and-singletons

            Comment


            • #7
              Originally posted by kawaii369 View Post
              Thank you all for replies.

              lloy, i did little research last night and found out implementing ServletContextAware is one way to do it and much easier but you have to add Wrapper class as SprinngBean.
              But this leads to another problem. Singleton issue.

              And i am not so sure how do I make this wrapper class as singleton if this is going to springbean? springbean has to have public constructor. right?
              singleton can't have public constructor.

              Any idea?
              i'm not sure why you think that is easier than the code i posted above. sounds like a huge PITA to me.

              private PatientManager patientManager = SpringUtil.getInstance().getBean(PatientManager.cl ass);

              how is writing a singleton wrapper class for every single bean you have easier than that? ... eclipse & ctrl space will even type all that for you. if you are using struts, you should follow that article that was posted. if you need to grab a bean where DI is not possible or you're lazy (me sometimes), SpringUtil does a fine job.

              Comment

              Working...
              X