When requesting a single com.codahale.metrics.Meter
via Jersey-REST-Service, Jackson is doing just fine and serializes the Meter to (formatting done by me)
{
"count":0,
"fiveMinuteRate":0.0,
"fifteenMinuteRate":0.0,
"oneMinuteRate":0.0,
"meanRate":0.0
}
When requesting the same Meter contained inside a Map<String, Metric>
, Jackson complaines:
No serializer found for class com.codahale.metrics.Meter and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap["testMetric"])
I could just make my resource-method return the String that the ObjectMapper
is able to create (see below), but I would like to keep my method returning Map<String, Metric>
.
Why can't Jackson figure it out on its own? How can I make Jackson realize that it knows how to serialize the Object? How can I check the configuration of the ObjectMapper used by Jersey?
I have verified that the Map is not empty and that the Meter
is acutally there.
When I create a vanilla ObjectMapper
and serialize the Map
ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString( myMetricMap );
it works just fine:
{
"testMetric":
{
"count":0,
"fiveMinuteRate":0.0,
"fifteenMinuteRate":0.0,
"oneMinuteRate":0.0,
"meanRate":0.0
}
}
dropwizard-metrics
provides a metrics-json
-Package that includes Serializers for Metrics and HealthChecks. Unfortunately, due to a dependency mess, I cannot use it.
EDIT:
As it was suggested in the comments, I've tried to serialize a Map<String, Meter>
- and it worked!
To summarize:
public interface Metric {
// Empty Marker Interface
}
public class Meter implements Metric {
...
}
@Path("/")
@Produces( MediaType.APPLICATION_JSON )
public MetricsResource {
@GET
@Path("metric/{metricName}")
public Metric getMetric( @PathParam String metricName ) {
// Works!
return MetricsService.getMetric( metricName );
}
@GET
@Path("metricsAsString")
public String getMetricsAsString()
{
// Works!
return (new ObjectMapper()).writeValueAsString(
MetricsService.getMetrics());
}
@GET
@Path("meters")
public Map<String, Meter> getMeters()
{
// Works!
return MetricsService.getMeters();
}
@GET
@Path("metrics")
public Map<String, Metric> getMetrics()
{
// Fails!
return metricsService.getMetrics();
}
I suppose that jackson is not determining the concrete Type when implicitly serializing, but is trying to serialize based on the (marker) Interface Metric
.