Announcement Announcement Module
Collapse
No announcement yet.
Trading Complexity Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    I Agree

    Hi Justin,

    your absolutely right, my earlier rantings were fueled by sheer frustration. As I've probably said, some of the stuff is great. I particularly like the way jdbc is handled and the controller in it's simplest form is an improvement on using a servlet for the same purpose.

    looking forward to the book being released (April i think)

    Cheers,

    Mark

    Comment


    • #17
      Mark,

      A shameless plug, but you can buy Pro Spring right now if you want a comprehensive guide to Spring.

      Rob

      Comment


      • #18
        I have been trying to make up my mind on this very same issue myself.

        I am a fairly experienced Java programmer, but of course if I can use a framework to ease my work burden I will make use of it. The problem is that there just simply are so many Java frameworks that I am often more productive just writing something from scratch using the base API I know thoroughly than getting to know yet another framework.

        The problem with most frameworks is that as you generalize a task to make it easier, you also end up enforcing the framework's idea of how things should be accomplished. This means that if you stray from the beaten path, you at worst have to pretty much recode half the framework to get your idea through... the question becomes, is it even possible to raise the level of abstraction in frameworks so high that we could have genuine code reuse without becoming way too stiff in the way things are prescribed to be done?

        I have a few suggestions to all budding framework-builders: try to first of all be clear in the descriptions of what your framework seeks to accomplish so that people don't spend too much time on initial evaluation. Second, in documentation, do try to give an idea of the "philosophy" of the framework and how it all makes use of the base APIs. I have a feeling that Spring's documentation suffers too much from being a collection of trivial code snippets that you can cut and paste without enough background information of what exactly is going on. This results in a lot of trial and error experimentation when things don't work the way I thought they would.

        Simple code snippets might be a cool marketing pitch for beginner programmers, but it is my feeling that a beginning coder is a beginning coder even when given a framework. Worse yet, the beginner is going to be way out of his depth when he stumbles outside of the beaten path of the framework. Therefore, do not assume that frameworks are there to make life easier for the newbie. The more experienced programmer, however, expects documentation to tie into his former knowledge. I really would like to see documentation that more formally defines a lot of Spring concepts and walks through what they actually do under the hood so that there would be less need for experimentation. And yes, I have considered writing some docs myself of my experiences once I gain the level of Spring fluency that I am able to do that...

        That said, Spring looks better and better the more I get to know it. My time spent learning it has not been wasted, and I think it's about the biggest compliment I can give to its developers

        Comment


        • #19
          I came very close to giving up on Spring MVC out of frustration, but fortunately I had the time and experience to be able to get a better understanding of how it works. The more I use it and understand how it works, the happier I am with it. There is a lot of info in the API doc's, but very few people are going to bother trying to learn a framework from the API docs, the reason being that it does not present a comprehensible flow of information.

          The part I found hardest to come to grips with was how data is passed to/from controller, form and jsp. I eventually realized that spring beans are application context, and anything passed via ModelAndView is request context. As other people have mentioned in other threads, most web apps require that the app state be in the session context. If only this was clearly described somewhere in a tutorial!

          The solution I took is to wire up my "default application state" in the spring xml file, then deep-copy it into the session context where all the controllers can access it. The "default application state" defines the relationships between all the data in the webapp and the menu choices to be populated in the forms. It's necessary to deep copy otherwise your users will all be sharing the same application state, probably not what you want.

          Note that the deep copy technique I used requires all the classes being copied to implement the Serializable interface which may not be suitable for everyone. I've seen other ways of doing a similar thing in other threads that don't require Serializable, but this works and is a simple way of copying a "default application state" into the session context. It would be nice if Spring provided a standard way of copying a spring bean hierarchy into the session context.

          Here's a code snippet in case anyone's wondering how I did it.

          In the spring xml config file set a property containing your "default application state" (tableInfo in this example) in the front end controller (springappController):

          <bean id="urlMapping" class="org.springframework.web.servlet.handler.Sim pleUrlHandlerMapping">
          <property name="mappings">
          <props>
          <prop key="/login.htm">springappController</prop>
          <prop key="/selecttable.htm">tableselector</prop>
          ...
          </props>
          </property>
          </bean>

          <bean id="springappController" class="au.com.national.web.db.tools.SpringappContr oller">
          <property name="tableInfo"><ref bean="tableInfo"/></property>
          </bean>

          <bean id="tableselector" class="web.db.tools.TableSelector">
          <property name="sessionForm"><value>true</value></property>
          <property name="commandName"><value>tableForm</value></property>
          <property name="commandClass"><value>au.com.national.web.db. tools.TableForm</value></property>
          <property name="successView"><value>manipulatetable</value></property>
          <property name="formView"><value>choosetable</value></property>
          </bean>

          ...
          // and this is the "default" application state here, the referenced beans are ommitted for brevity

          <bean id="tableInfo" class="web.db.tools.TableInfo">
          <property name="tableContents"><ref bean="tableContents"/></property>
          <property name="tableForm"><ref bean="tableForm"/></property>
          <property name="operationForm"><ref bean="operationForm"/></property>
          <property name="rowForm"><ref bean="rowForm"/></property>
          <property name="db"><ref bean="dbInfo"/></property>
          <property name="dbEditor"><ref bean="dbEditor"/></property>
          </bean>

          Here's the code for the front end controller that does the deep copy into the session context.

          import org.springframework.web.servlet.mvc.Controller;
          import org.springframework.web.servlet.ModelAndView;
          import org.springframework.web.servlet.view.RedirectView;

          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.*;
          import java.util.HashMap;
          import java.util.Map;

          import org.apache.commons.logging.LogFactory;

          public class SpringappController implements Controller {

          private TableInfo tableInfo;

          public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException, ClassNotFoundException
          {

          // put a copy of the tableInfo into the session
          if (tableInfo != null)
          {
          LogFactory.getLog(getClass()).info("put tableInfo into session " + request.getSession().getId());
          TableInfo sessionTableInfo = (TableInfo)makeDeepCopy(tableInfo);
          request.getSession().setAttribute("tableInfo", sessionTableInfo);

          request.getSession().setAttribute("tableContents", sessionTableInfo.getTableContents());
          request.getSession().setAttribute("operationForm", sessionTableInfo.getOperationForm());
          request.getSession().setAttribute("tableForm", sessionTableInfo.getTableForm());
          request.getSession().setAttribute("rowForm", sessionTableInfo.getRowForm());
          request.getSession().setAttribute("db", sessionTableInfo.getDb());
          }

          return new ModelAndView(new RedirectView("selecttable.htm"));
          }

          public void setTableInfo(TableInfo tableInfo)
          {
          this.tableInfo = tableInfo;
          }

          static public Object makeDeepCopy(Serializable obj2DeepCopy) throws IOException, ClassNotFoundException
          {
          // note: obj2DeepCopy must be serializable
          ObjectOutputStream outStream = null;
          ObjectInputStream inStream = null;
          try
          {
          ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
          outStream = new ObjectOutputStream(byteOut);
          // serialize and write obj2DeepCopy to byteOut
          outStream.writeObject(obj2DeepCopy);
          //always flush your stream
          outStream.flush();
          ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
          inStream = new ObjectInputStream(byteIn);

          // read the serialized, and deep copied, object and return it
          return inStream.readObject();
          }
          finally
          {
          // always close your streams in finally clauses
          try {
          outStream.close();
          inStream.close();
          } catch (Throwable t) {}
          }
          }
          }

          package web.db.tools;

          import org.springframework.web.servlet.mvc.SimpleFormCont roller;
          import org.springframework.web.servlet.ModelAndView;
          import org.springframework.validation.BindException;
          import org.apache.commons.logging.LogFactory;

          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.sql.SQLException;
          import java.util.HashMap;
          import java.util.Map;

          /**
          * Controller servlet which accepts user requests and dispatches responses to destination JSP's..
          */
          public class TableSelector extends SimpleFormController
          {
          private TableInfo tableInfo;

          protected Object formBackingObject(HttpServletRequest request)
          {
          LogFactory.getLog(getClass()).info("get tableForm");
          tableInfo = (TableInfo)request.getSession().getAttribute("tabl eInfo");
          return tableInfo.getTableForm();
          }

          protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors)
          throws Exception
          {
          LogFactory.getLog(getClass()).info("validate tableForm");
          try
          {
          TableForm tableForm = (TableForm)command;
          tableForm.setOrderBy("");
          LogFactory.getLog(getClass()).info("table is " + tableForm.getTable());
          LogFactory.getLog(getClass()).info("where is " + tableForm.getWhere());
          LogFactory.getLog(getClass()).info("user is " + tableInfo.getDb().getUser());
          tableInfo.getTableContents().load();
          }
          catch (SQLException e)
          {
          LogFactory.getLog(getClass()).info(e.getClass() + ": " + e.getMessage() + ": no tableInfo");
          errors.reject("error.load-error", "Unable to load table data, is where clause valid? " + e.getClass().getName() + ": " + e.getMessage());
          }
          }

          /**
          * Process incoming requests for information
          * @param request Object that encapsulates the request to the servlet
          * @param response Object that encapsulates the response from the servlet
          */
          public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
          BindException errors) throws Exception
          {
          LogFactory.getLog(getClass()).info("submit to manipulatetable");

          Map model = new HashMap();
          model.put("tableForm", tableInfo.getTableForm());
          model.put("operationForm", tableInfo.getOperationForm());
          return new ModelAndView(getSuccessView(), model);
          }
          }

          Finally, some JSP to complete the example

          <spring:bind path="tableForm.table">
          <select name="<c:out value="${status.expression}"/>">
          <option value='NONE'>----------</option>
          <c:forEach items="${tableForm.tables}" var="table">
          <option value="<c:out value="${table}"/>">
          <c:out value="${table}"/>
          </option>
          </c:forEach>
          </select>
          </spring:bind>

          Comment


          • #20
            Originally posted by huckfinn
            I have a few suggestions to all budding framework-builders: try to first of all be clear in the descriptions of what your framework seeks to accomplish so that people don't spend too much time on initial evaluation. Second, in documentation, do try to give an idea of the "philosophy" of the framework and how it all makes use of the base APIs. I have a feeling that Spring's documentation suffers too much from being a collection of trivial code snippets that you can cut and paste without enough background information of what exactly is going on. This results in a lot of trial and error experimentation when things don't work the way I thought they would.
            I do agree that to a certain extent that the MVC documentation is a bit sketchy. But i think for Spring, Rod did a wonderful job of laying out what Spring is all about and what problems it solves. He did all that in his 1st book, Expert 1-on-1 J2EE design and Development, which explain the major design decisions that underpin Spring today. The major parts of the MVC for the interface21 framework(which evolved into Spring) are fully explained. I regard that book to be the best from Rod and the best in J2EE i've ever read.

            OTOH i've ordered Pro Spring from amazon UK and for some strange reason they couldn't deliver it and i re-placed the order about 2 weeks ago and they havent yet dispatched it :x

            Comment

            Working...
            X