Can we use the decorator pattern in Actions?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Can we use the decorator pattern in Actions?

wild_oscar
Imagine the scenario where you have security implemented at the action
method level with an annotation:

@Secured("someRole") restricts that action to that role (and it is
checked with an interceptor).

Discussing this on the TDD mailing list a while back, a decorator
approach was suggested

To separate concerns and ease up testing, authorization is implemented
as a decorator (a-la GoF decorator pattern) adding authorization to the
underlying (decorated) MVC app.

The technique to getting there (see pseudo code in [1])
1. Extract an interface from your main class with all the public methods
2. Implement a decorator which adds authorization rules to a decorated
underlying object. The decorator implements the authorization rules
using annotations
3. in your tests, test the decorator providing a mock underlying
decorated object, asserting in each test that given a request with a
user that has certain roles the underlying method should or should not
be called.


As you see, tests would have a simple setup as you wouldn't be calling
"the real, possible complicated action code", but the fake decorated
one.
The problem arises when you have superclasses (and maybe also when you
implement interfaces). I exemplify with both.

Imagine this:
RealAction extends CommonAction implements IAction(){
...}

CommonAction implements ServletRequestAware(){
...
}

AuthorizingDecorator implements IAction(){
//injected decorated IAction, see [1]
...
}

Now, on a regular RealAction implementation, the request object exists:
RealAction extends CommonAction, so the request is injected through its
ServletRequestAware.
If you're using the AuthorizingDecorator, however, the request will be
null: RealAction will be injected, so Struts won't kick in to populate
RealAction's request object.


My question is: how would you go on and solve this? Or is the decorator
approach impractical in Struts? I haven't even consider the necessity to
implement every getter/setter on the IAction, which would also make this
approach a bit cumbersome. The simplicity for testing, however, is
great!

Cheers,

Miguel Almeida


[1] The code might end up like this (semi-pseudo code)

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 IAction
{

        String MethodA()
        String MethodB()
        ...

}

// this is the real action implementing methodA, methodB etc
class RealAction: IAction
{

        String MethodA()
        String MethodB()
        ...

}

// this is responsible for authorization
class AuthorizingDecoratorAction : IAction
{

        private IAction _decorated;
        public AuthorizationDecorator(IAction decorated)
        {
        _decorated = decorated;
        }
       
        // each method is implemented using annotations and calling the
        underlying decorated object
        @SecuredRoles("admin, manager")
        public void MethodA()
        {
        _decorated.MethodA();
        }
       
        @SecuredRoles("regular user")
        public void MethodB()
        {
        _decorated.MethodB();
        }

}
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

Łukasz Lenart
I'm not sure if I understand, but you should be able to create an
interceptor and check if action implements given interface, then
create (or reuse) your decorator to check security.


Regards
--
Łukasz http://www.lenart.org.pl/
mobile +48 606 323 122, office +27 11 0838747
Warszawa JUG conference - Confitura http://confitura.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

wild_oscar
In reply to this post by wild_oscar
I was speaking with Lukasz today about this, so I'm resurrecting this
old thread.

The underlying question in my (rather extensive) post is:

How can you perform the following decorator pattern:

public OriginalAction implements Preparable,
SessionAware,OriginalActionInterface{

  public String someFunctionality(){
    ....
  }
}

Decorate like:

public DecoratedAction implements Preparable, SessionAware,etc{
  private OriginalActionInterface originalAction; //inject
OriginalAction here
  @Secured
  public String someFunctionality(){
    // do new stuff
    orignalAction.someFunctionality();
  }
}

Issues:
1) Your OriginalAction will probably rely on some objects injected by
struts (eg: session will probably be used). However, because
OriginalAction is now only decorating DecoratedAction...those objects
won't be automatically populated by Struts.


The only way I see it is to use Spring IoC to define these needed
objects in OriginalAction. But it would be neat if that was performed by
Struts.

What are your thoughts on this?


Miguel Almeida


 On Wed, 2012-05-16 at 11:22 +0100, Miguel Almeida wrote:

