Say we are writing a prototypical blogging web application. All blogging applications give authors the ability to edit a blog entry. One straightforward way to implement this is to check if logged user is the author of the blog and then displaying the edit link to the user like so:
Months later, say we decide that the administrator should also have the ability to edit blogs. We can add an 'or' condition to the if statement like so:<c:if test="${user == blog.author}">
<a href="/blog/233/edit">Edit Blog</a> </c:if>
The good developer, however, should see that we are going down the path of littering our JSP/HTML view with too much logic, which will ultimately become harder to test and less maintainable. The "right thing" to do is to push this logic to a middle tier.<c:if test="${user == blog.author || user.role == 'admin'}">
<a href="/blog/233/edit">Edit Blog</a> </c:if>
First, remove the if logic and replace it with the custom JSP tag "dm:feature" (to be created) like so:
Note the attribute name="blogEditing" which will effectively label the inside body as the blogEditing feature.<dm:feature name="blogEditing">
<a href="/blog/233/edit">Edit Blog</a> </dm:feature>
Second, create a custom JSP tag that will:
- Get a FeatureService object from your Spring web application context.
- Do a featureService.isEnabled(featureName) to determine whether the body should be evaluated or skipped.
context = (ApplicationContext)pageContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
PageContext.APPLICATION_SCOPE );
Third, create your FeatureService interface and implementation. In this example, the implementation would need to be aware of the current user and the current blog so you can do the check "if current user is the blog author." Leave a comment if you want more details.
This should dramatically reduce unnecessary logic in your view and make it more testable because you are pushing the logic into a middle-tier.
Keep in mind that this only eliminates blog editing from the view. You still need to disable the controllers/services for blog editing as well. This is where Spring's Aspect Oriented Programming comes in. Here's a brief outline of what you need to do:
- Create an @Feature annotation that requires feature name (e.g., @Feature("blogEditing"). This annotation will basically label methods as being part of a feature.
- Create a FeatureAspect bean with FeatureService as a dependency.
- Create an around advice (method in the FeatureAspect bean annotated with @Around). This advice should check if the feature specified in the @Feature is enabled. If enabled, execute the method. Otherwise, throw a runtime FeatureNotEnabledException and add top-level handlers to redirect user to a 403 unauthorized page.
Helpful? Let me know.
No comments:
Post a Comment