How to know that a method was run, when you didn’t write that method

Recently, I was posed with a situation where I needed to ensure that a particular method was being run by an application, but that method was part of the framework (ADF in this case) not a method that I had written myself.  Since Java does not let me go and open up a framework class and add more code to it (like Scala’s ‘pimp my library’ pattern does), I could not really use the good old reliable System.out.println() approach to debugging – so what to do?

Asking around, I discovered something called a pointcut, a feature of aspect oriented programming.  This is a little out of my area of experience, but I like to think of it essentially as a mechanism that lets you define a piece of code to run when some particular thing happens.

So for example, I can say something like ‘whenever method X on object Y is executed, do Z’ which is great – that lets me solve my exact problem.

So let’s look at a simple example.  Let’s say for the sake of an example that I want to ensure that a particular ADF view is causing the method addPartialTriggerListeners() on object org.apache.myfaces.trinidadinternal.context.RequestContextImpl to be invoked.  This ought to be invoked when we have a partial page refresh on a view.

Let’s start by building a simple ADF application.

First, we will create a managed bean that we can use as a simple data source.  Here is the code:

package test;

import java.util.ArrayList;
import java.util.List;

import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

public class TestBean {

    private List<SelectItem> suggestions = new ArrayList<SelectItem>();
    private String theValue;

    public TestBean() {
        super();
        System.out.println("TestBean init");

        //initialise list of choices
        suggestions.add(new SelectItem("Sydney"));
        suggestions.add(new SelectItem("Melbourne"));
        suggestions.add(new SelectItem("Singapore"));
        suggestions.add(new SelectItem("Tokyo"));
        suggestions.add(new SelectItem("Beijing"));
        suggestions.add(new SelectItem("San Francisco"));
        suggestions.add(new SelectItem("New York"));
        suggestions.add(new SelectItem("Houston"));
        suggestions.add(new SelectItem("Seattle"));
        suggestions.add(new SelectItem("London"));
        suggestions.add(new SelectItem("Paris"));
    }

    public List<SelectItem> getSuggestions() {
        return suggestions;
    }

    public void setSuggestions(List<SelectItem> suggestions) {}

    public String getTheValue() { return this.theValue; }

    public void setTheValue(String value) { this.theValue = value; }

    public void selectValueChangeListener(ValueChangeEvent valueChangeEvent) {
        theValue = (String) valueChangeEvent.getNewValue();
    }
}

Then we can create our view.  To make it easier, you can copy the source from here:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
  <f:view>
    <af:document id="d1">
      <af:form id="f1">
        <af:outputText value="This is a test page" id="ot1">
          <span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'>3-5705908791</span>
        </af:outputText>
        <af:selectOneChoice label="Pick a city" id="soc1"
                            valueChangeListener="#{TestBean.selectValueChangeListener}"
                            autoSubmit="true">
          <f:selectItems value="#{TestBean.suggestions}" id="si1"/>
        </af:selectOneChoice>
        <af:outputText value="you choose #{TestBean.theValue}" id="ot2"
                       partialTriggers="soc1"/>
      </af:form>
    </af:document>
  </f:view>
</jsp:root>

Now open up the adf-config.xml and add the managed bean as shown below:

Now you can deploy the ADF application to your WebLogic Server and make sure it works.

Next, we want to enable the WebLogic Diagnostic Framework on the managed server.  This is a one off activity.  You do this in the WebLogic Console, under the DiagnosticsDiagnostic Modules menu.

There should be a module definition there that was created when you installed WebLogic, if there is not, just go ahead and create one.  You just need to give it a name and then target it to the appropriate managed server.  Then open it up and go to the ConfigurationInstrumentation tab and click on the Enabled check box to turn it on.

Now we need to tell it what to monitor.  Go to the Deployments menu item and open up your ADF application that you just deployed.

Go to the ConfigurationInstrumentation tab and again check the Enabled check box for this application.  Then go back in there again and click on the Add Custom Monitor button (down the bottom).

Give your monitor a name, e.g. listener, and enter the pointcut as shown below (all on one line):

execution ( * 
org.apache.myfaces.trinidadinternal.context.RequestContextImpl 
addPartialTriggerListeners(...) )

Now click on the Save button and then open up your new monitor again.  Go down to the Actions section and make sure that the TraceAction is moved across to the Chosen list.  Also make sure that the Enabled check box is selected.  Now Save your monitor.

When you are prompted, create a new Plan for the application.

Then go and update your application (select it in Deployments and click on the Update button).

If this is the very first time you have turned on WLDF, you may need to restart your managed server as well.

Now go run your application and choose something from the drop down list.

Now we can check to see if that method was run.   Go to the DiagnosticsLog Files menu and open the EventsDataArchive log.  You should see the output from your monitor right there, confirming that the method in question was in fact run.  The image below shows an example.  It also shows output from a second custom monitor.  If you are feeling adventureous, you may want to try to create that monitor too.

Well I am sure that this is only just scratching the surface of what WebLogic Diagnostic Framework can do, but I for one am inspired to go and learn more.  I hope you enjoyed this post!

Thanks to Robert Patrick and Sabha Parameswaran for teaching me about pointcuts!

About Mark Nelson

Mark Nelson is an Architect (an "IC6") in the Fusion Middleware Central Development Team at Oracle. Mark's job is to make Fusion Middleware easy to use in the cloud and at home, for developers and operations folks, with special focus on continuous delivery, configuration management and provisioning - making it simple to manage the configuration of complex environments and applications built with Oracle Database, Fusion Middleware and Fusion Applications, on-premise and in the cloud. Before joining this team, Mark was a senior member of the A-Team since 2010, and worked in Sales Consulting at Oracle since 2006 and various roles at IBM since 1994.
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

2 Responses to How to know that a method was run, when you didn’t write that method

  1. Pingback: How to find which class is printing out a bad message | RedStack

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s