> Imagine the scenario where you have security implemented at the action
> method level with an annotation:
>
> @Secured("someRole") restricts that action to that role (and it is
> checked with an interceptor).
>
> Discussing this on the TDD mailing list a while back, a decorator
> approach was suggested
>
> To separate concerns and ease up testing, authorization is implemented
> as a decorator (a-la GoF decorator pattern) adding authorization to the
> underlying (decorated) MVC app.
>
> The technique to getting there (see pseudo code in [1])
> 1. Extract an interface from your main class with all the public methods
> 2. Implement a decorator which adds authorization rules to a decorated
> underlying object. The decorator implements the authorization rules
> using annotations
> 3. in your tests, test the decorator providing a mock underlying
> decorated object, asserting in each test that given a request with a
> user that has certain roles the underlying method should or should not
> be called.
>
>
> As you see, tests would have a simple setup as you wouldn't be calling
> "the real, possible complicated action code", but the fake decorated
> one.
> The problem arises when you have superclasses (and maybe also when you
> implement interfaces). I exemplify with both.
>
> Imagine this:
> RealAction extends CommonAction implements IAction(){
> ...}
>
> CommonAction implements ServletRequestAware(){
> ...
> }
>
> AuthorizingDecorator implements IAction(){
> //injected decorated IAction, see [1]
> ...
> }
>
> Now, on a regular RealAction implementation, the request object exists:
> RealAction extends CommonAction, so the request is injected through its
> ServletRequestAware.
> If you're using the AuthorizingDecorator, however, the request will be
> null: RealAction will be injected, so Struts won't kick in to populate
> RealAction's request object.
>
>
> My question is: how would you go on and solve this? Or is the decorator
> approach impractical in Struts? I haven't even consider the necessity to
> implement every getter/setter on the IAction, which would also make this
> approach a bit cumbersome. The simplicity for testing, however, is
> great!
>
> Cheers,
>
> Miguel Almeida
>
>
> [1] The code might end up like this (semi-pseudo code)
>
> 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 IAction
> {
>
>         String MethodA()
>         String MethodB()
>         ...
>
> }
>
> // this is the real action implementing methodA, methodB etc
> class RealAction: IAction
> {
>
>         String MethodA()
>         String MethodB()
>         ...
>
> }
>
> // this is responsible for authorization
> class AuthorizingDecoratorAction : IAction
> {
>
>         private IAction _decorated;
>         public AuthorizationDecorator(IAction decorated)
>         {
>         _decorated = decorated;
>         }
>        
>         // each method is implemented using annotations and calling the
>         underlying decorated object
>         @SecuredRoles("admin, manager")
>         public void MethodA()
>         {
>         _decorated.MethodA();
>         }
>        
>         @SecuredRoles("regular user")
>         public void MethodB()
>         {
>         _decorated.MethodB();
>         }
>
> }


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

Gabriel Belingueres-2
If this is a recurring functionality (that is, you use it on several
actions), then implementing it as an interceptor makes perfect sense.

http://struts.apache.org/2.3.4.1/docs/writing-interceptors.html

Gabriel

2012/10/3 Miguel Almeida <[hidden email]>:

