You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ace.apache.org by Marcel Offermans <ma...@luminis.nl> on 2011/01/22 15:18:35 UTC

Dynamically debugging services with aspects...

For ACE-112 [1] I had to debug the events flowing through the system to see if the events being sent were created and received correctly. Most events (in ACE) are being sent asynchronously, which makes debugging by setting breakpoints a bit more difficult, as setting breakpoints in handleEvent() will not reveal the sender.

One way to get more information is to "intercept" all calls to EventAdmin, and the technique to do this is what I wanted to share with you in this e-mail.

What we can do is use the Dependency Manager to create an aspect service on top of EventAdmin. An aspect can intercept all calls to services and in your interceptor you can still delegate the calls to the original service. Technically, this is being implemented using service rankings, which means that consumers will automatically react to aspects.

What I did was add the following to the Activator of the VaadinClient:

        manager.add(createAspectService(EventAdmin.class, null, 10, null)
            .setImplementation(new EventAdmin() {
                volatile EventAdmin m_eventAdmin;
                
                private String print(Event event) {
                    StringBuffer result = new StringBuffer();
                    result.append("Event[ ");
                    String[] names = event.getPropertyNames();
                    for (String name : names) {
                        result.append(name);
                        result.append('=');
                        result.append(event.getProperty(name));
                        result.append(' ');
                    }
                    result.append(']');
                    return result.toString();
                }
                
                public void postEvent(Event event) {
                    System.out.println("postEvent: " + print(event));
                    m_eventAdmin.postEvent(event);
                }
    
                public void sendEvent(Event event) {
                    System.out.println("sendEvent: " + print(event));
                    m_eventAdmin.sendEvent(event);
                }
            }));

When we create the aspect service, the first two parameters are the service class and a filter condition (null here) we want to create aspects on top of. For each service that matches the service name and filter, and aspect will be instantiated of the class specified below. The third parameters is the service ranking for this aspect. This is there because you can also chain aspects on top of each other. The final option (null here) is the name of the member that should be injected into the aspect service (null means any member of the right class).

The implementation is just one that intercepts all calls, prints the event, and then delegates them to the real EventAdmin (which is injected automatically).

So it's quite easy to debug a service this way, and it's fully dynamic. Even in a running production system, you can install a new bundle that adds an aspect on top of an existing service and you can instantly intercept all calls, and stop or uninstall the bundle again once you're done.

Greetings, Marcel

[1] https://issues.apache.org/jira/browse/ACE-112


Re: Dynamically debugging services with aspects...

Posted by Marcel Offermans <ma...@luminis.nl>.
Hello Dennis,

Yes, the sample below is something that literally came out of the ACE code, but I ripped it out before I committed it. Go to the ace-webui-vaadin project, and then to the src/main/java/org/apache/ace/webui/vaadin/Activator.java class and lookup the init(BundleContext context, DependencyManager manager) method and insert the snippet below at the end.

That's the quickest way to start with this. Naturally, by sticking it in the same bundle as the UI, you cannot easily install and uninstall it separately form the rest of the codebase, but I guess that's not hard to do.

Greetings, Marcel


On 23 Jan 2011, at 21:29 , Dennis Crissman wrote:

