Snowplow Java Tracker 0.5.0 released


We’re excited to announce another release of the Snowplow Java Tracker version 0.5.0
This release comes with a few changes to the Tracker method signatures to support our upcoming Snowplow 0.9.7 release with POST support, bug fixes, and more. Notably, we’ve added a new class for supporting your context data.
I’ll be covering everything mentioned above in more detail:
- Project structure changes
- Collector endpoint changes for POST requests
- The SchemaPayload Class
- Emitter callback
- Configuring the buffer
- Tracker context bug fix
- Miscellaneouss
- Support
1. Project structure changes
We have changed the project structure so that the Java Tracker is now java-tracker-core as a subproject of the root snowplow-java-tracker
project. The structure looks something like this:
snowplow-java-tracker/ |_ build.gradle |_ ... |_ java-tracker-core/ |_ build.gradle |_ ...
This is part of a re-structuring to make space for a java-tracker-server
that we’re looking to add in the future, and to allow code re-use with the Snowplow Android Tracker, which is coming soon. What this means for you, is that some enum classes have been moved from the com.snowplowanalytics.snowplow.tracker
package to com.snowplowanalytics.snowplow.tracker.core
. If you’re pulling the tracker straight from GitHub and you come across any caching warnings, try removing your current Tracker project and do a clean pull.
2. Collector endpoint changes for POST requests
We decided to make a change to the collector endpoint for POST requests, so that the URI path would follow the format /[api_vendor]/[api_version]
. This is similar to how we append /i
to the collector endpoint. So an example of what the URI would look would be:
http://collector.acme.net/com.snowplowanalytics.snowplow/tp2
If requests are being sent as GET, we default to appending the original /i
to the end of the collector URI.
2. The SchemaPayload Class
A new class SchemaPayload
has been added as a wrapper around your custom contexts. The idea is to make sure that each context is a valid self-describing JSON which Snowplow can process. Hence, a SchemaPayload
instance provides two methods setSchema
and setData
. Here’s an example if your context was a simple map:
// Let's say your context is a simple map Map<String, String> contextMap = new HashMap<String, String>(); contextMap.put("someContextKey", "someContextValue"<span class="o">); // Create a SchemaPayload to wrap that context SchemaPayload schemaPayload = new SchemaPayload<span class="o">(); // Set the schema you that describes your context schemaPayload.setSchema("iglu:com.snowplowanalytics.snowplow/my_schema/jsonschema/1-0-0"<span class="o">); // Set the context as the data schemaPayload.setData(contextMap<span class="o">); // All contexts need to be passed in as a list so we add it to one ArrayList<SchemaPayload> contextList = new ArrayList<SchemaPayload>(); contextList.add(schemaPayload<span class="o">); // For completeness, let's add this context to a page view without Base64 encoding tracker.trackPageView("www.mypage.com", "My Page", "www.me.com", contextList<span class="o">);
What this ends up looking like in a JSON format, note the co
property:
{ "schema": "iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-0", "data": [ { "e": "pv", "url": "www.mypage.com", "page": "My Page", "refr": "www.me.com", "aid": "cloudfront", "tna": "AF003", "tv": "java-0.5.0", "dtm": "1407831713559", "co": "{"schema":"iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0","data":[{"schema":"setse","data":{"someContextKey":"someContextValue"}}]}", "tz": "America/Toronto", "p": "pc", "vp": "320x480", "eid": "c7526a7f-a545-431e-a224-277c791111c1" } ] }
The new class also changes the track methods from accepting a context of List<Map>
to List<SchemaPayload>
. Here’s an example of the new method signatures:
// Previous trackPageView(String pageUrl, String pageTitle, String referrer, List<Map> context, double timestamp) // Now trackPageView(String pageUrl, String pageTitle, String referrer, List<SchemaPayload> context, double timestamp)
4. Emitter callback
The Emitter class now supports callbacks for success/failure of sending events. If events fail to send, you can now choose how to handle that failure, by passing in a class using the RequestCallback
interface to the Emitter
object. Here’s an example to make it easier to understand:
Emitter emitter = new Emitter(testURL, HttpMethod.GET, new RequestCallback() { @Override public void onSuccess(int successCount) { System.out.println("Success count for POST/GET:" + successCount<span class="o">); } @Override public void onFailure(int successCount, List<Payload> failedEvent) { System.out.println("Failure, successCount: " + successCount + "nfailedEvent:n" + failedEvent.toString()); } <span class="o">});
If events are all successfully sent, the onSuccess
method returns the number of successful events sent. If there were any failures, the onFailure
method returns the successful events sent (if any) and a list of events that failed to be sent (i.e. the HTTP state code did not return 200).
We’ve also added two new Emitter constructors to support callbacks:
Emitter(String URI, RequestCallback callback) Emitter(String URI, HttpMethod httpMethod, RequestCallback callback)
This is an optional feature, so if you choose to not worry about the failed events, you can still use the original Emitter
constructors:
Emitter(String URI) Emitter(String URI, HttpMethod httpMethod)
5. Configuring the buffer
We’ve changed the default behavior of sending events in this update. When you create an Emitter
and set the HttpMethod
to send GET requests, we default the Emitter to send events instantly upon being tracked. It makes most sense to send GET requests immediately since they cannot be grouped like events sent via POST.
Here is a short example:
// By default BufferOption.Instant is set for GET Emitter emitter = new Emitter("collector.acme.net", HttpMethod.GET<span class="o">); // By default BufferOption.Default is set as the buffer option for POST... Emitter emitter = new Emitter("collector.acme.net", HttpMethod.POST<span class="o">); // ... but we can still change that if we like emitter.setBufferOption(BufferOption.Instant<span class="o">);
6. Tracker context bug fix
There was a bug in our tracking method signatures whereby the context argument was passed as a Map
. We have now fixed this: all signatures expect a List
of contexts, using the new SchemaPayload
as mentioned above. The new type for passing the context is List<SchemaPayload>
.
7. Miscellaneous
We have made a few miscellaneous fixes in this version, including:
- We have added some unit tests for the
Subject
class - Base64 encoding of unstructured event and context JSONs now uses
UTF-8
notUS-ASCII
7. Support
Please get in touch if you need help setting up the Snowplow Java Tracker or want to suggest a new feature. And of course if you find any bugs, please do raise an issue.
For more details on this release, please check out the 0.5.0 Release Notes on GitHub.