Announcement Announcement Module
Collapse
No announcement yet.
Spring / Struts - best practice Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring / Struts - best practice

    Hi,

    i am using the Spring-LDAP-API in a Struts webapplication. I am searching for some 'best practice' hints where to place the factory/dao. For Hibernate, a best practice seems to write a Struts-plugin - i did the same for Spring.

    Is this the best way to do it? And should i store BeanFactory or the PersonDao in the SessionContext to make pooling available?

    Thanks in advance for any hints,
    Christian

  • #2
    I'm not sure what you're asking. Do you need more specific information than what's described in the Struts integration section in the Spring reference manual?

    Comment


    • #3
      O.k., ...

      ... i am using only the Spring-LDAP-API, nothing more of Spring, plus Hibernate and Struts.

      So i went out and wrote a plugin for Struts:

      Code:
      /*
       * SpringLdapPlugin.java
       *
       * Created on 13. März 2007, 12:38
       *
       */
      
      package de.uniulm.coronaNG.struts.plugins;
      
      import de.uniulm.coronaNG.Constants;
      import de.uniulm.coronaNG.spring.ldap.PersonDao;
      import javax.servlet.ServletException;
      import org.apache.log4j.Logger;
      import org.apache.struts.action.ActionServlet;
      import org.apache.struts.action.PlugIn;
      import org.apache.struts.config.ModuleConfig;
      import org.springframework.beans.factory.BeanFactory;
      import org.springframework.beans.factory.xml.XmlBeanFactory;
      import org.springframework.core.io.ClassPathResource;
      
      /**
       *
       * @author caschoff
       */
      public class SpringLdapPlugin implements PlugIn {
          
          /**
           * <b>Jede</b> Klasse hat ihren Logger.
           */
          private static final Logger logger = Logger.getLogger(SpringLdapPlugin.class);
          
          /**
           * Die Verbindung zum LDAP.
           */
          private BeanFactory factory;
          
          /**
           * Creates a new instance of SpringLdapPlugin.
           */
          public SpringLdapPlugin() {
          }
          
          /**
           * Initialisierung.
           * @param actionServlet Das ActionServlet.
           * @param moduleConfig Die Modulkonfiguration.
           * @throws ServletException Wird bei einem Initialisierungsfeheler geworfen.
           */
          public void init(ActionServlet actionServlet, ModuleConfig moduleConfig)
          throws ServletException {
              try {
                  logger.debug("Erzeuge BeanFactory fuer LDAP-Zugriff aus spring.cfg.xml");
                  logger.error("LDAPs einschalten!");
                  
                  factory = new XmlBeanFactory(new ClassPathResource("spring.cfg.xml"));
                  
                  actionServlet.getServletContext().setAttribute(Constants.ldapFactory, factory);
              } catch (Throwable ex) {
                  logger.error("Exception in init", ex);
                  throw new ServletException(ex);
              }
          }
          
          /**
           * Wird vom Container bei einem Undeploy/Herunterfahren aufgerufen.
           */
          public void destroy() {
              logger.debug("Nichts zum schliessen im Spring-LDAP-Plugin.");
          }
          
      }
      In my Struts-Actions, i use the Factory like this:

      Code:
      ...
      
      // Neue Session erstellen.
      session = request.getSession(true);
      // LDAP-Objekt holen...
      BeanFactory factory = (BeanFactory) servlet.getServletContext().getAttribute(Constants.ldapFactory);
      PersonDao personDao = (PersonDao) factory.getBean("ldapAccessObject");
      // User erstellen...
      logger.error("TODO: Passwort pruefen!");
      LdapPerson ldapPerson = personDao.getPersonByUid(indexForm.getUid());
      User user = new User(indexForm.getUid(), indexForm.getPassword(), request.getRemoteAddr(), ldapPerson);
      // ... und in Session speichern
      session.setAttribute("user", user);
      LogLogic.createLog(hiberSession, user, Constants.LOG_LOGIN, "Login");
      ...
      Finally, my question is: Is this the best way to make the LDAP-Access available to my Actions, or are there other 'best practices'? Will the LDAP-Connection be pooled? Or is it better to obtain a BeanFactory in every Action?

      May thanks for your help in advance,
      Christian

      Comment


      • #4
        The best practice is to let Spring manage your application context files, even in a Struts application. The file that wires up your service layer beans (dao beans in your case) should be loaded by the Spring ContextLoaderListener. It's very easy to do. Your web.xml should contain this:

        Code:
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        ...
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring.cfg.xml</param-value>
        </context-param>
        With regards to the actions, there are a few ways to do it:

        1. Wire up your action beans in a separate application context file and load it using the Struts-specific ContextLoaderPlugIn. This will get the dao beans automatically injected into your actions. Imagine that your actions don't have to care how the PersonDao got there; it's just available for use:

        Code:
        public class MyAction extends Action {
           public void setPersonDao(PersonDao personDao) {
              this.personDao = personDao;
           }
        
           public ActionForward execute(...) {
              personDao.findByPrimaryKey(...);
              ...
        2. Subclass the Spring ActionSupport class instead of the Struts Action class and get hold of your beans using the getWebApplicationContext() method inherited form ActionSupport. It would look like this:

        Code:
        public class MyAction extends ActionSupport {
        
           public ActionForward execute(...) {
              WebApplicationContext ctx = getWebApplicationContext();
              PersonDao personDao = (PersonDao) ctx.getBean("ldapAccessObject");
              personDao.findByPrimaryKey(...);
              ...
        3. You can also manually get the application context using the utility class WebApplicationContextUtils. The code in your action would look like this:

        Code:
        public class MyAction extends Action {
        
           public ActionForward execute(...) {
              ServletContext servletContext = getServlet().getServletContext();
              WebApplicationContext ctx = 
                 WebApplicationContextUtils.getWebApplicationContext(servletContext);
              PersonDao personDao = (PersonDao) ctx.getBean("ldapAccessObject");
              personDao.findByPrimaryKey(...);
              ...
        I realize that you currently get the application context manually via your own custom Struts plugin. However, as described above, there is already support in Spring for loading, storing and providing the application context to a Struts application. You just need to choose the level of integration, since there are a few ways to do it. It's all described in section 15.4 in the Spring reference manual.

        Also, using the first alternative, you get the possibility to have your dao beans (and other beans) injected into your actions. That is something you can't do with your current solution.

        Your LDAP connections will be pooled correctly regardless of how you make your dao bean available to your action.

        Comment


        • #5
          Not much to add, but I found this article to be pretty useful.
          http://www-128.ibm.com/developerwork...ary/j-sr2.html

          Comment


          • #6
            Thank you...

            ... very much. As a longtime 'non-spring' programmer, the AOP and IOC-concepts are somewhat confusing or unusual to me - but i think i get the idea piece by piece...

            Thanks for your help.

            Regards,
            Christian

            Comment


            • #7
              It is all a little too much to take in at once. The great thing about Spring is you can introduce a little piece at a time. We used that approach previously over a period of weeks and it was very successful.

              Comment

              Working...
              X