> 
> Would it be possible to get a working example of how to do this?
> 
> Thanks,
> Dennis Crissman
> 
>> Subject: Re: Dynamically debugging services with aspects...
>> From: marcel.offermans@luminis.nl
>> Date: Sun, 23 Jan 2011 19:34:09 +0100
>> To: ace-dev@incubator.apache.org
>> 
>> Definitely, or, using the same method described below, you can also intercept all EventHandlers that are listening to events.
>> 
>> On 23 Jan 2011, at 15:55 , Angelo van der Sijpt wrote:
>> 
>>> Ooh, nice method, I've had this problem before.
>>> 
>>> To add to that, you could ease debugging (or at least, tracing of calls to EventAdmin) by attaching the method that calls this postEvent or sendEvent method, for instance by using
>>>   result.append(Thread.currentThread().getStackTrace()[2])
>>> 
>>> I am aware that this will fail in certain environments, but in most situations it gives you an idea of 'where this message came from'.
>>> 
>>> Angelo
>>> 
>>> On Jan 22, 2011, at 3:18 PM, Marcel Offermans wrote:
>>> 
>>>> For ACE-112 [1] I had to debug the events flowing through the system to see if the events being sent were created and received correctly. Most events (in ACE) are being sent asynchronously, which makes debugging by setting breakpoints a bit more difficult, as setting breakpoints in handleEvent() will not reveal the sender.
>>>> 
>>>> One way to get more information is to "intercept" all calls to EventAdmin, and the technique to do this is what I wanted to share with you in this e-mail.
>>>> 
>>>> What we can do is use the Dependency Manager to create an aspect service on top of EventAdmin. An aspect can intercept all calls to services and in your interceptor you can still delegate the calls to the original service. Technically, this is being implemented using service rankings, which means that consumers will automatically react to aspects.
>>>> 
>>>> What I did was add the following to the Activator of the VaadinClient:
>>>> 
>>>>      manager.add(createAspectService(EventAdmin.class, null, 10, null)
>>>>          .setImplementation(new EventAdmin() {
>>>>              volatile EventAdmin m_eventAdmin;
>>>> 
>>>>              private String print(Event event) {
>>>>                  StringBuffer result = new StringBuffer();
>>>>                  result.append("Event[ ");
>>>>                  String[] names = event.getPropertyNames();
>>>>                  for (String name : names) {
>>>>                      result.append(name);
>>>>                      result.append('=');
>>>>                      result.append(event.getProperty(name));
>>>>                      result.append(' ');
>>>>                  }
>>>>                  result.append(']');
>>>>                  return result.toString();
>>>>              }
>>>> 
>>>>              public void postEvent(Event event) {
>>>>                  System.out.println("postEvent: " + print(event));
>>>>                  m_eventAdmin.postEvent(event);
>>>>              }
>>>> 
>>>>              public void sendEvent(Event event) {
>>>>                  System.out.println("sendEvent: " + print(event));
>>>>                  m_eventAdmin.sendEvent(event);
>>>>              }
>>>>          }));
>>>> 
>>>> When we create the aspect service, the first two parameters are the service class and a filter condition (null here) we want to create aspects on top of. For each service that matches the service name and filter, and aspect will be instantiated of the class specified below. The third parameters is the service ranking for this aspect. This is there because you can also chain aspects on top of each other. The final option (null here) is the name of the member that should be injected into the aspect service (null means any member of the right class).
>>>> 
>>>> The implementation is just one that intercepts all calls, prints the event, and then delegates them to the real EventAdmin (which is injected automatically).
>>>> 
>>>> So it's quite easy to debug a service this way, and it's fully dynamic. Even in a running production system, you can install a new bundle that adds an aspect on top of an existing service and you can instantly intercept all calls, and stop or uninstall the bundle again once you're done.
>>>> 
>>>> Greetings, Marcel
>>>> 
>>>> [1] https://issues.apache.org/jira/browse/ACE-112
>>>> 
>>> 
>>> 
>> 
> 		 	   		  


RE: Dynamically debugging services with aspects...

Posted by Dennis Crissman <de...@hotmail.com>.
Would it be possible to get a working example of how to do this?

Thanks,
Dennis Crissman

