View Full Version : Maybe trivial question about proxies
Diego
08-12-2007, 10:59 PM
Hi to all, I don't know if I'm asking a trivial or FAQ question, however is there any trick to proxy also private methods of a class ? I'd like to use AOP to create a logging system that intercept all methods calls and that logs the method called, parameters and other informations. But I'm limited to log only interface methods.
I've read in the guide the section "13.5.4. Proxying Classes", but with no success.
Can anyone suggest me if there is a way to do this ?
Thanks ;)
Mark Pollack
08-13-2007, 04:48 AM
Hi Diego,
There isn't any trick, private methods are not candidates to be proxied. You can proxy methods on an interface or public virtual methods. While AOP aims to add as non-invasive as possible in terms of influencing your class design, you will occasionally need to rework your class to accomodate the application of AOP advice. Sometimes this works in the direction of promoting a best practice, such as using interfaces for service layer opertions, but other times it can seem artifical.
Cheers,
Mark
floyd
08-13-2007, 11:15 AM
There isn't any trick, private methods are not candidates to be proxied. You can proxy methods on an interface or public virtual methods.
Hi Mark,
How about "Property"? Does property can be proxied?
Recently I found every I set property to my proxied object, it doesn't work.
By using debugger and trace, I found property value which I set could not e forward to my proxied object. As following ======
<object id="CategoryService" singleton="false" type="KB.Service.CategoryService, KB">
<property name="CategoryDao" ref="CategoryDao"/>
</object>
<object id="CategoryDao" type="Persistence.CategoryDao, KB">
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<object id="CategoryServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="TargetSource" ref="CategoryTargetSource"/>
<property name="ProxyInterfaces">
<list>
<value>KB.Service.ICategoryService</value>
</list>
</property>
<property name="InterceptorNames">
<value>TransactionInterceptor</value>
</property>
</object>
<object id="CategoryTargetSource" type="Spring.Aop.Target.PrototypeTargetSource, Spring.Aop">
<property name="TargetObjectName" value="CategoryService" />
</object>
<object id="TransactionInterceptor" type="Spring.Transaction.Interceptor.TransactionIntercep tor, Spring.Data">
<property name="TransactionManager" ref="HibernateTransactionManager"/>
<property name="TransactionAttributeSource" ref="MatchAlwaysTransactionAttributeSource"/>
</object>
My code as following
ICategoryService obj = ctx["CategoryServiceProxy"] as ICategoryService;
service.ServingUser = user;
service.CheckPrivilege = checkPrivilege;
The values of user and checkPrivilege seem to be "ignore" or somehow disappear. I can't never user these value within my CategoryService like following situation
The CategoryService id defined like following
public class categoryService{
private User user;
private bool checkPrivilege;
public bool CheckPrivilege
{
get
{
return checkPrivilege;
}
set
{
checkPrivilege = value;
}
}
public User ServingUser
{
get
{
return user;
}
set
{
user = value;
}
}
public Category anotherMethod(){
Category c = new Category();
c.LastModifierId = this.user.DisplayName;
//problem here, will throw a nullpotinerexception.
//seem like user variable is null
retunr c;
}
}
I don't know what wrong and I read all documents but no idea.
Hope you can understand my problem.
Bruno Baia
08-13-2007, 01:02 PM
Hi,
Your service class does not implement any interface, so Spring will proxy the target type.
To allow a class that does not implement any interface to be proxied by Spring, you need to mark its members as virtual (properties and methods).
Reference documentation :
12.5.3. Proxying Interfaces (http://www.springframework.net/doc-latest/reference/html/aop.html#aop-proxying-interfaces)
12.5.4. Proxying Classes (http://www.springframework.net/doc-latest/reference/html/aop.html#d0e7796)
HTH,
Bruno
floyd
08-13-2007, 04:58 PM
Hi,
Your service class does not implement any interface, so Spring will proxy the target type.
To allow a class that does not implement any interface to be proxied by Spring, you need to mark its members as virtual (properties and methods).
Reference documentation :
12.5.3. Proxying Interfaces (http://www.springframework.net/doc-latest/reference/html/aop.html#aop-proxying-interfaces)
12.5.4. Proxying Classes (http://www.springframework.net/doc-latest/reference/html/aop.html#d0e7796)
HTH,
Bruno
Hi Bruno,
Thanks for you reply first!
Actually I did implements the interface ICategoryService in my Service class I just forgot to describe, sorry.
So the problem is still around how can I set properties of my service object which proxied by Spring container. It seems to that everytime i set properties to my service object, the value are gone(disappear and became null).
How colud this be solved? mark properties virtual?
By the way, I read those documents and you guy are reaaly nice on documents. I'm still have no idea with it.
Bruno Baia
08-13-2007, 05:04 PM
ICategoryService obj = ctx["CategoryServiceProxy"] as ICategoryService;
service.ServingUser = user;
service.CheckPrivilege = checkPrivilege;
What's that 'service' field ?
Does your properties belongs to the interface ?
Why are you not injecting thoses properties with Spring ?
Be careful, you are using prototypes.
Cheers,
Bruno
Diego
08-13-2007, 05:13 PM
Actually I did implements the interface ICategoryService in my Service class I just forgot to describe, sorry.
So the problem is still around how can I set properties of my service object which proxied by Spring container. It seems to that everytime i set properties to my service object, the value are gone(disappear and became null).
How colud this be solved? mark properties virtual?
Hi, in my experiments I'm able to proxy properties (and their value is not lost) if they appear in the interface. So in your case you can add to ICategoryService interface:
User ServingUser { get; set; }
bool CheckPrivilege { get; set; }
I've made some test to reproduce your situation (using a IMethodInterceptor advice), but for me there are no errors (with or without properties declared in the interface).
floyd
08-13-2007, 06:11 PM
What's that 'service' field ?
Does your properties belongs to the interface ?
Why are you not injecting thoses properties with Spring ?
Be careful, you are using prototypes.
Cheers,
Bruno
I'm sorry that I made a typo
ICategoryService service = ctx["CategoryServiceProxy"] as ICategoryService;
service.ServingUser = user;
service.CheckPrivilege = checkPrivilege;
Why I'm not inject properties with Spring is because that ServingUser and CheckPrivilege is runtime determinated with logged on user througt web. So I need get service object from Spring and set service object's properties also I need service object transactional.
Diego
08-13-2007, 06:15 PM
There isn't any trick, private methods are not candidates to be proxied. You can proxy methods on an interface or public virtual methods. While AOP aims to add as non-invasive as possible in terms of influencing your class design, you will occasionally need to rework your class to accomodate the application of AOP advice. Sometimes this works in the direction of promoting a best practice, such as using interfaces for service layer opertions, but other times it can seem artifical.
Thanks for the reply, I supposed that. However, because I'm testing Spring.net in order to see if I can introduce it in my future projects, I can rework and accomodate the team practice. Our projects often use Enterprise Services (ES from now), so my final objective is to test Spring.net with them in order to produce a logging and benchmarking sub-system. For now I've not tested with ES, because I'm making incremental experiments. I can say that Spring.net is not so invasive regarding ES because in ES you always make interfaces for the classes that perform business logic, so instead of:
IBusinessClass1 _ISC1 = new BusinessClass1();it's not a big problem to write:
IBusinessClass1 _ISC1 = (BusinessClass) ctx.GetObject( "NameSpace.IBusinessClass" );The only problems I've found for now are:
private or protected methods, because they cannot be proxied. However I can accomodate this by declaring them virtual public in the class definition and by not declaring them in the interface (so they are not exposed in the public interface exposed by COM+). So no big deal here.
method m2() belonging to class A, called by method m1() of the same class. This is very strange because the method m2() is not intercepted by a IMethodInterceptorFor the second problem, in order to intercept m2(), I must transform all code like this:
public interface IA
{void m1();
}
public class A : IA
{public void m1()
{
m2();
}
virtual public void m2()
{
/// Do something...
}
}
/// ... and this is the calling code:
IApplicationContext ctx = ContextRegistry.GetContext();
IA a = (A) ctx.GetObject( "A" );
a.m1();
/// ...
in something like this:
public interface IA
{void m1();
}
public class A : IA
{public void m1()
{ IApplicationContext ctx = ContextRegistry.GetContext();
IA a = (A) ctx.GetObject( "A" );
a.m2();
}
virtual public void m2()
{
/// Do something...
}
}
/// ... and this is the calling code:
IApplicationContext ctx = ContextRegistry.GetContext();
IA a = (A) ctx.GetObject( "A" );
a.m1();
/// ...
and this is not so "beautiful" if singleton is set to false, because it works for methods that don't access properties or attributes of the class A, but not in the other case. Is this normal or I'm doing some error based on my inexperience ? I'm using an ObjectNameAutoProxyCreator to create proxies.
Thanks for the help.
floyd
08-13-2007, 06:17 PM
Hi, in my experiments I'm able to proxy properties (and their value is not lost) if they appear in the interface. So in your case you can add to ICategoryService interface:
User ServingUser { get; set; }
bool CheckPrivilege { get; set; }
I've made some test to reproduce your situation (using a IMethodInterceptor advice), but for me there are no errors (with or without properties declared in the interface).
Thanks Diego,
The situation is my CategoryService class implements ICategoryService
and ICategoryService extends IManager interface. Within IManager interface, defined two property as following shows:
public interface IManager{
User ServingUser {get; set;}
bool CheckPrivilege {get; set;}
}
I lost my property value but trasaction context is initial smootly. did I miss something?
Mark Pollack
08-17-2007, 03:52 PM
Hi Floyd,
Can you .zip up a minimal solution demonstrating the issue and post it here as an attachement?
Cheers,
Mark
Mark Pollack
08-17-2007, 03:59 PM
Hi Diego,
You can get access to the current proxy inside the target class by setting the property 'ExposeProxy' to true in ProxyFactoryObject. This will store the current AOP proxy in thread local storage. You can then retrieve it via a call to AopContext.CurrentProxy. I believe this would be more appropriate than what you are currently doing, which looks like you are instantiating a new object inside the method since you are using prototypes.
A more non-invasive way, i.e. not refering to the spring API is to use a combination of method-replacement for a This() method. In the class definition it would simply return 'this' but using method-replacement it would return AopContext.CurrentProxy. I have not yet tried this last approach yet, it was a good suggestion from another user on the forum.
Cheers,
Mark
Diego
08-17-2007, 05:53 PM
You can get access to the current proxy inside the target class by setting the property 'ExposeProxy' to true in ProxyFactoryObject. This will store the current AOP proxy in thread local storage. You can then retrieve it via a call to AopContext.CurrentProxy. I believe this would be more appropriate than what you are currently doing, which looks like you are instantiating a new object inside the method since you are using prototypes.
Very good, I've just tested this way and it works fine. It is not so invasive in my opinion.
p.s. no success in the other thread about unhandled exceptions
floyd
08-17-2007, 06:36 PM
Hi Floyd,
Can you .zip up a minimal solution demonstrating the issue and post it here as an attachement?
Cheers,
Mark
okay. I'll prepare with it as soon as possible.
thanks Mark!
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.