Announcement Announcement Module
Collapse
No announcement yet.
converting a client-server system to SpringMVC Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • converting a client-server system to SpringMVC

    I have been tasked with refactoring a Java Servlet that returns text information to a Swing based UI. The UI sends a request to the Servlet using URLConnection, then reads the response stream from the Servlet. I would like to use SpringMVC to do this refactoring but I have no idea if the communication scheme used by the UI would work with a SpringMVC controller that is returning a jsp that contains the text response.

    Here is the UI code (a lot of junk was edited out, so this is not actually working code):

    Code:
    URL dataURL = null;
    URLConnection urlConnection = null;
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1536);
    PrintWriter printWriter = new PrintWriter(byteStream, true); 
    
    try {
        dataURL = new URL(protocol, host, port, urlSuffix);
    } catch (MalformedURLException e1) {}
    
    try {
        urlConnection = dataURL.openConnection();
    } catch (IOException e2) {}
    
    urlConnection.setUseCaches(false); // ignore cached data
    urlConnection.setDoOutput(true); // set up the connection to do output to the server
    
    // 'print' the request to the byteStream that is wrapped by the PrintWriter
    printWriter.print(... the param string,e.g. "userId=some.user.id" );
    printWriter.flush();
    
    String lengthString = String.valueOf(byteStream.size());
    urlConnection.setRequestProperty("Content-Length", lengthString);
    urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
    
    try {
        byteStream.writeTo(urlConnection.getOutputStream()); // write the byte stream to the server
    } catch (IOException e3) {}
    
    printWriter.close();
    The UI reads the Servlet response with:
    Code:
    BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
    
        String line = null;
        try {
            while ((line = in.readLine()) != null) {
    When the Servlet receives the request it does:

    Code:
    PrintWriter out = response.getWriter();
    out.println(...get the string to return...);
    out.flush();
    My question is: can I do this with a SpringMVC controller and a JSP?

    The Spring code would be:

    Code:
    model.addAttribute("returnString", ...get the string to return... );
    return "SingleStringView";
    Where SingleStringView.jsp is just a single placeholder:

    Code:
    ${returnString}
    My concern is that the connection to the server opened by the UI is not the connection that Spring would use to deliver the response. I think this may be the case because I tried to send a request to the Servlet by just typing a legal URL into a browser. The request was processed by the Servlet but the browser popped up a 'save' window instead of displaying the expected result and there were zero bytes in the saved file.

    Thanks for any help or advice,
    bils

  • #2
    Spring MVC != JSP you can use whatever technology you like or implement your own!

    Not sure what all your requirements are but you could either implement your own HttpRequestHandler instead of your current servlet which lets you basically do the same as you do now in your servlet. You could also use a Controller but use your own view technology to write strings instead of selecting and rendering jsp.

    For a first step (and see it working) I probably would start with a HttpRequestHandler and then, if needed, move to controllers with a View implementation.

    Basically for the UI (Swing part) it doesn't matter what the backend technology is, it simply calls a URL and if that is a Servlet, Filter, Controller (or whatever) behind a DispatcherServlet it simply doesn't matter. So the only thing to change is the servlet. We can be of more help if you post the servlet and maybe some more code/web.xml which would give an insight into what you are actually trying to achieve.

    A final hint to get your spring setup right you could start with configuring the old servlet in spring and wrap it with a ServletWrappingController. That way you can have your spring setup first and then migrate to your new solution (more graduatly).
    Last edited by Marten Deinum; Dec 12th, 2012, 01:43 AM.

    Comment


    • #3
      Thanks for the reply, this is a follow up

      Martin,

      Thanks for the informative reply. Your summation of the situation answered my main question.

      Basically for the UI (Swing part) it doesn't matter what the backend technology is, it simply calls a URL and if that is a Servlet, Filter, Controller (or whatever) behind a DispatcherServlet it simply doesn't matter.

      I will try to restate what I think I need to do but I don't think posting the entire servlet would be of much use. It is over 4000 lines long and is basically a monolith with lots of globals and no consistency in the way things are coded making it VERY hard to read and understand in a short period of time. I do not think a ServletWrappingController is appropriate for this situation because all of the code in the Servlet needs to be completely refactored and the plan is to retire the old Servlet when the refactoring is completed.

      The original servlet is an if/elseif block with about 100 cases. 90% of the cases retrieve some data from the local db, do some simple formatting and return the data to the requestor by doing:

      Code:
       response.getWriter().println(...get the string to return...);
      All requests contains a 'command' parameter so a typical if/elsef case looks like:
      Code:
      else if (command.equals("VALIDATELOGIN")) {
      	String id = req.getParameter("id");
      	... see if the given id is currently logged in ...
      	if ( loggedIn )
      		resonse.getWriter().println("LOGGED IN") ;
      	else
      		response.getWriter().println("NOT LOGGED IN");
      The other 10% do some processing and dispatch to a jsp. My plan is to create a class for each command and inject a command factory into the controller or HttpRequestHandler that delivers the appropriate class for the incoming command. All URLs are the same up to the parameter list so a single Controller could be mapped to handle the 'front end' for all requests.

      If you need other info, such as web.xml, let me know and I'll find and post it.

      For the meantime let me ask a more focused question. If I use a Controller or HttpRequestHandler do I just use
      the same code (same as the original Servlet) in the controller to return the text response? By this I mean,
      Code:
      response.getWriter().println("LOGGED IN") ;
      Or would you recommend a Controller since dispatching to a jsp is also required for a few cases?

      Thanks for your help,
      bils

      Comment


      • #4
        Martin,
        I just put together a simple Controller to try using response.getWriter().println() and it worked fine with a test driver. I'll have to wait until tomorrow to try it on the existing Servlet but this is the first sign of progress and it feels great!

        I was wondering if there is a less wordy way to do: response.getWriter().println() from a controller or a view invoked by the controller.

        Thanks again for the help,
        -=b

        Comment


        • #5
          I do not think a ServletWrappingController is appropriate for this situation because all of the code in the Servlet needs to be completely refactored and the plan is to retire the old Servlet when the refactoring is completed.
          Why not. That way you can first fix your configuration (basically put the servlet behind the DispatcherServlet) and then slowly remove all the if/else elements from the old servlet to Controllers. That way you have a migration path and you can first fix your configuration.

          The other 10% do some processing and dispatch to a jsp. My plan is to create a class for each command and inject a command factory into the controller or HttpRequestHandler that delivers the appropriate class for the incoming command. All URLs are the same up to the parameter list so a single Controller could be mapped to handle the 'front end' for all requests.
          So you are basically planning on rewriting Spring MVC on top of Spring MVC. Why? Simply creaete a controller per command and let spring do the mapping... The PrintWriter can be injected into the request handling method (see sample below).

          Code:
          @Controller
          public class LoggedInController {
          
            @RequestMapping(params={"command=VALIDATELOGIN"}
            public void checkLoggedIn(@RequestParam("id") String id, PrintWriter writer) {
              // Check if logged in
              if (loggedIn ) {
                writer.println("LOGGED IN") ;
             } else {
               witer.println("NOT LOGGED IN");
             }
          }
          
          }
          However instead of using the writer I suggest writing a custom View which renders the view that way you have a nice decoupling.

          Code:
          public class TextView extends AbstractView {
          
              public static final String PARAMETER = "output-text";
          
              @Override
              protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
                  Object result = model.get(PARAMETER);
                  if (result != null && result instanceof String) {
                      ByteArrayOutputStream baos = createTemporaryOutputStream();
                      byte[] toWrite = ((String) result).getBytes();
                      baos.write(toWrite);
                      writeToResponse(response, baos);
                  }
              }
          
          }
          Then simply configure it and let a viewresolver do the work.

          Code:
          <bean id="textView" class="TextView" />
          
          <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" >
            <property name="order" value="1" />
          </bean>
          
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="order" value="1" />
            <property name="prefix" value=".jsp" />
            <property name="suffix" value="/WEB-INF/views/" />
          </bean>
          You could then rewirte the controller to something like this.

          Code:
          @Controller
          public class LoggedInController {
          
            @RequestMapping(params={"command=VALIDATELOGIN"}
            public String checkLoggedIn(@RequestParam("id") String id, Model model) {
              // Check if logged in
              if (loggedIn ) {
                model.put(PARAMETER, "LOGGED IN");
             } else {
                model.put(PARAMETER, "NOT LOGGED IN");
             }
             return "textView"; // The name of the view.
          }
          
          }
          This way you have a decoupling, controllers only process the request, prepare the model and select the view.

          Comment


          • #6
            martin,
            Thanks for doing the system design for me. You provided more than I ever imagined as an answer to my question. I was mulling what to do about the view situation and you provided all the code necessary.

            Thanks so much,
            bils

            Comment

            Working...
            X