struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Lukasz Lenart <lukaszlen...@apache.org>
Subject Re: [Idea] Add ability for decorator pattern in Actions
Date Tue, 16 Jul 2013 10:09:25 GMT
2013/7/12 Miguel Almeida <miguel@almeida.at>:
> I'd like to discuss with you an idea that came up a while ago while
> trying to fulfil this need:
>
> As a developer
> I want to unit test annotations in my actions without having to run the
> method's body
> So that I can TDD more effectively and have quicker unit tests.
>
> Namely, imagine an action:
>
> @SecuredRoles("admin")
> public String adminStuff(){
> ...
> }
>
> It would be interesting to have a way to test the @SecuredRoles without
> having to run the method's body.
>
> Upon discussion within the TDD group, a nice solution was suggested (in
> italic. Skip below for my comments regarding Struts) :
>
> So I would test and implement each aspect in isolation of the other -
> the authorization would be implemented as a decorator (a-la GoF
> decorator pattern) adding authorization to the underlaying (decorated)
> MVC app. BTW I got to this technique by TDDing the separate aspects
> (this is a good example of where the tests drive the design).
>
> The technique to getting there is quite simple:
> 1. Extract an interface from your main class with all the public methods
>
> 2. Implement a decorator which adds authorization rules to a decorated
> underlaying object. The decorator can implement the authorization rules
> using your annotations (see this is where the academic meets the
> practical - you'll in fact be reusing the already existing interceptor
> but adapting it to a test-driven architecture)
>
> 3. in your tests, test the decorator providing a mock underlaying
> decorated object, asserting in each test that given a request with a
> user that has certain roles the underlaying method should or should not
> be called.
>
> The code might end up like this (semi-pseudo code but you get the idea)
>
>
> Tests:
>
> test_admin_can_call_method_a()
> {
> // setup a fake request with admin role:
> httpRequest = buildRequestWithRole("admin");
>
> // setup a mock app decorated with an authorzation decorator:
> MockApp app = new MockApp();
> AuthorizationDecorator authorizer = new AuthorizationDecorator(app);
>
> // act - try calling method A in the decorator:
> authorizer.MethodA(httpRequest);
>
> // assert - underlaying method a should have been called:
> Assert(app.MethodA.WasCalled==true);
> }
>
> test_regularUser_cannot_call_method_a()
> {
> // setup a fake request with regular user role:
> httpRequest = buildRequestWithRole("regular user");
>
> // setup a mock app decorated with an authorzation decorator:
> MockApp app = new MockApp();
> AuthorizationDecorator authorizer = new AuthorizationDecorator(app);
>
> // act - try calling method A in the decorator:
> authorizer.MethodA(httpRequest);
>
> // assert - underlaying method a should not have been called:
> Assert(app.MethodA.WasCalled==false);
> }
>
>
>
> In the SUT:
>
> interface IApp
> {
> void MethodA()
> void MethodB()
> ...
> }
>
> // this is the real app implementing methodA, methodB etc
> class RealApp : IApp
> {
> void MethodA()
> void MethodB()
> ...
> }
>
> // this is responsible for authorization
> class AuthorizingDecorator : IApp
> {
> private IApp _decorated;
> public AuthorizationDecorator(IApp decorated)
> {
> _decorated = decorated;
> }
>
> // each method is implemented using annotations
> // and calling the underlaying decorated object
> @SecuredRoles("admin, manager")
> public void MethodA()
> {
> _decorated.MethodA();
> }
>
>
>
> @SecuredRoles("regular user")
> public void MethodB()
> {
> _decorated.MethodB();
> }
> }
>
> Then in your final MVC application you'd wire up the decorator with the
> RealApp object:
>
> IApp app = new AuthorizingDecorator(new RealApp());
>
>
>
> This design is incompatible with Struts2 - if you decorate
> DecoratedAction with OriginalAction, all Struts-related things (e.g.
> ParamsInterceptor populating Action's fields from request, and I assume
> every other interceptor's behaviour as well) will no work on
> DecoratedAction, because it doesn't extend OriginalAction but rather
> delegates to OriginalAction. E.g, a "someRequestParam" would be
> populated OriginalAction if it was in the request, but it won't populate
> originalAction.someRequestParam in DecoratedAction.
>
> It would be very interesting to support the Decorator Pattern in Struts
> actions. What are your thoughts on it?

Is it similar to ModelDriven?

The problem I see is how to distinguish when to call decorator and
when decorated object.


Regards
-- 
Ɓukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message