Java

Documentation - Raygun4Java - Java Error & Crash Reporting

Contents

The Raygun4Java provider

Raygun crash reporting and error monitoring is easily available with raygun4java. Raygun4java is a library that you can easily add to your Java application, which will then allow you to transmit all exceptions to your Raygun.io dashboard. Installation is painless, and configuring your site to transmit errors takes only 5 minutes.

Raygun4java supports Java 6 and greater. The library is available as a Maven package, so you only need to add the appropriate entry to your pom.xml. JARs are also available for other build systems.

What Java project types are supported?

Pretty much anything! Classical desktop and console apps are supported by the main library. Web applications projects, such as Java Servlets and projects that use JSPs are fully supported by including the additional raygun4java-web library. This can also be used in popular web frameworks such as Spring.

First-class Scala and the Play 2 framework support is also available, and the library can also be used in code running on Google App Engine.

What can I send to Raygun.io?

Raygun4Java is designed to send any object that inherits from Throwable. You can add a set of tags (as an array of strings) to identify a certain type of message, or add a custom user data (as a key-value Map).

What are the steps I need to take to add raygun4java to my application?

Here's an overview:

  1. Add the dependency to your pom.xml, or copy the JAR(s) into a /lib folder and add it to the build path
  2. Create an exception handler and subscribe to it
  3. Add two lines to this handler - one creating an instance of RaygunClient, and the other calling Send() on it. And you're done!

Read the step-by-step instructions below.

Installation

With Maven and Eclipse/another IDE

These instructions assume you have a Maven project with a POM file set up in Eclipse, but this is also applicable to other IDEs and environments.

  1. Open your project's pom.xml in Eclipse. Click on Dependencies -> Add. In the pattern search box, typecom.mindscapehq.
  2. Add com.mindscape.raygun4java and com.mindscapehq.core, version 2.0.0.

    If you are working in a web environment, add com.mindscapehq.webprovider jar too.

    If you wish to grab the example project, you can also get the sampleapp jar.

  3. Save your POM, and the dependencies should appear in Maven Dependencies.

With Maven and a command shell

If you are in a shell/text editor environment, you can run mvn install from the directory containing your project's pom.xml. The pom.xml will need to contain something like:

<dependencies>
    ...
    <dependency>
        <groupId>com.mindscapehq</groupId>
        <artifactId>raygun4java</artifactId>
        <type>pom</type>
        <version>[2.1.1)</version>
    </dependency>
    <dependency>
        <groupId>com.mindscapehq</groupId>
        <artifactId>core</artifactId>
        <version>[2.1.1)</version>
    </dependency>
</dependencies>

POM for Web Projects

If you're using servlets, JSPs or similar, you'll need to also add:

<dependency>
    <groupId>com.mindscapehq</groupId>
    <artifactId>webprovider</artifactId>
    <version>[2.1.1)</version>
</dependency>

With Ant or other build tools

Download the JARs for the latest version from here:

raygun-corerequired

raygun-webprovideroptional - if you want to receive HTTP request data from JSPs, servlets, GAE, web frameworks etc.

gsonrequired - you will also need the Gson dependency in your classpath.

Usage

Desktop applications

To catch all exceptions in your application, and to send them to Raygun:

public class MyApp
{
    public static void main(String[] args) throws Throwable
    {
            Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
    }
}

class MyExceptionHandler implements Thread.UncaughtExceptionHandler
{
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        RaygunClient client = new RaygunClient("YOUR_APP_API_KEY");
        client.Send(e);

    }
}

Or see the sample app which is where this code originates.

JSPs

The concept is the same for the above - set up an Unhandled Exception handler, then inside it create a RaygunClient and call Send() on it, passing in the exception. The way this is done will vary based on what framework you are using. Presented below is a naive example that just uses plain JSPs - this architecture is obviously not recommended. A similar method will work for raw servlets if happen to be using those.

