---
title: Java agent API: Custom instrumentation with annotation of an example app
source: https://docs.newrelic.com/docs/apm/agents/java-agent/api-guides/java-agent-api-custom-instrumentation-annotation-example-app
---

The [New Relic Java agent API](http://newrelic.github.io/java-agent-api/javadoc/com/newrelic/api/agent/NewRelic.html) lets you set up custom instrumentation for your Java application. This document shows an example of using custom instrumentation with annotation in an imaginary application.

> #### ⚠️ IMPORTANT
>
> For best results when using the API, ensure you have the [latest Java agent release](https://docs.newrelic.com/docs/release-notes/agent-release-notes/java-release-notes).

## Complete example app using API [#all]

Below is an example of an imaginary store app's servlet using the Java agent API.

> #### 💡 TIP
>
> If you copy and paste example code, be sure to use appropriate spacing on your command lines.

**Complete API call example**

````java
<a href="#import-packages">package test;</a>

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Java agent API imports
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;

<a href="#set-annotation">public class TestServlet extends HttpServlet {</a>
    // instrumentation via annotation
    @Trace(dispatcher = true)
    protected void
    processRequest(HttpServletRequest req,
    HttpServletResponse resp)
        throws ServletException, IOException {

        saveNewRelicInfo(req);
        doRequestWork(req);
        writeResponse(resp);
    }

    <a href="#name-transactions">private void saveNewRelicInfo(HttpServletRequest req) {</a>
        String storeId = req.getParameter("storeId");
        if (storeId != null) {
        // set the name of the Transaction
        NewRelic.setTransactionName(null, "/store");

    <a href="#ignore-apdex">if (storeId.equals("betaStore")) {
</a>        // prevent the method from contributing to the Apdex score
        NewRelic.ignoreApdex();
        }
    }

    <a href="#record-user-id">String userId = req.getParameter("userId");</a>
        if (userId != null) {
            // Tracks the user ID to the current transaction by setting the enduser.id agent attribute 
            NewRelic.setUserId(userId);
            // set the user name to associate with the RUM JavaScript footer 
            // for the current web transaction
            NewRelic.setUserName(userId);
            // add a key/value pair to the current transaction
            NewRelic.addCustomParameter("userId", userId);
        }

    <a href="#get-custom-metric">String promotionId = req.getParameter("promotionId");</a>
        if (promotionId != null) {
            // increment the metric counter for the given name
            NewRelic.incrementCounter("Custom/Promotion");
        }
    }

    <a href="#control-handler">protected void
    doRequestWork(HttpServletRequest req) {</a>
    try {
        long millisToSleep  = new Random().nextInt(5000);
        Thread.sleep(millisToSleep);
        // record a response time in milliseconds for the given metric name
        NewRelic.recordResponseTimeMetric("Custom/RandomSleep",
        millisToSleep);
        } catch (InterruptedException e) {
            // report a handled exception
            NewRelic.noticeError(e, false);
        }
    }

    protected void
    writeResponse(HttpServletResponse resp)
        throws IOException {

    <a href="#include-browser">resp.setContentType("text/html;charset=UTF-8");</a>
    PrintWriter out = resp.getWriter();
    out.println("<html>");
    out.println("<head>");

    // get the RUM JavaScript header for the current web transaction
    out.println(NewRelic.getBrowserTimingHeader());
    out.println("<title>NewRelic API example servlet</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>API example</h1>");
    // get the RUM JavaScript footer for the current web transaction
    out.println(NewRelic.getBrowserTimingFooter());
    out.println("</body>");
    out.println("</html>");
    out.close();
    }
    <a href="#complete-response">protected void doGet(HttpServletRequest req,</a>
    HttpServletResponse resp)
        throws ServletException, IOException {
        processRequest(req, resp);
        }
    protected void doPost(HttpServletRequest req,
    HttpServletResponse resp)
        throws ServletException, IOException {
        processRequest(req, resp);
    }
}
```

````

## How the example uses the API [#app-broken-down]

Here is the same example app divided into sections that describe how the API is used:

**Import the needed packages**

This part of the example shows the imports needed for the example application and Java agent API.

````java
package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Java agent API imports 
import com.newrelic.api.agent.NewRelic;
import com.newrelic.api.agent.Trace;
```

````

**Set @Trace for transaction traces**

This part of the API call provides instructions to instrument this call using New Relic's trace annotation `@Trace`. Any requests that hit `processRequest` will now show a segment in APM's [Transaction trace call chart](https://docs.newrelic.com/docs/apm/transactions/transaction-traces/viewing-transaction-traces).

````java
public class TestServlet extends HttpServlet {
    // instrumentation via annotation
    @Trace(dispatcher = true)
    protected void processRequest(HttpServletRequest req,
        HttpServletResponse resp) throws ServletException, IOException {
        saveNewRelicInfo(req);
        doRequestWork(req);
        writeResponse(resp);
    }
```

````

**Create custom names for web transactions**

This part of the API call instructs web transactions containing a `storeId` value to appear in APM's [**Transactions** page](https://docs.newrelic.com/docs/apm/applications-menu/monitoring/transactions-dashboard) with the custom transaction name you set. A request to any one store will appear under the same, aggregate name.

````java
private void
saveNewRelicInfo(HttpServletRequest req) {
    String storeId = req.getParameter("storeId");
    if (storeId != null) {
        // set the name of the Transaction
        NewRelic.setTransactionName(null, "/store");
    }
}
```

````

**Bypass Apdex when collecting non-public data**

This part of the API call excludes the non-public beta `storeID` from affecting the [Apdex score](https://docs.newrelic.com/docs/apm/new-relic-apm/apdex/view-your-apdex-score).

````java
if (storeId.equals("betaStore")) {
    // prevent the method from contributing to the Apdex score 
    NewRelic.ignoreApdex();
}
```

````

**Record the user ID**

This part of the API call inserts additional metadata into the [page load timing](https://docs.newrelic.com/docs/browser/new-relic-browser/page-load-timing-resources/page-load-timing-process) request so that browser traces can be tied with the `userId`. It also records the `userId` as a custom parameter on the transaction so that it appears in the [parameter details of a transaction trace](https://docs.newrelic.com/docs/apm/transactions/transaction-traces/transaction-traces-trace-details-page). (Page load timing sometimes is referred to as real user monitoring or RUM.)

````java
String userId = req.getParameter("userId");
if (userId != null) {
    // set the user name to associate with the RUM JavaScript footer 
    // for the current web transaction 
    NewRelic.setUserName(userId); 
    // add a key/value pair to the current transaction 
    NewRelic.addCustomParameter("userId", userId);     
}
```

````

**Collect promotion data**

This part of the API call records the number of times a promotion was viewed so that the metrics can appear on a custom dashboard.

> #### ⚠️ IMPORTANT
>
> For metrics you want to graph in [custom dashboards](https://docs.newrelic.com/docs/dashboards/new-relic-dashboards/custom-dashboards/creating-custom-dashboards), be sure to prepend `Custom/` to the metric name; for example, `Custom/Promotion`.

````java
String promotionId = req.getParameter("promotionId");
if (promotionId != null) {
    // increment the metric counter for the given name
    NewRelic.incrementCounter("Custom/Promotion");
}
```

````

**Send instructions to the handler**

This part of the API call sends a set of instructions to the handler for processing requests and handling exceptions.

````java
protected void doRequestWork(HttpServletRequest req) {
    try {
        long millisToSleep = new Random().nextInt(5000);
        Thread.sleep(millisToSleep);
        // record a response time in milliseconds for the given metric name
        NewRelic.recordResponseTimeMetric("Custom/RandomSleep", millisToSleep);
    } catch (InterruptedException e) {
        // report a handled exception
        NewRelic.noticeError(e, false);
    }
}
protected void writeResponse(HttpServletResponse resp) throws IOException {
```

````

**Include page load timing code in the HTTP response**

This part of the API call defines what to include in the `HttpServletResponse`. For [manual instrumentation of browser monitoring](https://docs.newrelic.com/docs/agents/java-agent/instrumentation/page-load-timing-java) to monitor page load timing (sometimes referred to as real user monitoring or RUM):

-   Set the header after the `<head>` tag.
-   Set the footer at the end of `<body>` tag.

    ```java
    resp.setContentType("text/html;charset=UTF-8");
    PrintWriter out = resp.getWriter();
    out.println("<html>");
    out.println("<head>");
    // get the RUM JavaScript header for the current web transaction
    out.println(NewRelic.getBrowserTimingHeader());
    out.println("<title>NewRelic API example servlet</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>API example</h1>");
    // get the RUM JavaScript footer for the current web transaction
    out.println(NewRelic.getBrowserTimingFooter());
    out.println("</body>");
    out.println("</html>");
    out.close();
    ```

**Complete the HTTP response**

This part of the API call defines the remaining information to include in the `HttpServletResponse` response.

````java
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    processRequest(req, resp);
}

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    processRequest(req, resp);
}
```

````
