"Bailey, Jeff A" wrote:

> [snip]
> Craig gave some pseudocode for an action class that had the perform method:
>
>         public interface Action {
>           public void perform(HttpServlet servlet, HttpServletRequest
> request, HttpServletResponse response)
>                 throws IOException, ServletException;
>         } // ends interface Action
>
> (thanks Craig)
>
> Now my questions are, what is the advantage is passing an HttpServlet
> object?  I understand HttpServletRequest and HttpServletResponse, but why
> HttpServlet?  Also, assuming you answer this, HOW do you pass this inside
> the servlet (sounds trivial but I have never tried any such thing)?
>

Passing the servlet means that you can get access to things in the servlet context
-- for example, a servlet context attribute -- from within the action class.  I do
this, for example, to access my database connection pool (this is inside an
action's perform() method):

    ConnectionPool pool =
      (ConnectionPool) servlet.getServletContext().getAttribute("pool");

I can also get an initialization parameter for the servlet itself.  It follows
through on my design principle:  "anything a servlet's service() method can do, the
action's perform() method should be able to do."  To do this, it needs access to
the same set of resources.

As to HOW you call it (from the controller servlet's doGet()/doPost() method?
That's actually quite simple:

    Action action = ...;    // Figure out which instance you want
    action.perform(this, request, response);

The "this" keyword in Java (and other O-O languages) is translated by the compiler
into an object reference to the object containing the method call you are making.
In this case (pun intended :-), it is the servlet instance of your controller
servlet.

>
> There was mention of 2 HashTables (or HashMaps) used in the controller
> Servlet.  If I am understanding correctly, the first maps the requestURI to
> the appropriate action class, and the second is used to store an instance of
> the appropriate action class?  So, in theory, you would grab the requestURI
> and look it up in the first HashTable.  Once the appropriate class is
> determined, you look for an instance of that class in the second HashTable?
> You would then call the perform method on that class (if it exists) or
> instantiate the class and call the perform method?  I have not worked a lot
> with dynamic class loading so a little help here would be greatly
> appreciated.  Maybe a little pseudocode to get me over the hump?

You've got the right idea.

Dynamic class loading (without fleshing out the error handling) looks like this:

    String actionClassName = ...;    // Whatever action class you need
    Class actionClass = Class.forName(actionClassName);
    Action action = (Action) actionClass.newInstance();

For this to work, your action class must have a zero-arguments constructor, or no
constructors at all.

>
> I had some concern about something craig mentioned in the brevity of his
> action classes (being 50 - 100 line mostly performing setXXX()).  In my
> servlet, I am doing all my setXXX() error checking where it seems you are
> performing this in the bean (or maybe I am just not writing as concise
> code?).  If this is the case, how do you know when the data is inappropriate
> for the field (ie, characters were found in a social security number?).  In
> my case, I do this checking in the servlet.  If an error has occured, I set
> the bean to an appropriate value (sometimes to null, and sometimes to the
> input value so that it can be easily modified by the user).  Otherwise I
> just set the bean property.  Could you go into a little more detail on this
> please?  As I mentioned earlier, it is hard to learn alternative design
> strategies when there are little to no examples to learn from =).

You have to know the right data types for your properties before you can even call
the right method, so it makes sense to do that conversion (say, string->integer) in
the action class before calling -- and catch the error there.

For semantic errors (does this integer field accept negative numbers?  is the
customer account number valid?) I prefer to do those checks inside the bean, and
throw an exception (usually IllegalArgumentException or IllegalStateException) if
the data has the right type, but is not valid according to the business rules.

If I'm just collecting form values (as opposed to updating a business object
directly), I do all of the property setting, and then call a validate() method in
the business bean.  Why?  So, in case there's an error, I can use this bean when I
redisplay the input form to show the user's last entered values (whether they were
valid or not) so he or she can just fix the ones that need to be changed.  This
behavior is expected by users of GUI applications, and there is no reason that web
apps shouldn't provide the same courtesy.

I wish I could show you complete examples, but the apps I've done this way are
proprietary, and I haven't yet had the opportunity to build an example (based on
this architecture) that I can share.  Maybe someday soon ...

>
> One more thing (as if this email isnt long enough). . . I read mention of
> using yet a public HashTable (or was it a method)? to determine which page
> the action class should forward to instead of hardcoding the value within
> the action class.  Is this really all that advantageous?  I like the idea of
> having logic names mapped to a specific file name, but otherwise, this seems
> to be overhead in projects that dont span hundreds of pages (or dont have
> the possibility of spanning that large).  I assume, in this strategy, the
> action class would lookup the logical name prior to forwarding to the .jsp
> refered to in the controller servlet?

I did my first Model 2 app without this kind of a mapping.  What happened to me is
that I later wanted to reassign all the "filename.jsp" names to a more natural
naming convention -- it was the kind of thing that happens occasionally as an
application grows over time.  Unfortunately, that meant had to go back and do
surgery on all of my action classes to correct these (of course, like a fool, I
used literal string values instead of constants in some shared object, so this was
pretty painful).  If I had had the logical mapping table, it would have been one
set of changes in one place to fix this.

Moral of the story -- some things that look like "overkill" in the initial design
really help you down the road, so they're worth building in at the beginning.

>
> I hope this all makes sense.
>
> Thanks to everyone for helping me in understanding some of these basic
> issues I am having.  I look forward to your replies :).
>
> Thanks
>
> Jeff
>

Craig

===========================================================================
To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff JSP-INTEREST".
Some relevant FAQs on JSP/Servlets can be found at:

 http://java.sun.com/products/jsp/faq.html
 http://www.esperanto.org.nz/jsp/jspfaq.html
 http://www.jguru.com/jguru/faq/faqpage.jsp?name=JSP
 http://www.jguru.com/jguru/faq/faqpage.jsp?name=Servlets

Reply via email to