> I was speaking with Lukasz today about this, so I'm resurrecting this
> old thread.
>
> The underlying question in my (rather extensive) post is:
>
> How can you perform the following decorator pattern:
>
> public OriginalAction implements Preparable,
> SessionAware,OriginalActionInterface{
>
>   public String someFunctionality(){
>     ....
>   }
> }
>
> Decorate like:
>
> public DecoratedAction implements Preparable, SessionAware,etc{
>   private OriginalActionInterface originalAction; //inject
> OriginalAction here
>   @Secured
>   public String someFunctionality(){
>     // do new stuff
>     orignalAction.someFunctionality();
>   }
> }
>
> Issues:
> 1) Your OriginalAction will probably rely on some objects injected by
> struts (eg: session will probably be used). However, because
> OriginalAction is now only decorating DecoratedAction...those objects
> won't be automatically populated by Struts.
>
>
> The only way I see it is to use Spring IoC to define these needed
> objects in OriginalAction. But it would be neat if that was performed by
> Struts.
>
> What are your thoughts on this?
>
>
> Miguel Almeida
>
>
>  On Wed, 2012-05-16 at 11:22 +0100, Miguel Almeida wrote:
>
>> Imagine the scenario where you have security implemented at the action
>> method level with an annotation:
>>
>> @Secured("someRole") restricts that action to that role (and it is
>> checked with an interceptor).
>>
>> Discussing this on the TDD mailing list a while back, a decorator
>> approach was suggested
>>
>> To separate concerns and ease up testing, authorization is implemented
>> as a decorator (a-la GoF decorator pattern) adding authorization to the
>> underlying (decorated) MVC app.
>>
>> The technique to getting there (see pseudo code in [1])
>> 1. Extract an interface from your main class with all the public methods
>> 2. Implement a decorator which adds authorization rules to a decorated
>> underlying object. The decorator implements the authorization rules
>> using annotations
>> 3. in your tests, test the decorator providing a mock underlying
>> decorated object, asserting in each test that given a request with a
>> user that has certain roles the underlying method should or should not
>> be called.
>>
>>
>> As you see, tests would have a simple setup as you wouldn't be calling
>> "the real, possible complicated action code", but the fake decorated
>> one.
>> The problem arises when you have superclasses (and maybe also when you
>> implement interfaces). I exemplify with both.
>>
>> Imagine this:
>> RealAction extends CommonAction implements IAction(){
>> ...}
>>
>> CommonAction implements ServletRequestAware(){
>> ...
>> }
>>
>> AuthorizingDecorator implements IAction(){
>> //injected decorated IAction, see [1]
>> ...
>> }
>>
>> Now, on a regular RealAction implementation, the request object exists:
>> RealAction extends CommonAction, so the request is injected through its
>> ServletRequestAware.
>> If you're using the AuthorizingDecorator, however, the request will be
>> null: RealAction will be injected, so Struts won't kick in to populate
>> RealAction's request object.
>>
>>
>> My question is: how would you go on and solve this? Or is the decorator
>> approach impractical in Struts? I haven't even consider the necessity to
>> implement every getter/setter on the IAction, which would also make this
>> approach a bit cumbersome. The simplicity for testing, however, is
>> great!
>>
>> Cheers,
>>
>> Miguel Almeida
>>
>>
>> [1] The code might end up like this (semi-pseudo code)
>>
>> 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 IAction
>> {
>>
>>         String MethodA()
>>         String MethodB()
>>         ...
>>
>> }
>>
>> // this is the real action implementing methodA, methodB etc
>> class RealAction: IAction
>> {
>>
>>         String MethodA()
>>         String MethodB()
>>         ...
>>
>> }
>>
>> // this is responsible for authorization
>> class AuthorizingDecoratorAction : IAction
>> {
>>
>>         private IAction _decorated;
>>         public AuthorizationDecorator(IAction decorated)
>>         {
>>         _decorated = decorated;
>>         }
>>
>>         // each method is implemented using annotations and calling the
>>         underlying decorated object
>>         @SecuredRoles("admin, manager")
>>         public void MethodA()
>>         {
>>         _decorated.MethodA();
>>         }
>>
>>         @SecuredRoles("regular user")
>>         public void MethodB()
>>         {
>>         _decorated.MethodB();
>>         }
>>
>> }
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

Lukasz Lenart
In reply to this post by wild_oscar
2012/10/3 Miguel Almeida <[hidden email]>:

> I was speaking with Lukasz today about this, so I'm resurrecting this
> old thread.
>
> The underlying question in my (rather extensive) post is:
>
> How can you perform the following decorator pattern:
>
> public OriginalAction implements Preparable,
> SessionAware,OriginalActionInterface{
>
>   public String someFunctionality(){
>     ....
>   }
> }
>
> Decorate like:
>
> public DecoratedAction implements Preparable, SessionAware,etc{
>   private OriginalActionInterface originalAction; //inject
> OriginalAction here
>   @Secured
>   public String someFunctionality(){
>     // do new stuff
>     orignalAction.someFunctionality();
>   }
> }
>
> Issues:
> 1) Your OriginalAction will probably rely on some objects injected by
> struts (eg: session will probably be used). However, because
> OriginalAction is now only decorating DecoratedAction...those objects
> won't be automatically populated by Struts.
>
>
> The only way I see it is to use Spring IoC to define these needed
> objects in OriginalAction. But it would be neat if that was performed by
> Struts.
>
> What are your thoughts on this?
>
>
> Miguel Almeida
>
>
>  On Wed, 2012-05-16 at 11:22 +0100, Miguel Almeida wrote:
>
>> Imagine the scenario where you have security implemented at the action
>> method level with an annotation:
>>
>> @Secured("someRole") restricts that action to that role (and it is
>> checked with an interceptor).
>>
>> Discussing this on the TDD mailing list a while back, a decorator
>> approach was suggested
>>
>> To separate concerns and ease up testing, authorization is implemented
>> as a decorator (a-la GoF decorator pattern) adding authorization to the
>> underlying (decorated) MVC app.
>>
>> The technique to getting there (see pseudo code in [1])
>> 1. Extract an interface from your main class with all the public methods
>> 2. Implement a decorator which adds authorization rules to a decorated
>> underlying object. The decorator implements the authorization rules
>> using annotations
>> 3. in your tests, test the decorator providing a mock underlying
>> decorated object, asserting in each test that given a request with a
>> user that has certain roles the underlying method should or should not
>> be called.
>>
>>
>> As you see, tests would have a simple setup as you wouldn't be calling
>> "the real, possible complicated action code", but the fake decorated
>> one.
>> The problem arises when you have superclasses (and maybe also when you
>> implement interfaces). I exemplify with both.
>>
>> Imagine this:
>> RealAction extends CommonAction implements IAction(){
>> ...}
>>
>> CommonAction implements ServletRequestAware(){
>> ...
>> }
>>
>> AuthorizingDecorator implements IAction(){
>> //injected decorated IAction, see [1]
>> ...
>> }
>>
>> Now, on a regular RealAction implementation, the request object exists:
>> RealAction extends CommonAction, so the request is injected through its
>> ServletRequestAware.
>> If you're using the AuthorizingDecorator, however, the request will be
>> null: RealAction will be injected, so Struts won't kick in to populate
>> RealAction's request object.
>>
>>
>> My question is: how would you go on and solve this? Or is the decorator
>> approach impractical in Struts? I haven't even consider the necessity to
>> implement every getter/setter on the IAction, which would also make this
>> approach a bit cumbersome. The simplicity for testing, however, is
>> great!
>>
>> Cheers,
>>
>> Miguel Almeida
>>
>>
>> [1] The code might end up like this (semi-pseudo code)
>>
>> 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 IAction
>> {
>>
>>         String MethodA()
>>         String MethodB()
>>         ...
>>
>> }
>>
>> // this is the real action implementing methodA, methodB etc
>> class RealAction: IAction
>> {
>>
>>         String MethodA()
>>         String MethodB()
>>         ...
>>
>> }
>>
>> // this is responsible for authorization
>> class AuthorizingDecoratorAction : IAction
>> {
>>
>>         private IAction _decorated;
>>         public AuthorizationDecorator(IAction decorated)
>>         {
>>         _decorated = decorated;
>>         }
>>
>>         // each method is implemented using annotations and calling the
>>         underlying decorated object
>>         @SecuredRoles("admin, manager")
>>         public void MethodA()
>>         {
>>         _decorated.MethodA();
>>         }
>>
>>         @SecuredRoles("regular user")
>>         public void MethodB()
>>         {
>>         _decorated.MethodB();
>>         }
>>
>> }
>
>

I thought about that a bit, but as I'm not sure what's the real use
case is so my proposal can be wrong ;-)
There are two option (both to extend struts2 itself), beside that you
can always write your own interceptor.

First is to add additional interface (ActionDecortator) that will mark
an action as a decorating action the original one and all the
injections / method calls will be performed onto
ActionDecorator#getDelegate(). Thus must be implemented in each
interceptor which interacts with action base on interface (Preparable,
ValidationAware, SessionAware, etc).

The second option is to add additional interface / annotation just for
selected existing interceptors, eg. ServletConfigInterceptor and new
ServletConfigDecorator#getDelegate(). Thus must be only implemented
with given interceptor.

We can always mix the both ways and start with one interface
(ActionDecorator) and add the functionality to all the interceptors
step by step.


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

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

wild_oscar
I am resurrecting this very old thread to ask if there have been any
updates to struts itself to solve this.
I was reading some comments on this subject on stackoverflow and
recalled our discussion.

Lukasz - do you know of any developments within Struts in this area?

With regards to your original suggestion, I'm not sure I followed, since
"Thus must be implemented in each interceptor which interacts with
action base on interface (Preparable, ValidationAware, SessionAware,
etc)." sounded like all (or most) Struts  interceptors would need to be
re-written.

Miguel

On Qui, 2012-10-04 at 08:05 +0200, Lukasz Lenart wrote:

> 2012/10/3 Miguel Almeida <[hidden email]>:
> > I was speaking with Lukasz today about this, so I'm resurrecting this
> > old thread.
> >
> > The underlying question in my (rather extensive) post is:
> >
> > How can you perform the following decorator pattern:
> >
> > public OriginalAction implements Preparable,
> > SessionAware,OriginalActionInterface{
> >
> >   public String someFunctionality(){
> >     ....
> >   }
> > }
> >
> > Decorate like:
> >
> > public DecoratedAction implements Preparable, SessionAware,etc{
> >   private OriginalActionInterface originalAction; //inject
> > OriginalAction here
> >   @Secured
> >   public String someFunctionality(){
> >     // do new stuff
> >     orignalAction.someFunctionality();
> >   }
> > }
> >
> > Issues:
> > 1) Your OriginalAction will probably rely on some objects injected by
> > struts (eg: session will probably be used). However, because
> > OriginalAction is now only decorating DecoratedAction...those objects
> > won't be automatically populated by Struts.
> >
> >
> > The only way I see it is to use Spring IoC to define these needed
> > objects in OriginalAction. But it would be neat if that was performed by
> > Struts.
> >
> > What are your thoughts on this?
> >
> >
> > Miguel Almeida
> >
> >
> >  On Wed, 2012-05-16 at 11:22 +0100, Miguel Almeida wrote:
> >
> >> Imagine the scenario where you have security implemented at the action
> >> method level with an annotation:
> >>
> >> @Secured("someRole") restricts that action to that role (and it is
> >> checked with an interceptor).
> >>
> >> Discussing this on the TDD mailing list a while back, a decorator
> >> approach was suggested
> >>
> >> To separate concerns and ease up testing, authorization is implemented
> >> as a decorator (a-la GoF decorator pattern) adding authorization to the
> >> underlying (decorated) MVC app.
> >>
> >> The technique to getting there (see pseudo code in [1])
> >> 1. Extract an interface from your main class with all the public methods
> >> 2. Implement a decorator which adds authorization rules to a decorated
> >> underlying object. The decorator implements the authorization rules
> >> using annotations
> >> 3. in your tests, test the decorator providing a mock underlying
> >> decorated object, asserting in each test that given a request with a
> >> user that has certain roles the underlying method should or should not
> >> be called.
> >>
> >>
> >> As you see, tests would have a simple setup as you wouldn't be calling
> >> "the real, possible complicated action code", but the fake decorated
> >> one.
> >> The problem arises when you have superclasses (and maybe also when you
> >> implement interfaces). I exemplify with both.
> >>
> >> Imagine this:
> >> RealAction extends CommonAction implements IAction(){
> >> ...}
> >>
> >> CommonAction implements ServletRequestAware(){
> >> ...
> >> }
> >>
> >> AuthorizingDecorator implements IAction(){
> >> //injected decorated IAction, see [1]
> >> ...
> >> }
> >>
> >> Now, on a regular RealAction implementation, the request object exists:
> >> RealAction extends CommonAction, so the request is injected through its
> >> ServletRequestAware.
> >> If you're using the AuthorizingDecorator, however, the request will be
> >> null: RealAction will be injected, so Struts won't kick in to populate
> >> RealAction's request object.
> >>
> >>
> >> My question is: how would you go on and solve this? Or is the decorator
> >> approach impractical in Struts? I haven't even consider the necessity to
> >> implement every getter/setter on the IAction, which would also make this
> >> approach a bit cumbersome. The simplicity for testing, however, is
> >> great!
> >>
> >> Cheers,
> >>
> >> Miguel Almeida
> >>
> >>
> >> [1] The code might end up like this (semi-pseudo code)
> >>
> >> 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 IAction
> >> {
> >>
> >>         String MethodA()
> >>         String MethodB()
> >>         ...
> >>
> >> }
> >>
> >> // this is the real action implementing methodA, methodB etc
> >> class RealAction: IAction
> >> {
> >>
> >>         String MethodA()
> >>         String MethodB()
> >>         ...
> >>
> >> }
> >>
> >> // this is responsible for authorization
> >> class AuthorizingDecoratorAction : IAction
> >> {
> >>
> >>         private IAction _decorated;
> >>         public AuthorizationDecorator(IAction decorated)
> >>         {
> >>         _decorated = decorated;
> >>         }
> >>
> >>         // each method is implemented using annotations and calling the
> >>         underlying decorated object
> >>         @SecuredRoles("admin, manager")
> >>         public void MethodA()
> >>         {
> >>         _decorated.MethodA();
> >>         }
> >>
> >>         @SecuredRoles("regular user")
> >>         public void MethodB()
> >>         {
> >>         _decorated.MethodB();
> >>         }
> >>
> >> }
> >
> >
>
> I thought about that a bit, but as I'm not sure what's the real use
> case is so my proposal can be wrong ;-)
> There are two option (both to extend struts2 itself), beside that you
> can always write your own interceptor.
>
> First is to add additional interface (ActionDecortator) that will mark
> an action as a decorating action the original one and all the
> injections / method calls will be performed onto
> ActionDecorator#getDelegate(). Thus must be implemented in each
> interceptor which interacts with action base on interface (Preparable,
> ValidationAware, SessionAware, etc).
>
> The second option is to add additional interface / annotation just for
> selected existing interceptors, eg. ServletConfigInterceptor and new
> ServletConfigDecorator#getDelegate(). Thus must be only implemented
> with given interceptor.
>
> We can always mix the both ways and start with one interface
> (ActionDecorator) and add the functionality to all the interceptors
> step by step.
>
>
> Regards
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Can we use the decorator pattern in Actions?

