Binding Interceptor to intercept a method call of objects which are created by a factory method

155 views
Skip to first unread message

Richard

unread,
Mar 20, 2009, 12:49:46 PM3/20/09
to google-guice
Hello,
this way i have to create my webservice client:
private static class ReportingServiceProvider implements
Provider<IReportingService> {
@Inject
@Named("webservices.properties.ReportingService")
private String url;

public IReportingService get() {
HessianProxyFactory factory = new HessianProxyFactory();
factory.setHessian2Reply(true);
factory.setHessian2Request(true);
try {
return (IReportingService) factory.create(IReportingService.class,
url);
} catch (MalformedURLException e) {
throw new RuntimeException(
e);
}
}
}

Now I want to bind an Interceptor to it:
bindInterceptor(Matchers.subclassesOf(IReportingService.class),
Matchers.any(), new CallTimeInterceptor());

But this is not working. I remember a new group entry saying that
guice only installs interceptors to objects it creates. Any ideas how
to work around this problem?

Richard Hauswald

unread,
Mar 20, 2009, 4:24:32 PM3/20/09
to google-guice
I did a dirty hack... it enables me to somehow, in a very dirty way,
apply java proxies to instances created by guice and providers. I
attached the solutions classes. Here is how it works:
bind(MyService.class).annotatedWith(Names.named("intercept")).to(MyServiceImpl.class);
bind(MyService.class).toProvider(new
ProxyBindingProvider<MyService>(Key.get(MyService.class,
Names.named("intercept")),CallTimeProxy.class));

I'd be glad if somebody would be so kind to give it short look and
maybe write his/her thoughts.
Thanks,
Richard


2009/3/20 Richard <Richard....@googlemail.com>:
RawTypeExtractor.java
ProxyBindingProvider.java
ProxyBindingProviderTest.java

Alen Vrecko

unread,
Mar 20, 2009, 8:23:50 PM3/20/09
to google-guice
Hi,

yeah, if Guice doesn't create the instance than there is no way to get
in the interceptors.

One way I can think of without using any hacks is to put in some
delegates like in your case you'd have:

interface IReportingServiceDelegate extends IReportingService

class IReportingServiceDelegateImpl implements
IReportingServiceDelegate{

private final IReportingService delegate;

@Inject
// will use your own class created by custom factory but this class
will be Guice created so interceptors will work
public IReportingServiceDelegateImpl(IReportingService delegate){
this.delegate = delegate;
}

@LogMe
public void someMethod(){
delegate.someMethod();
}

...
}

and then use the delegate instead of the original. It is a bit more
visual noise. Most IDEs know how to make delegates automatically.

It should be possible to make the delegates automatically behind the
curtains with some CG magic.

Your solution is independent of bindInterceptor;)

HTH,
Alen

On Mar 20, 9:24 pm, Richard Hauswald <richard.hausw...@googlemail.com>
wrote:
> I did a dirty hack... it enables me to somehow, in a very dirty way,
> apply java proxies to instances created by guice and providers. I
> attached the solutions classes. Here is how it works:
> bind(MyService.class).annotatedWith(Names.named("intercept")).to(MyServiceImpl.class);
> bind(MyService.class).toProvider(new
> ProxyBindingProvider<MyService>(Key.get(MyService.class,
> Names.named("intercept")),CallTimeProxy.class));
>
> I'd be glad if somebody would be so kind to give it short look and
> maybe write his/her thoughts.
> Thanks,
> Richard
>
> 2009/3/20 Richard <Richard.Hausw...@googlemail.com>:
>
>
>
> > Hello,
> > this way i have to create my webservice client:
> > private static class ReportingServiceProvider implements
> > Provider<IReportingService> {
> >                @Inject
> >                @Named("webservices.properties.ReportingService")
> >                private String url;
>
> >                public IReportingService get() {
> >                        HessianProxyFactory factory = new HessianProxyFactory();
> >                        factory.setHessian2Reply(true);
> >                        factory.setHessian2Request(true);
> >                        try {
> >                                return (IReportingService) factory.create(IReportingService.class,
> > url);
> >                        } catch (MalformedURLException e) {
> >                                throw new RuntimeException(
> >                                                e);
> >                        }
> >                }
> >        }
>
> > Now I want to bind an Interceptor to it:
> > bindInterceptor(Matchers.subclassesOf(IReportingService.class),
> > Matchers.any(), new CallTimeInterceptor());
>
> > But this is not working. I remember a new group entry saying that
> > guice only installs interceptors to objects it creates. Any ideas how
> > to work around this problem?
>
>
>
>  RawTypeExtractor.java
> < 1KViewDownload
>
>  ProxyBindingProvider.java
> 2KViewDownload
>
>  ProxyBindingProviderTest.java
> 3KViewDownload

