Great people like Ron Bodkin talk about the pragmatic way of doing software. So why don't me, when I have this experience and I'm just hot to tell the world to look at the other side of this matrix..
Ilybra is a battlefield when it comes to aspects. Ther first aspect was tracing of course, the rest you see below, and today I got an idea on another one to my collection. Some people will even call my aspects "enterprise"! As you wish :) I don't know the meaning of that word. I just develop an application for my library ladies.. ;)
Like it was said in the Ilybra: introduction, Ilybra utilizes some custom made aspects. They are:
I will demonstrate you my Struts' action code with: tracing, authorization, persistence, returning empty String instead of null, resetting forms and measuring time of invocation of action - ufff, a lot :) :
My full, original code (without any cheating or removal lines of code for the
sake of the presentation of the example) of user story: Prolong copy on
reader's account: enter new date, accept choice, view confirmation.
Note: of course, there exists one, additional, global
ilybra-aop.xml AOP configuration file for defining pointcuts.
public class ProlongCopy
extends IlybraAction
{
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
{
BookForm bookForm = (BookForm) form;
String prolongDate = bookForm.getReturnDate();
Library library = getWorld().getLibrary(); //the first reason for
//the base IlybraAction class
Copy copy = library.getCopies().getCopyById(
bookForm.getCopyId()
);
Utils.notNullAssertion("Copy: ", copy);
//I wait for this to become an aspect :)
library.prolongCopy(copy, Dates.someDateByString(prolongDate));
saveOneMessage(request, "message.prolong.change.success",
copy.getSignature());
//second reason for IlybraAction
return mapping.findForward("success");
}
}
/** @@pat.transaction */ public void prolongCopy(Copy copy, DateRepresentation newReturnDate) { copy.returnDate = newReturnDate; } public Copy getCopyById(Long id) { return (Copy) copies.get(id); //copies is java.util.Map }
..Authorization and authentification are common in applications. And so it is with Ilybra. It is 2 years now, I started to work on the application, but only from the last week the system must authorize a reader to access his account.
What is important here I've managed to add this concern - orthogonal concern - after the application was finished. I've done it with one simple aspect listening on all Struts actions, which checks if there is a User object in a session. Implementation is trivial. And aspect oriented way turned out to work. (This implementation could also be done using "servlet's filters", as they also crosscut expected behaviour in this particular example).
Code of the aspect on the plate:
<bind pointcut="execution(* $instanceof{Action}->execute(*))"
cflow="(notInLoginAction AND notInLogoutAction)">
<advice aspect="AuthorizingAspect" name="checkUserLoggedIn"/>
</bind>
public class AuthorizingAspect
{
public Object checkUserLoggedIn(Invocation invocation)
throws Throwable
{
MethodInvocation mi = (MethodInvocation) invocation;
ActionMapping mapping = (ActionMapping) mi.getArguments()[0];
HttpServletRequest request = (HttpServletRequest) mi.getArguments()[2];
User sessionUser = getUserFromSession(request);
String servletPath = request.getServletPath();
if (servletPath.startsWith("/anonymous/"))
{
return letThrough_becauseAnonymousCall(invocation);
}
if (null == sessionUser)
{
storeUserRequestInSession(request, mapping);
return redirectToLoginPage(mapping);
}
else
{
if (userIsAuthorizedToAction(servletPath, sessionUser))
return letThrough_becauseIsAuthorized(invocation, sessionUser);
else
return redirectToHomePage(mapping, sessionUser);
}
}
private ....
}
I hope those examplets will clear your mind for a moment :)
Take care,
Tomasz Nazar
Interested in How do I test the Ilybra application with aspects applied?"