Inside web.xml

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
        <location>/error.jsp</location>
</error-page>

Inside error.jsp

<%@ page isErrorPage="true" %>
<%@ page import="com.mindscapehq.raygun4java.webprovider.RaygunServletClient" %>

<%
RaygunServletClient client = new RaygunServletClient("YOUR_APP_API_KEY", request);

client.Send(exception);
%>

When an exception is thrown from another JSP, this page will take care of the sending.

Note: all Java dynamic web page projects should have core-2.0.0..jar, webprovider-2.0.0..jar and gson-2.1.jar on their classpath.

Play 2 framework for Java and Scala

This provider now contains a dedicated Play 2 provider for automatically sending Java and Scala exceptions from Play 2 web apps. Feedback is appreciated if you use this provider in a Play 2 app. You can use the plain core-2.x.x provider from Scala, but if you use this dedicated Play 2 provider HTTP request data is transmitted too.

Installation

With SBT

Add the following line to your build.sbt's libraryDependencies:

libraryDependencies ++= Seq(
    "com.mindscapehq" % "raygun4java-play2" % "2.2.0"
)

Usage

For automatic exception sending, in your Play 2 app's global error handler, RaygunPlayClient has a method which allows you to pass in a RequestHeader and send a Throwable. If you have changed your global class in conf/application.conf, the appropriate code below should be placed in that class instead.

In Scala - app/Global.scala:

override def onError(request: RequestHeader, ex: Throwable) = {
  val rg = new RaygunPlayClient("your_api_key", request)
  val result = rg.SendAsync(ex)

  super.onError(request, ex)
}

In Java - app/Global.java:

import play.*;
import play.mvc.*;
import play.mvc.Http.*;
import play.libs.F.*;

import com.mindscapehq.raygun4java.play2.RaygunPlayClient;

import static play.mvc.Results.*;

public class Global extends GlobalSettings {

    private String apiKey = "paste_your_api_key_here";

    public Promise<Result> onError(RequestHeader request, Throwable t) {
        RaygunPlayClient rg = new RaygunPlayClient(apiKey, request);
        rg.SendAsync(t);

        return Promise.<Result>pure(internalServerError(
            views.html.myErrorPage.render(t)
        ));
    }
}

Sending asynchronously

Web projects that use RaygunServletClient can call SendAsync(), to transmit messages asynchronously. When SendAsync is called, the client will continue to perform the sending while control returns to the calling script or servlet. This allows the page to continue rendering and be returned to the end user while the exception message is trasmitted.

SendAsync()

Overloads:

void SendAsync(Throwable throwable)

void SendAsync(Throwable throwable, List tags)

void SendAsync(Throwable throwable, List tags, Map userCustomData)

This provides a huge speedup versus the blocking Send() method, and appears to be near instantaneous from the user's perspective.

No HTTP status code is returned from this method as the calling thread will have terminated by the time the response is returned from the Raygun API. A logging option will be available in future.

This feature is considered to be in Beta, and it is advised to test it in a staging environment before deploying to production. When in production it should be monitored to ensure no spurious behaviour (especially in high traffic scenarios) while the feature is in beta. Feedback is appreciated.

Google app engine: This method will not work from code running on GAE - see the troubleshooting section below.

Custom user data and tags

To attach custom data or tags, use these overloads on Send:

RaygunClient client = new RaygunClient("apikey");
Exception exception;

ArrayList tags = new ArrayList<String>();
tags.add("tag1");

Map<string, int> userCustomData = new HashMap<string, int>();
userCustomData.put("data", 1);

client.Send(exception, tags);
// or
client.Send(exception, tags, userCustomData);

Tags can be null if you only wish to transmit custom data. Send calls can take these objects inside a catch block (if you want one instance to contain specific local variables), or in a global exception handler (if you want every exception to contain a set of tags/custom data, initialized on construction).

Affected user tracking