Richard

unread,
Mar 21, 2009, 4:31:30 AM3/21/09
to google-guice
Hi Alen,
thanks for your help.

> yeah, if Guice doesn't create the instance than there is no way to get
> in the interceptors.
This is a big disadvantage - is it going to solved in 2.0?

> One way I can think of without using any hacks is to put in some
> delegates like in your case you'd have:
> ...
> and then use the delegate instead of the original. It is a bit more
> visual noise. Most IDEs know how to make delegates automatically.
I'm using the free version of eclipse. It supports this feature under
the source menu. The initial effort to create these delegates is not
that much but in case of changes to the service interface you always
have to regenrate the delegates. Thats not very AOP. Having 20 service
classes this will cause my boss to hire a student apprentice to do
this job every day. :-)

> It should be possible to make the delegates automatically behind the
> curtains with some CG magic.
Thats what I was trying to do. AFAIK this is not possible without
providers cause proxies are created @ runtime and binding an interface
type is checked @ compile time. :-(
> Your solution is independent of bindInterceptor;)
Thats why it's dirty :)
> > > Now I want to bind anInterceptorto it:
> > > bindInterceptor(Matchers.subclassesOf(IReportingService.class),
> > > Matchers.any(), new CallTimeInterceptor());
>
> > > But this is not working. I remember a new group entry saying that
> > > guice only installs interceptors toobjectsit creates. Any ideas how

Alen Vrecko

unread,
Mar 21, 2009, 7:37:46 AM3/21/09
to google-guice
Hi Richard,

> > yeah, if Guice doesn't create the instance than there is no way to get
> > in the interceptors.
>
> This is a big disadvantage - is it going to solved in 2.0?

AFAIK: No. This is technically not possible.

When you request an instance lets say getInstance(Foo.class) should it
need AOP Guice will create a subclass of Foo with the interceptors
installed. That is why AOP doesn't work on final classes since they
cannot be subclassed.

But if you already create an instance there is no way to change class
structure of an instance on the fly and put in the interceptors.

You're right, delegates are very cumbersome. Yeah, there is no nice
solution to this. But to be honest your solution is a bit
intimidating:) If it solves your problem I'd call it a day. I'd go a
step further and make it more user friend (to use bindInterceptor).

With the auto delegates I had this craziness in mind:
when you want IFoo but are supplied with new FooImpl, you'd create a
delegate class definition for IFoo and ask Guice to provide it (Guice
will then subclass it with AOP) and then set the FooImpl to the
created delegate and return the delegate. Not for the faint hearted.

Cheers,
Alen

Richard Hauswald

unread,
Mar 21, 2009, 12:54:37 PM3/21/09
to google...@googlegroups.com
Hi Alen,
I'm a brave guy so i don't fear intimidating solutions :-) But you are
right, bindInterceptor would be the way of the hero.

> With the auto delegates I had this craziness in mind:
> when you want IFoo but are supplied with new FooImpl, you'd create a
> delegate class definition for IFoo and ask Guice to provide it (Guice
> will then subclass it with AOP) and then set the FooImpl to the
> created delegate and return the delegate. Not for the faint hearted.
What do you mean by auto delegates? Dynamicly created or created by
the IDE? If you mean dynamicly created, I don't have any glue how to
do this, maybe my brain is trapped at the end of one way dead end
road...
Please help me out of this misery,
Richard
> Cheers,
> Alen
> >
>

Alen Vrecko

unread,
Mar 21, 2009, 2:29:00 PM3/21/09
to google-guice
Hi Richard,

Yeah, I had dynamically created delegates in mind. Basically I'd use
code generation (handcrafted or ASM or CGLib or ...) to create a
delegate class definition (a perfectly legitimate class) and then ask
Guice to provide an instance of this class after which I set the
actual instance to delegate to (returned by the provider). I'd go and
intercept the provider like this

@CreateDynamicDelegate // this will intercept the instance and do the
magic and return the delegate, which only implements IFoo, instead of
FooImpl.
IFoo get(){
return new FooImpl(12);
}

There are some issues with this, do you need annotations, how about
other interfaces the instance implements and obviously you can't cast
to a concrete instance and it only works for interfaces...

There are lots of smart people on this list...surely somebody will
come up with something better.

Cheers,
Alen

On Mar 21, 5:54 pm, Richard Hauswald <richard.hausw...@googlemail.com>
wrote:
Reply all
Reply to author
Forward
0 new messages