Lukasz Lenart
Hi Miguel,

I still have this on my TODO list ;-) But to be honest, I have no idea
(or rather forgot) how it should be implemented and I still don't get
it, what's the main reason/functionality?

It looks like a proxy but from user/developer perspective (just for
records, Struts is using ActionProxy internally), but as far I
understand you will code the original action and the decorated one by
hand? there be no proxy magic involved? So all you need is a way to
inject the original action into the decorated action ... which seems
doable ;-)

To start over:

@OriginalAction
public OriginalAction implements Preparable, SessionAware,
OriginalActionInterface {

  public String someFunctionality(){
    ....
  }
}

@DecoratedAction
public DecoratedAction {

 @InjectAction
 private OriginalActionInterface originalAction; //inject OriginalAction here

  @Secured
  public String someFunctionality(){
    // do new stuff
    orignalAction.someFunctionality();
  }
}

<struts>
  <action name="decorated" class="...DecoratedAction">
     ...
  </action
</struts>

having actions as such and the configuration, the flow will be as follow:

http request -> map to the "decorated" entry in struts.xml -> create
instance of the DecoratedAction -> discover @DecoratedAction and/or
@InjectAction (possibility to inject multiple decorated actions???) ->
create instance of the OriginalAction and apply request on it (this
action will be threaten as it will the original mapped to action, in a
classic way) -> inject the original action into the decorated -> call
execute -> continue to result -> response

is the above align to your idea?


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

2017-03-31 18:29 GMT+02:00 Miguel Almeida <[hidden email]>:

