Sample Application
The sample application is available in the Beta 0.6.0.0 release of Lattis. It's
a very simple application and is far away from being a real project. However, it
demonstrates the principles of using Lattis framework.
Lattis is inspired in Struts,
a very successfull Java framework for
building Web applications. Those who have worked with Struts
don't even need to take a look at this brief explanation, just donwload the sample
application and start taking a look at the source. The similarities to Struts can
be easily observed.
Microsoft .NET framewok has both a nice object model and a powerful event handling
structure. Thus, when using Lattis, the final result is something very close to what
the JSF (Java Server Faces) technology proposes.
Developers who has also worked with JSF
shouldn't have any problems understanding Lattis philosophy neither.
If you have not worked with Struts or
JSF, it doesn't matter,
it will still be very easy to learn how to use Lattis. Download the sample application
from SourceForge
and let's try to undesrtand it.
A very important piece of Lattis is a user created configuration file called
Application.config. This file should be located at the application's root directory.
We will first examine the Actions-Config element in Application.config.
This element may have inner elements called Action-Config, which
represent the actions that should be taken when a request identified by its
Path attribute hits the web server. You also need to configure what class is
reponsible for handling the specified action, it's done using the attribute Class.
Naturally, as we're working in the .NET enviroment, you can't forget to tell Application.config
the assembly name where your classes are located, that's the reason of the Assembly
attribute.
The action class specified to handle the request must inherit either from Lattis.Control.Action
or Lattis.Control.LookupAction. If the class inherits from Lattis.Control.Action it must
override its Execute() method to determine the desired behaviour. On the other hand, if the
class inherits from Lattis.Control.LookupAction, it must have a method with the same
name of a value kept under a query string key used to reach this action. The key
under you should place the name of the method to be invoked is specified by the
MethodKey attribute of the Action-Config element. Naturally, this method, as the Execute()
method in the other case, is responsible for your business logic.
Take a look in Application.config file of the sample application and you'll see
examples of the two approaches mentioned above. Just to make sure, I'm placing them right here.
...
<!-- Typical and simple Action configuration. -->
<Action-Config
Path="ActionDoMyStuff1.aspx"
Class="LattisSampleApp.Actions.ActionDoMyStuff1"
Assembly="LattisSampleApp">
...
...
...
</Action-Config>
<!-- Typical LookupAction configuration. -->
<Action-Config
Path="ActionDoMyStuff2.aspx"
Class="LattisSampleApp.Actions.ActionDoMyStuff2"
Assembly="LattisSampleApp"
MethodKey="op">
...
...
...
</Action-Config>
...
Inside Action-Config element is possible to configure two other elements.
They're Forwards-Config, which keeps Forward-Config inner elements and
Exceptions-Config, which keeps Exception-Config inner elements. We'll take
a look at them later. First let's examine a little of the action classes.
As mentioned earlier, the action classes are responsible for handling the business logic
of the request. This can be accessing façades, legacy systems, persistence
mechanisms, etc. It's important to note though that these classes must inherit from
either Lattis.Control.Action or Lattis.Control.LookupAction. If an action
class inherits from Lattis.Control.Action, it must override its execute method
and would look something like class ActionDoMyStuff1 from the sample application.
...
public class ActionDoMyStuff1: Lattis.Control.Action
{
override protected ActionForward Execute(HttpContext context)
{
try
{
// do the job here...
return this.FindForward("Success");
}
catch(Exception)
{
// do logging or anyother thing.
}
// if it gets here, something went wrong, so return failure.
return this.FindForward("Failure");
}
}
...
When an action class extends Lattis.Control.LookupAction it doesn't need to
override its Execute() method, actually, it shouldn't do so. Extending
Lattis.Control.LookupAction means that that you could place how many methods you'd
want in the action class and the decision of which method should be invoked will be
based on a query string parameter. The query string parameter must have the same
name you specified for the attribute MethodKey in the action configuration
element. Class ActionDoMyStuff2 from the sample application extends from
Lattis.Control.LookupAction. Here's a snippet.
...
public class ActionDoMyStuff2: LookupAction
{
protected ActionForward Method_A(HttpContext context)
{
string inputData = context.Request.Form["TextBox1"];
// do some job using input data.
return this.FindForward("Method_A_Success");
}
protected ActionForward Method_B(HttpContext context)
{
return this.FindForward("Global");
}
}
...
There's still another rule that action classes must follow: They always have to
return an Lattis.Control.ActionForward instance. This can be achieved by using
the FindForward() method present in Lattis.Control.Action. That's exactly
where we come back to Application.config file and identify all the Forward-Config
elements. Forward-Config tell the framework information about the destiny of
the request. Usually, you'd have two diferent destinies for a request, one
to be called when something goes wrong and the other one to be called when a successful
operation has happened.
FindForward() method expects one parameter which is the name of the Forward-Config
element to be used by this request. Naturally, the name of the Forward-Config is
specified by the attribute Name and the path related to this name is specified
by the attribute Path. Optionally, you can also tell the framework if the request
should be redirected or just transfered to the configured path. This can be done using the
Redirect attribute - default behaviour is a transfer.
When an action class uses the FindForward() method to determine the request's destiny, Lattis
will first look if there's a local Forward-Config element with the name passed
to the method. If it doesn't find a Forward-Config with this name, it will search
global Forward-Config elements. The same behaviour is used with Exception-Config
elements.
Exception-Config elements must be configured with at least two attributes:
An exception class and a path. This information is represented respectively by the
attributes Class and Path. Basically, here's what you need to learn about
Exception-Config. If any exception is raised during the execution of your action
class, Lattis will search all local and global Exception-Config elements in Application.config
to verify if there's a map for the exception type that has been raised. If it finds any, the
request will be transferred to the path specified in Exception-Config element.
If it doesn't find a match for the exception, it's just propagated as usual.
Now that you have a better idea of how Lattis works, it'll be pretty easy to understand
the sample application and adapt your projects to this paradigm (if you liked it, of course).
I'm planning on developing other features for Lattis, like a nice validation structure (I'm not
very happy with .NET's default one) and a page template system. Also, I'd like to
work a little more on the documentation and in a sample application a bit closer to
reality. Naturally, if you have doubts, questions and opinions, feel free to
post it in Lattis Forum
or Mailing List.
|