You can call client.SetUser(RaygunIdentifier) to set the current user's data, which will be displayed in the dashboard. There are two constructor overloads available, both of which requires a unique string as the uniqueUserIdentifier. This should be the user's email address if available, or an internally unique ID representing the users. Any errors containing this string will be considered to come from that user.

The other overload contains all the available properties, some or all of which can be null and can be also be set individually on the RaygunIdentifier object.

The previous method, SetUser(string) has been deprecated as of 1.5.0.

Version tracking

Raygun4Java reads the version of your application from your manifest.mf file in the calling package. It first attempts to read this from Specification-Version, then Implementation-Version if the first doesn't exist.

A SetVersion(string) method is also available to manually specify this version (for instance during testing). It is expected to be in the format X.X.X.X, where X is a positive integer.

Getting/setting/cancelling the error before it is sent

This provider has an OnBeforeSend API to support accessing or mutating the candidate error payload immediately before it is sent, or cancelling the send outright.

This is provided as the public method RaygunClient.SetOnBeforeSend(RaygunOnBeforeSend), which takes an instance of a class that implements the RaygunOnBeforeSend interface. Your class needs a public OnBeforeSend method that takes a RaygunMessage parameter, and returns the same.

By example:

class BeforeSendImplementation implements RaygunOnBeforeSend {
    @Override
    public RaygunMessage OnBeforeSend(RaygunMessage message) {
        // About to post to Raygun, returning the payload as is...
        return message;
    }
}

class MyExceptionHandler implements Thread.UncaughtExceptionHandler {
    public void uncaughtException(Thread t, Throwable e) {
        RaygunClient client = new RaygunClient("paste_your_api_key_here");
        client.SetOnBeforeSend(new BeforeSendImplementation());
        client.Send(e, tags, customData);
    }
}


public class MyProgram {
    public static void main(String[] args) throws Throwable {
        Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
    }
}

In the example above, the overridden `OnBeforeSend` method will log an info message every time an error is sent.

To mutate the error payload, for instance to change the message:

@Override
public RaygunMessage OnBeforeSend(RaygunMessage message) {
    RaygunMessageDetails details = message.getDetails();
    RaygunErrorMessage error = details.getError();
    error.setMessage("Mutated message");

    return message;
}

To cancel the send (prevent the error from reaching the Raygun dashboard) by returning null:

@Override
public RaygunMessage OnBeforeSend(RaygunMessage message) {
    //Cancelling sending message to Raygun...
    return null;
}

Custom error grouping

You can override Raygun's default grouping logic for Java exceptions by setting the grouping key manually in OnBeforeSend (see above):

@Override
public RaygunMessage OnBeforeSend(RaygunMessage message) {
    RaygunMessageDetails details = message.getDetails();
    details.setGroupingKey("foo");
    return message;
}

Any error instances with a certain key will be grouped together. The example above will place all errors within one group (as the key is hardcoded to 'foo'). The grouping key is a String and must be between 1 and 100 characters long. You should send all data you care about (for instance, parts of the exception message, stacktrace frames, class names etc) to a hash function (for instance MD5), then pass that to setGroupingKey.

Troubleshooting

  • When Maven runs the tests locally, Surefire might complain of unsupported major.minor version 51.0 - ensure you have JDK 7 set as your JAVA_HOME, or set the plugin goal for maven-surefire-plugin to be <configuration><jvm>${env.your_jre_7_home}/bin/java.exe</jvm></configuration> in the parent pom.

  • Google App Engine: Raygun4Java is confirmed to work with projects built with GAE, however only limited environment data is available due to JDK library restrictions. The SendAsync methods also will not work, however you can place the Send() call in the Run() body of a background thread, or one of the other threading features in the App Engine API.

Raygun4java GitHub Repository

For complete installation instructions, getting the source code and troubleshooting, visit the GitHub repository here.

Documentation missing?

If we don't have documentation about your desired topic, send us a message and we'll create it for you.