> Subject: Re: Dynamically debugging services with aspects...
> From: marcel.offermans@luminis.nl
> Date: Sun, 23 Jan 2011 19:34:09 +0100
> To: ace-dev@incubator.apache.org
> 
> Definitely, or, using the same method described below, you can also intercept all EventHandlers that are listening to events.
> 
> On 23 Jan 2011, at 15:55 , Angelo van der Sijpt wrote:
> 
> > Ooh, nice method, I've had this problem before.
> > 
> > To add to that, you could ease debugging (or at least, tracing of calls to EventAdmin) by attaching the method that calls this postEvent or sendEvent method, for instance by using
> >    result.append(Thread.currentThread().getStackTrace()[2])
> > 
> > I am aware that this will fail in certain environments, but in most situations it gives you an idea of 'where this message came from'.
> > 
> > Angelo
> > 
> > On Jan 22, 2011, at 3:18 PM, Marcel Offermans wrote:
> > 
> >> For ACE-112 [1] I had to debug the events flowing through the system to see if the events being sent were created and received correctly. Most events (in ACE) are being sent asynchronously, which makes debugging by setting breakpoints a bit more difficult, as setting breakpoints in handleEvent() will not reveal the sender.
> >> 
> >> One way to get more information is to "intercept" all calls to EventAdmin, and the technique to do this is what I wanted to share with you in this e-mail.
> >> 
> >> What we can do is use the Dependency Manager to create an aspect service on top of EventAdmin. An aspect can intercept all calls to services and in your interceptor you can still delegate the calls to the original service. Technically, this is being implemented using service rankings, which means that consumers will automatically react to aspects.
> >> 
> >> What I did was add the following to the Activator of the VaadinClient:
> >> 
> >>       manager.add(createAspectService(EventAdmin.class, null, 10, null)
> >>           .setImplementation(new EventAdmin() {
> >>               volatile EventAdmin m_eventAdmin;
> >> 
> >>               private String print(Event event) {
> >>                   StringBuffer result = new StringBuffer();
> >>                   result.append("Event[ ");
> >>                   String[] names = event.getPropertyNames();
> >>                   for (String name : names) {
> >>                       result.append(name);
> >>                       result.append('=');
> >>                       result.append(event.getProperty(name));
> >>                       result.append(' ');
> >>                   }
> >>                   result.append(']');
> >>                   return result.toString();
> >>               }
> >> 
> >>               public void postEvent(Event event) {
> >>                   System.out.println("postEvent: " + print(event));
> >>                   m_eventAdmin.postEvent(event);
> >>               }
> >> 
> >>               public void sendEvent(Event event) {
> >>                   System.out.println("sendEvent: " + print(event));
> >>                   m_eventAdmin.sendEvent(event);
> >>               }
> >>           }));
> >> 
> >> When we create the aspect service, the first two parameters are the service class and a filter condition (null here) we want to create aspects on top of. For each service that matches the service name and filter, and aspect will be instantiated of the class specified below. The third parameters is the service ranking for this aspect. This is there because you can also chain aspects on top of each other. The final option (null here) is the name of the member that should be injected into the aspect service (null means any member of the right class).
> >> 
> >> The implementation is just one that intercepts all calls, prints the event, and then delegates them to the real EventAdmin (which is injected automatically).
> >> 
> >> So it's quite easy to debug a service this way, and it's fully dynamic. Even in a running production system, you can install a new bundle that adds an aspect on top of an existing service and you can instantly intercept all calls, and stop or uninstall the bundle again once you're done.
> >> 
> >> Greetings, Marcel
> >> 
> >> [1] https://issues.apache.org/jira/browse/ACE-112
> >> 
> > 
> > 
> 
 		 	   		  

Re: Dynamically debugging services with aspects...

Posted by Marcel Offermans <ma...@luminis.nl>.
Definitely, or, using the same method described below, you can also intercept all EventHandlers that are listening to events.

On 23 Jan 2011, at 15:55 , Angelo van der Sijpt wrote:

> Ooh, nice method, I've had this problem before.
> 
> To add to that, you could ease debugging (or at least, tracing of calls to EventAdmin) by attaching the method that calls this postEvent or sendEvent method, for instance by using
>    result.append(Thread.currentThread().getStackTrace()[2])
> 
> I am aware that this will fail in certain environments, but in most situations it gives you an idea of 'where this message came from'.
> 
> Angelo
> 
> On Jan 22, 2011, at 3:18 PM, Marcel Offermans wrote:
> 
>> For ACE-112 [1] I had to debug the events flowing through the system to see if the events being sent were created and received correctly. Most events (in ACE) are being sent asynchronously, which makes debugging by setting breakpoints a bit more difficult, as setting breakpoints in handleEvent() will not reveal the sender.
>> 
>> One way to get more information is to "intercept" all calls to EventAdmin, and the technique to do this is what I wanted to share with you in this e-mail.
>> 
>> What we can do is use the Dependency Manager to create an aspect service on top of EventAdmin. An aspect can intercept all calls to services and in your interceptor you can still delegate the calls to the original service. Technically, this is being implemented using service rankings, which means that consumers will automatically react to aspects.
>> 
>> What I did was add the following to the Activator of the VaadinClient:
>> 
>>       manager.add(createAspectService(EventAdmin.class, null, 10, null)
>>           .setImplementation(new EventAdmin() {
>>               volatile EventAdmin m_eventAdmin;
>> 
>>               private String print(Event event) {
>>                   StringBuffer result = new StringBuffer();
>>                   result.append("Event[ ");
>>                   String[] names = event.getPropertyNames();
>>                   for (String name : names) {
>>                       result.append(name);
>>                       result.append('=');
>>                       result.append(event.getProperty(name));
>>                       result.append(' ');
>>                   }
>>                   result.append(']');
>>                   return result.toString();
>>               }
>> 
>>               public void postEvent(Event event) {
>>                   System.out.println("postEvent: " + print(event));
>>                   m_eventAdmin.postEvent(event);
>>               }
>> 
>>               public void sendEvent(Event event) {
>>                   System.out.println("sendEvent: " + print(event));
>>                   m_eventAdmin.sendEvent(event);
>>               }
>>           }));
>> 
>> When we create the aspect service, the first two parameters are the service class and a filter condition (null here) we want to create aspects on top of. For each service that matches the service name and filter, and aspect will be instantiated of the class specified below. The third parameters is the service ranking for this aspect. This is there because you can also chain aspects on top of each other. The final option (null here) is the name of the member that should be injected into the aspect service (null means any member of the right class).
>> 
>> The implementation is just one that intercepts all calls, prints the event, and then delegates them to the real EventAdmin (which is injected automatically).
>> 
>> So it's quite easy to debug a service this way, and it's fully dynamic. Even in a running production system, you can install a new bundle that adds an aspect on top of an existing service and you can instantly intercept all calls, and stop or uninstall the bundle again once you're done.
>> 
>> Greetings, Marcel
>> 
>> [1] https://issues.apache.org/jira/browse/ACE-112
>> 
> 
> 


