Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / March 2008

Tip: Looking for answers? Try searching our database.

problem with MVC pattern

Thread view: 
K Gaur - 01 Mar 2008 05:57 GMT
hi everybody

i was trying this Model View Controller pattern but got stuck.

the servlet(EmailServlet_2) that is the controller looks like this:

_________________________________________________________________
package servpack;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import business.*;
import data.*;

public class EmailServlet_2 extends HttpServlet {

    public void doGet(HttpServletRequest request,HttpServletResponse
response)
        throws ServletException, IOException{
            String firstName=request.getParameter("firstName");
            String lastName=request.getParameter("lastName");
            String eID=request.getParameter("eID");
            String[] music=request.getParameterValues("music");

            //page forward control
            if((firstName.length()==0)||(lastName.length()==0)||
(eID.length()==0)){

                RequestDispatcher
dispatcher=getServletContext().getRequestDispatcher("/
get_missing_fields.jsp");
                dispatcher.forward(request,response);
            }
            else if(music[0].length()==0){
                RequestDispatcher
dispatcher=getServletContext().getRequestDispatcher("/
select_an_option.jsp");
                dispatcher.forward(request,response);
            }

            User user=new User(firstName, lastName, eID);
           UserIO.addRecord(user,"C:/Program Files/Apache Software
Foundation/Tomcat 6.0/webapps/m_egs/WEB-INF/etc/UserEmail.txt");

           RequestDispatcher
dispatcher=getServletContext().getRequestDispatcher("/
show_email_entry_2.jsp");
           dispatcher.forward(request,response);
    }

    public void doPost(HttpServletRequest request,HttpServletResponse
response)
        throws ServletException, IOException{
            doGet(request,response);
    }
}
___________________________________________________________________

the 'music' element is a list box.

when i fill all fields i.e. firstName, lastName and eID and when i
select
at least one option in 'music' list box the 'show_email_entry_2.jsp'
is called
(as it should be) and application works correctly.
but when i leave any of the 3 fields (firstName, lastName and eID)
empty,
rather than showing 'get_missing_fields.jsp' this shows up in browser:

_________________________________________________________________________________
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented
it from fulfilling this request.

exception

java.lang.IllegalStateException: Cannot forward after response has
been committed
    servpack.EmailServlet_2_ex6.doGet(EmailServlet_2_ex6.java:33)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

note The full stack trace of the root cause is available in the Apache
Tomcat/6.0.13 logs.
Apache Tomcat/6.0.13
_________________________________________________________________________________

also when all three fields (firstName, lastName and eID) are filled
but
no option in 'music' list box is selected then server returns this:

_________________________________________________________________________
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented
it from fulfilling this request.

exception

java.lang.NullPointerException
    servpack.EmailServlet_2_ex6.doGet(EmailServlet_2_ex6.java:24)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

note The full stack trace of the root cause is available in the Apache
Tomcat/6.0.13 logs.
Apache Tomcat/6.0.1
________________________________________________________________________

please tell me where i m wrong
Lew - 01 Mar 2008 12:50 GMT
>     public void doGet(HttpServletRequest request,HttpServletResponse
> response)
>         throws ServletException, IOException{
>             String firstName=request.getParameter("firstName");
>             String lastName=request.getParameter("lastName");

Please, please, please, please, please do not use TAB characters as the
indent-maker for Usenet listings.  Use a low number (up to four) of *spaces*
for each indent level.

> the 'music' element is a list box.

Thus when not filled out, sends an empty array or null array to the server.

> but when i [sic] leave any of the 3 fields (firstName, lastName and eID)
> empty,
> rather than showing 'get_missing_fields.jsp' this shows up in browser:
---
> java.lang.IllegalStateException: Cannot forward after response has
> been committed
[quoted text clipped - 4 lines]
> note The full stack trace of the root cause is available in the Apache
> Tomcat/6.0.13 logs.

And the root cause from those logs is what, exactly?

> _________________________________________________________________________________
>
[quoted text clipped - 14 lines]
>
> please tell me where i [sic] m [sic] wrong

You dereference music[0] without ever making sure that music != null and
music.length > 0.

Without the log message from the IllegalStateException I don't see why the
system thinks that you've already committed a response before the dispatch.

You should refactor your code so that the next view is calculated but the
dispatch doesn't happen until the end of the method.  Use if-then-else
patterns to reach a single point of dispatch, not multiple points, with the
view correctly selected into a String variable, then dispatch to that variable.

This was not an example of MVC.  You separated the view, but the model and
controller are still mixed.  Move model logic out into separate classes from
the controller.

Signature

Lew

K Gaur - 01 Mar 2008 18:11 GMT
> Please, please, please, please, please do not use TAB characters as the
> indent-maker for Usenet listings.  Use a low number (up to four) of *spaces*
> for each indent level.

thanks for advice, will see to it.

> > the 'music' element is a list box.
> Thus when not filled out, sends an empty array or null array to the server.
---
> And the root cause from those logs is what, exactly?
> Without the log message from the IllegalStateException I don't see why the
> system thinks that you've already committed a response before the dispatch.

sorry, the logs directory shows nothing listed in the file
'stderr_20080301.log'
which i([sic] or ![sic]) suppose should contain the error log referred
to by server as:
> > note The full stack trace of the root cause is available in the Apache
> > Tomcat/6.0.13 logs.

> You dereference music[0] without ever making sure that music != null and
> music.length > 0.

won't client side validation be required to do that.
couldn't figure out how to do that on server side.
what do you suggest?

> You should refactor your code so that the next view is calculated but the
> dispatch doesn't happen until the end of the method.

and how to do that? please elucidate.
Lew - 01 Mar 2008 19:47 GMT
Lew wrote:
>> You dereference music[0] without ever making sure that music != null and
>> music.length > 0.

> won't client side validation be required to do that.

No.

> couldn't figure out how to do that on server side.
> what do you suggest?

In the servlet code that says,

  else if(music[0].length()==0){

you add the test:

  else if ( music == null || music.length == 0 )
  {
    ...
  }
  else if(music[0].length()==0){

>> You should refactor your code so that the next view is calculated but the
>> dispatch doesn't happen until the end of the method.

> and how to do that? please elucidate.

The logic above, for example, could be placed in a validate() or isValid()
method of a Validator type implementor:

  public interface Validator
  {
    public boolean isValid( Map < String, String []> params );
  }

The controller would identify the source of the request from some
standardized, likely hidden form parameter:

<example>
 package controller;
 import ... ;
 public class Controller extends HttpServlet
 {
   private static final Map < String, Class< ? extends Validator>> validators
     = ControllerUtility.initializeValidators();

   protected void doPost(
     HttpServletRequest request,
     HttpServletResponse response )
   throws ServletException, IOException
  {
    doProcess( request, response );
  }

  private void doProcess(
     HttpServletRequest request,
     HttpServletResponse response )
   throws ServletException, IOException
  {
    String sourceView = request.getParameter( "sourceView" );
    Class< ? extends Validator> clazz = validators.get( sourceView );
    String destinView
    if ( clazz == null )
    {
      destinView = sourceView;
    }
    else
    {
     Validator validator = clazz.newInstance(); // try-catch needed
     destinView = ( validator == null? sourceView
          : ControllerUtility.lookupDestiny( sourceView,
                validator.isValid( request.getParameterMap() )
            ));
    }
    RequestDispatcher rd = request.getRequestDispatcher( destinView );
    rd.forward( request, response );
  }
 }
</example>

Except for the omitted try-catch on the reflection this is pretty much how a
complete controller will look.  Notice how the validation logic is completely
abstracted out of the controller.  To add model logic, insert a
model.execute() step between the validation and the determination of
'destinView' (or whatever *your* variable name is).  It uses the same pattern
- look up the mapping between outcomes and destination view based on the
configuration of the application.  This can even be through external files, as
in Struts or Java Server Faces (JSF).

Only the control pattern is in this code.  The actual logic is hidden behind
implementations of the Validator interface, and it would be similarly hidden
behind implementations of a ModelExecutor supertype.

  public interface Modeler
  {
    public static enum Outcome
    { SUCCESS, FAILURE, ERROR };
    public Outcome execute( Map < String, String []> parms );
    public Object getResult();
  }
  public abstract class ModelExecutor implements Modeler
  {
    // protected methods to provide scaffolding
  }

In the controller, you would add a
  ModelExecutor modeler = ControllerUtility.getModeler( sourceView );
  Modeler.Outcome outcome = modeler.execute( request.getParameterMap() );

and later
  request.setAttribute( "result", modeler.getResult() );

sometime before the rd.forward() call.

Thus your controller is actually quite brief, concerning itself solely with
matching validation and model logic with a source view, and likewise matching
a destination to the source and the outcome of its logic.  The view named in
"destinView" is the URL of a JSP, solely concerned with presentation of the
data in the request attribute "result" (or whatever you name it).  The logic
in the modeler instance does not care about the view, only how to get data
into an object that can be returned by getResult().  You have complete
separation of the M from the V from the C in MVC.

Signature

Lew



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.