> I am resurrecting this very old thread to ask if there have been any updates
> to struts itself to solve this.
> I was reading some comments on this subject on stackoverflow and recalled
> our discussion.
>
> Lukasz - do you know of any developments within Struts in this area?
>
> With regards to your original suggestion, I'm not sure I followed, since
> "Thus must be implemented in each interceptor which interacts with action
> base on interface (Preparable, ValidationAware, SessionAware, etc)." sounded
> like all (or most) Struts  interceptors would need to be re-written.
>
> Miguel
>
>
> On Qui, 2012-10-04 at 08:05 +0200, Lukasz Lenart wrote:
>
> 2012/10/3 Miguel Almeida <[hidden email]>:
>> I was speaking with Lukasz today about this, so I'm resurrecting this
>> old thread.
>>
>> The underlying question in my (rather extensive) post is:
>>
>> How can you perform the following decorator pattern:
>>
>> public OriginalAction implements Preparable,
>> SessionAware,OriginalActionInterface{
>>
>>   public String someFunctionality(){
>>     ....
>>   }
>> }
>>
>> Decorate like:
>>
>> public DecoratedAction implements Preparable, SessionAware,etc{
>>   private OriginalActionInterface originalAction; //inject
>> OriginalAction here
>>   @Secured
>>   public String someFunctionality(){
>>     // do new stuff
>>     orignalAction.someFunctionality();
>>   }
>> }
>>
>> Issues:
>> 1) Your OriginalAction will probably rely on some objects injected by
>> struts (eg: session will probably be used). However, because
>> OriginalAction is now only decorating DecoratedAction...those objects
>> won't be automatically populated by Struts.
>>
>>
>> The only way I see it is to use Spring IoC to define these needed
>> objects in OriginalAction. But it would be neat if that was performed by
>> Struts.
>>
>> What are your thoughts on this?
>>
>>
>> Miguel Almeida
>>
>>
>>  On Wed, 2012-05-16 at 11:22 +0100, Miguel Almeida wrote:
>>
>>> Imagine the scenario where you have security implemented at the action
>>> method level with an annotation:
>>>
>>> @Secured("someRole") restricts that action to that role (and it is
>>> checked with an interceptor).
>>>
>>> Discussing this on the TDD mailing list a while back, a decorator
>>> approach was suggested
>>>
>>> To separate concerns and ease up testing, authorization is implemented
>>> as a decorator (a-la GoF decorator pattern) adding authorization to the
>>> underlying (decorated) MVC app.
>>>
>>> The technique to getting there (see pseudo code in [1])
>>> 1. Extract an interface from your main class with all the public methods
>>> 2. Implement a decorator which adds authorization rules to a decorated
>>> underlying object. The decorator implements the authorization rules
>>> using annotations
>>> 3. in your tests, test the decorator providing a mock underlying
>>> decorated object, asserting in each test that given a request with a
>>> user that has certain roles the underlying method should or should not
>>> be called.
>>>
>>>
>>> As you see, tests would have a simple setup as you wouldn't be calling
>>> "the real, possible complicated action code", but the fake decorated
>>> one.
>>> The problem arises when you have superclasses (and maybe also when you
>>> implement interfaces). I exemplify with both.
>>>
>>> Imagine this:
>>> RealAction extends CommonAction implements IAction(){
>>> ...}
>>>
>>> CommonAction implements ServletRequestAware(){
>>> ...
>>> }
>>>
>>> AuthorizingDecorator implements IAction(){
>>> //injected decorated IAction, see [1]
>>> ...
>>> }
>>>
>>> Now, on a regular RealAction implementation, the request object exists:
>>> RealAction extends CommonAction, so the request is injected through its
>>> ServletRequestAware.
>>> If you're using the AuthorizingDecorator, however, the request will be
>>> null: RealAction will be injected, so Struts won't kick in to populate
>>> RealAction's request object.
>>>
>>>
>>> My question is: how would you go on and solve this? Or is the decorator
>>> approach impractical in Struts? I haven't even consider the necessity to
>>> implement every getter/setter on the IAction, which would also make this
>>> approach a bit cumbersome. The simplicity for testing, however, is
>>> great!
>>>
>>> Cheers,
>>>
>>> Miguel Almeida
>>>
>>>
>>> [1] The code might end up like this (semi-pseudo code)
>>>
>>> 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 IAction
>>> {
>>>
>>>         String MethodA()
>>>         String MethodB()
>>>         ...
>>>
>>> }
>>>
>>> // this is the real action implementing methodA, methodB etc
>>> class RealAction: IAction
>>> {
>>>
>>>         String MethodA()
>>>         String MethodB()
>>>         ...
>>>
>>> }
>>>
>>> // this is responsible for authorization
>>> class AuthorizingDecoratorAction : IAction
>>> {
>>>
>>>         private IAction _decorated;
>>>         public AuthorizationDecorator(IAction decorated)
>>>         {
>>>         _decorated = decorated;
>>>         }
>>>
>>>         // each method is implemented using annotations and calling the
>>>         underlying decorated object
>>>         @SecuredRoles("admin, manager")
>>>         public void MethodA()
>>>         {
>>>         _decorated.MethodA();
>>>         }
>>>
>>>         @SecuredRoles("regular user")
>>>         public void MethodB()
>>>         {
>>>         _decorated.MethodB();
>>>         }
>>>
>>> }
>>
>>
>
> I thought about that a bit, but as I'm not sure what's the real use
> case is so my proposal can be wrong ;-)
> There are two option (both to extend struts2 itself), beside that you
> can always write your own interceptor.
>
> First is to add additional interface (ActionDecortator) that will mark
> an action as a decorating action the original one and all the
> injections / method calls will be performed onto
> ActionDecorator#getDelegate(). Thus must be implemented in each
> interceptor which interacts with action base on interface (Preparable,
> ValidationAware, SessionAware, etc).
>
> The second option is to add additional interface / annotation just for
> selected existing interceptors, eg. ServletConfigInterceptor and new
> ServletConfigDecorator#getDelegate(). Thus must be only implemented
> with given interceptor.
>
> We can always mix the both ways and start with one interface
> (ActionDecorator) and add the functionality to all the interceptors
> step by step.
>
>
> Regards

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Loading...