Re: Dynamically debugging services with aspects...

Posted by Angelo van der Sijpt <an...@luminis.eu>.
Ooh, nice method, I've had this problem before.

To add to that, you could ease debugging (or at least, tracing of calls to EventAdmin) by attaching the method that calls this postEvent or sendEvent method, for instance by using
    result.append(Thread.currentThread().getStackTrace()[2])

I am aware that this will fail in certain environments, but in most situations it gives you an idea of 'where this message came from'.

Angelo

On Jan 22, 2011, at 3:18 PM, Marcel Offermans wrote:

> For ACE-112 [1] I had to debug the events flowing through the system to see if the events being sent were created and received correctly. Most events (in ACE) are being sent asynchronously, which makes debugging by setting breakpoints a bit more difficult, as setting breakpoints in handleEvent() will not reveal the sender.
> 
> One way to get more information is to "intercept" all calls to EventAdmin, and the technique to do this is what I wanted to share with you in this e-mail.
> 
> What we can do is use the Dependency Manager to create an aspect service on top of EventAdmin. An aspect can intercept all calls to services and in your interceptor you can still delegate the calls to the original service. Technically, this is being implemented using service rankings, which means that consumers will automatically react to aspects.
> 
> What I did was add the following to the Activator of the VaadinClient:
> 
>        manager.add(createAspectService(EventAdmin.class, null, 10, null)
>            .setImplementation(new EventAdmin() {
>                volatile EventAdmin m_eventAdmin;
> 
>                private String print(Event event) {
>                    StringBuffer result = new StringBuffer();
>                    result.append("Event[ ");
>                    String[] names = event.getPropertyNames();
>                    for (String name : names) {
>                        result.append(name);
>                        result.append('=');
>                        result.append(event.getProperty(name));
>                        result.append(' ');
>                    }
>                    result.append(']');
>                    return result.toString();
>                }
> 
>                public void postEvent(Event event) {
>                    System.out.println("postEvent: " + print(event));
>                    m_eventAdmin.postEvent(event);
>                }
> 
>                public void sendEvent(Event event) {
>                    System.out.println("sendEvent: " + print(event));
>                    m_eventAdmin.sendEvent(event);
>                }
>            }));
> 
> When we create the aspect service, the first two parameters are the service class and a filter condition (null here) we want to create aspects on top of. For each service that matches the service name and filter, and aspect will be instantiated of the class specified below. The third parameters is the service ranking for this aspect. This is there because you can also chain aspects on top of each other. The final option (null here) is the name of the member that should be injected into the aspect service (null means any member of the right class).
> 
> The implementation is just one that intercepts all calls, prints the event, and then delegates them to the real EventAdmin (which is injected automatically).
> 
> So it's quite easy to debug a service this way, and it's fully dynamic. Even in a running production system, you can install a new bundle that adds an aspect on top of an existing service and you can instantly intercept all calls, and stop or uninstall the bundle again once you're done.
> 
> Greetings, Marcel
> 
> [1] https://issues.apache.org/jira/browse/ACE-112
>