David's concerns are quite valid -- one of the implications of the architecture
I propose is that the servlet containing the business logic (essentially the "C"
in an MVC architecture) has to select processing logic (i.e. specific Java
classes) and the subsequent presentation logic (i.e. the URL of the JSP page to
be forwarded to), without hard coding the set of possible selections. I'm going
to briefly describe the approaches I use to deal with these issues, and a couple
of alternative approaches that seem to make sense as well. (By the way, the
same issues apply in a JSP-Bean-EJB type architecture -- they are just factored
differently).
SELECTING THE PROCESSING LOGIC
The proposed architecture has a servlet receiving the input from every form. It
can make a decision of where to go next based on the request URI that was
received, the request parameters, and/or current state information from the
user's session.
What I have generally done is used a single servlet per application, mapped to a
filename extension like ".go" (I like this because it implies "go and do
something with my answer). So, l have the following sorts of logical business
function names, all mapped to the same servlet:
* customerList.go (accepts filter criteria
and selects a bunch of customers)
* saveOrder.go (validates the input fields
on the order that the user is working on,
and saves it to the database.
* logoff.go (logs the user out of the app)
So, how do we call the appropriate processing logic? The hard coded approach
might look like this:
String servletPath = request.getServletPath();
if (servletPath.equals("customerList.go"))
doCustomerList(request, response);
else if (servletPath.equals("saveOrder.go"))
doSaveOrder(requset, response);
...
but this is pretty obviously undesireable, because you have to modify and
recompile the servlet every time you add a new processing function. Instead, I
use the following approach:
* Use servlet initialization parameters to build
a hashtable where the key is the logical function
name (i.e. "customerList.go" or "saveOrder.go")
and the value is the name of a Java class that will
contain the processing logic for this function.
* Each processing logic class implements an
interface called Action:
public interface Action {
public void perform(HttpServlet servlet,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
}
* The first time that a particular action is
requested, I dynamically load a new class
(the name is selected by the hashtable
described above) and then create a new
instance of that class. Dynamic class
loading like this is the single coolest
thing about Java :-).
* Subsequent requests for the same action
will reuse the same object, because I save
them in the servlet. This avoids the overhead
of instantiating a new action object on every
request.
* A side effect of this is that action classes have
to be coded with multi-thread safety in mind,
and can contain no local state information.
They should use only method arguments and
local variables, and save any required state
information in the user's session.
In my applications, it has always been sufficient to initialize the mapping
table (request URI to Java class name) in the init() method. A workflow
environment might support mechanisms to modify the mapping dynamically, or allow
a particular user to customize the mappings by keeping a mapping table in their
session. (For example, you could even synthesize a new Java source file for a
new application function, compile it on the fly, and add a new mapping
automatically.) But the key feature is that the foundational logic in the
servlet has no need to have any knowledge of the various action methods hard
coded -- it's all initialized at run time.
If you wanted to get really fancy, you could even support dynamic class loading
for your action methods, so that you can update them on the fly (the way that
some servlet engines support automatic reloading when a class file changes)
without restarting the server ...
SELECTING THE PRESENTATION LOGIC
The same basic concept can be used to map "logical" presentation names ("Display
Customer List") to particular JSP pages ("/displayCustomers.jsp"). Doing this
lets you keep your action procedures reasonably independent of the actual URIs
of the JSP pages.
For the complex workflow issues, I don't feel so bad about using scriptlets to
embed conditionals (if this is not the last page in the workflow chain, generate
a "Next" button). I can rationalize this by saying "but this is really
*presentation* logic" :-). However, I plan to migrate to using
application-specific custom tag extensions for this sort of thing, because the
custom tag can incorporate as much state knowledge as it needs to know what to
create.
Essentially, the custom tag extension becomes a Java component that generates
HTML, rather than a Java component that contains data or processing logic
(<jsp:useBean>). I can easily conceive of a <NextPage/> custom tag that knows
how to do this right, and hides all the messy conditional logic from the page
designer.
Craig McClanahan
David Chisholm wrote:
> I agree that the approach described by Craig is the preferred approach, but
> the issue that I have with it in our application occurs with workflows. Not
> unlike many others I'm sure, we are delivering a UI via the web that in the
> past would have been a standalone application UI, and to do this requires
> that you take a step back in technology to accommodate the limitations of
> web servers and especially browsers.
>
> Part of what we do requires complicated workflows in which the user must
> traverse multiple pages to accomplish a task(s). The workflows are complex
> in that they may branch, subsets of them may be re-used within other
> workflows, and sometimes one workflow may bridge to another workflow (for
> example, a search workflow target may be the same as the target of a
> drill-down workflow).
>
> So the issue that I have with the page->servlet->bean->page design is that
> the servlet must support these workflows by directing requests to the
> appropriate bean based on the client's current workflow state. The only
> information that the servlet has available to direct the request is the data
> in the request itself, so the servlet has to do some kind of
> string-parameter to bean-class mapping to direct the request to the
> appropriate bean. Given that I'm used to developing a standalone
> application UI where I could fire events that would easily manage this, the
> mapping seems very kludgy to me. You don't want to hard-code it, but if you
> create some additional framework to make it configurable, you run the risk
> of a runtime mapping error. Oh, did I mention that our framework has to
> support users customizing and/or extending existing workflows and even
> creating their own new workflows?
>
> Assuming that a bean can handle workflow specific logic for a particular
> workflow, all the servlet need do is map a workflow name to a workflow bean.
> Then the rest of the framework is responsible for inserting the appropriate
> state information (e.g, workflow name) into subsequent requests. This still
> has the problem I mentioned above.
>
> The other issue is re-using pages within different branching workflows. In
> some workflows, a page would have a 'Next' link to go to the next page in
> the workflow, and in others the same page would be the final page in a
> workflow. You could easily create separate pages for each workflow, but I
> would prefer to avoid the maintenance problems that this would cause. So
> the framework has to support generating pages based on the context of the
> workflow. However the JSP pages are where this logic has to be applied, and
> I don't want to use scriptlets in the page to do this. I'm hoping that tag
> extensions will be a clean way of separating this logic from the page.
>
> Either there's better mechanism for supporting the workflow name mapping, or
> I'm just gonna have to live with it.
> David
>
> ----- Original Message -----
> From: Craig R. McClanahan <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Wednesday, November 24, 1999 10:16 AM
> Subject: Re: Which Architecture..?
>
> > sdheepa wrote:
> >
> > > Just look at the Foll. Architecture:
> > >
> > > JSP File ->Contacting Servlet-> This Servlet in
> > > turn talks with EJB to perform bussiness logic...
> > >
> > > What are the advantages/diadvantages of having the
> > > Servlet to contact the EJB..with repect to performance
> > > and scalability...
> > >
> > > Instead of having the servlet contact the EJB why not
> > > we have the Java Bean talk to the EJB..
> > >
> > > ie what problems we might face if the architecture is
> > > like this:
> > > JSP File ->Contacting Java Bean-> This Bean in turn
> > > talks with EJB to perform bussiness logic...
> > >
> >
> > The issue I have with this approach is not performance or scalability --
> there
> > will not be any significant differences here, because (as many have
> pointed out)
> > JSPs get turned in to servlets anyway. Rather, what I am concerned about
> is
> > maintainability and code re-use.
> >
> > Using a JSP-Bean-EJB architecture (instead of my preference, which is
> actually
> > JSP->Servlet-Bean/EJB->JSP) is that you have to embed your procedural
> business
> > logic *inside* your JSP page. This ties the two things together so that
> you
> > cannot change one without at least affecting the other.
> >
> > Instead, I prefer to segregate all my business logic (but zero HTML
> generation)
> > into servlets, which can use EJBs when appropriate or other techniques
> (such as
> > direct JDBC access) when EJBs are not necessary. I use beans to
> communicate the
> > processing results back to an appropriate JSP page for display, using
> > RequestDispatcher.forward() to transfer control.
> >
> > Just as an example of the kinds of things that happens to applications
> during
> > their lifetime, consider that you've built a nice transactional web
> application
> > for browsers, using HTML for the presentation. Now, your company decides
> to build
> > a version of this application for a wireless device, using WDML instead of
> HTML
> > (this is perfectly feasible with JSP and servlets). If you've separated
> the
> > business logic as I suggest, you've got a pretty good chance at being able
> to
> > reuse most or all of it. If you've embedded your business logic in the
> HTML code
> > in a JSP page, you're going to have to duplicate it, and maintain two
> versions
> > "forever".
> >
> > >
> > > Other than multi-threading do we have any other
> > > addtional adv. if we use Servlets..?
> > >
> >
> > On larger scale (multi-developer) projects, the separated approach also
> allows you
> > to devote Java programmers to the business logic side, and user interface
> > developers to the JSP side. They can work reasonably independently of
> each other,
> > once the bean interfaces are agreed upon, without stepping on each other's
> changes
> > to the same source files.
> >
> > >
> > > Can someone help me..?
> > >
> > > Thanks in advance..
> > > Dheepa
> > >
> >
> > Craig McClanahan
> >
> >
> ===========================================================================
> > To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff
> JSP-INTEREST".
> > FAQs on JSP can be found at:
> > http://java.sun.com/products/jsp/faq.html
> > http://www.esperanto.org.nz/jsp/jspfaq.html
> >
===========================================================================
To unsubscribe: mailto [EMAIL PROTECTED] with body: "signoff JSP-INTEREST".
FAQs on JSP can be found at:
http://java.sun.com/products/jsp/faq.html
http://www.esperanto.org.nz/jsp/jspfaq.html