From b9755b6ad41d08354978ad3d3185ea91595da91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20M=C3=A4rki?= Date: Wed, 23 Nov 2016 11:13:22 +0100 Subject: [PATCH] MsgPack and BSON Response writer. --- .settings/org.eclipse.jdt.core.prefs | 2 +- build.gradle | 2 + .../daq/queryrest/config/QueryRestConfig.java | 43 ++++++ .../response/PolymorphicResponseMixIn.java | 6 +- .../response/bson/BSONHTTPResponse.java | 69 ++++++++++ .../bson/BSONResponseStreamWriter.java | 41 ++++++ .../bson/BSONTableResponseStreamWriter.java | 64 +++++++++ .../response/csv/CSVResponseStreamWriter.java | 21 ++- .../response/json/JSONHTTPResponse.java | 4 +- .../json/JSONResponseStreamWriter.java | 117 +++++++++-------- .../json/JSONTableResponseStreamWriter.java | 22 +++- .../response/msgpack/MsgPackHTTPResponse.java | 69 ++++++++++ .../msgpack/MsgPackResponseStreamWriter.java | 40 ++++++ .../MsgPackTableResponseStreamWriter.java | 62 +++++++++ .../AbstractQueryRestControllerTableTest.java | 120 +++++++++++++++++ .../AbstractQueryRestControllerTest.java | 124 ++++++++++++++++++ .../BsonQueryRestControllerTableTest.java | 31 +++++ .../BsonQueryRestControllerTest.java | 31 +++++ ...t.java => CSVQueryRestControllerTest.java} | 2 +- ... => JsonQueryRestControllerTableTest.java} | 2 +- ....java => JsonQueryRestControllerTest.java} | 2 +- .../MsgPackQueryRestControllerTableTest.java | 30 +++++ .../MsgPackQueryRestControllerTest.java | 30 +++++ 23 files changed, 864 insertions(+), 70 deletions(-) create mode 100644 src/main/java/ch/psi/daq/queryrest/response/bson/BSONHTTPResponse.java create mode 100644 src/main/java/ch/psi/daq/queryrest/response/bson/BSONResponseStreamWriter.java create mode 100644 src/main/java/ch/psi/daq/queryrest/response/bson/BSONTableResponseStreamWriter.java create mode 100644 src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackHTTPResponse.java create mode 100644 src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackResponseStreamWriter.java create mode 100644 src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackTableResponseStreamWriter.java create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTableTest.java create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTest.java create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTableTest.java create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTest.java rename src/test/java/ch/psi/daq/test/queryrest/controller/{QueryRestControllerCsvTest.java => CSVQueryRestControllerTest.java} (99%) rename src/test/java/ch/psi/daq/test/queryrest/controller/{QueryRestControllerJsonTableTest.java => JsonQueryRestControllerTableTest.java} (99%) rename src/test/java/ch/psi/daq/test/queryrest/controller/{QueryRestControllerJsonTest.java => JsonQueryRestControllerTest.java} (99%) create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTableTest.java create mode 100644 src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTest.java diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index e1c3799..2441ebf 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ # -#Thu Aug 04 12:28:57 CEST 2016 +#Tue Nov 22 17:23:47 CET 2016 org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve diff --git a/build.gradle b/build.gradle index 71f8636..07d08b4 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,8 @@ dependencies { compile libraries.commons_io compile libraries.commons_csv compile libraries.netty_all + compile libraries.bson_jackson + compile libraries.msgpack_jackson testCompile libraries.spring_boot_starter_test testCompile libraries.jsonassert diff --git a/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java b/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java index 3c55e14..11ca027 100644 --- a/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java +++ b/src/main/java/ch/psi/daq/queryrest/config/QueryRestConfig.java @@ -10,6 +10,7 @@ import java.util.function.Function; import javax.annotation.PostConstruct; import javax.annotation.Resource; +import org.msgpack.jackson.dataformat.MessagePackFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; @@ -42,9 +43,16 @@ import ch.psi.daq.queryrest.model.PropertyFilterMixin; import ch.psi.daq.queryrest.query.QueryManager; import ch.psi.daq.queryrest.query.QueryManagerImpl; import ch.psi.daq.queryrest.response.PolymorphicResponseMixIn; +import ch.psi.daq.queryrest.response.bson.BSONResponseStreamWriter; +import ch.psi.daq.queryrest.response.bson.BSONTableResponseStreamWriter; import ch.psi.daq.queryrest.response.csv.CSVResponseStreamWriter; import ch.psi.daq.queryrest.response.json.JSONResponseStreamWriter; import ch.psi.daq.queryrest.response.json.JSONTableResponseStreamWriter; +import ch.psi.daq.queryrest.response.msgpack.MsgPackResponseStreamWriter; +import ch.psi.daq.queryrest.response.msgpack.MsgPackTableResponseStreamWriter; + +import de.undercouch.bson4jackson.BsonFactory; +import de.undercouch.bson4jackson.BsonGenerator; @Configuration @Import(value = QueryRestConfigCORS.class) @@ -119,6 +127,21 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { public JsonFactory jsonFactory() { return new JsonFactory(); } + + @Bean + public BsonFactory bsonFactory() { + BsonFactory factory = new BsonFactory(); + factory.enable(BsonGenerator.Feature.ENABLE_STREAMING); + + return factory; + } + + @Bean + public MessagePackFactory nessagePackFactory() { + MessagePackFactory factory = new MessagePackFactory(); + + return factory; + } @Bean public Function queryAnalizerFactory() { @@ -134,6 +157,26 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter { public JSONTableResponseStreamWriter jsonTableResponseStreamWriter() { return new JSONTableResponseStreamWriter(); } + + @Bean + public BSONResponseStreamWriter bsonResponseStreamWriter() { + return new BSONResponseStreamWriter(); + } + + @Bean + public BSONTableResponseStreamWriter bsonTableResponseStreamWriter() { + return new BSONTableResponseStreamWriter(); + } + + @Bean + public MsgPackResponseStreamWriter msgPackResponseStreamWriter() { + return new MsgPackResponseStreamWriter(); + } + + @Bean + public MsgPackTableResponseStreamWriter msgPackTableResponseStreamWriter() { + return new MsgPackTableResponseStreamWriter(); + } @Bean public CSVResponseStreamWriter csvResponseStreamWriter() { diff --git a/src/main/java/ch/psi/daq/queryrest/response/PolymorphicResponseMixIn.java b/src/main/java/ch/psi/daq/queryrest/response/PolymorphicResponseMixIn.java index 2dcac47..441f6e4 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/PolymorphicResponseMixIn.java +++ b/src/main/java/ch/psi/daq/queryrest/response/PolymorphicResponseMixIn.java @@ -4,8 +4,10 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import ch.psi.daq.queryrest.response.bson.BSONHTTPResponse; import ch.psi.daq.queryrest.response.csv.CSVHTTPResponse; import ch.psi.daq.queryrest.response.json.JSONHTTPResponse; +import ch.psi.daq.queryrest.response.msgpack.MsgPackHTTPResponse; @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, @@ -13,7 +15,9 @@ import ch.psi.daq.queryrest.response.json.JSONHTTPResponse; property = "format") @JsonSubTypes({ @Type(value = JSONHTTPResponse.class, name = JSONHTTPResponse.FORMAT), - @Type(value = CSVHTTPResponse.class, name = CSVHTTPResponse.FORMAT) + @Type(value = BSONHTTPResponse.class, name = BSONHTTPResponse.FORMAT), + @Type(value = MsgPackHTTPResponse.class, name = MsgPackHTTPResponse.FORMAT), + @Type(value = CSVHTTPResponse.class, name = CSVHTTPResponse.FORMAT) }) // see: http://stackoverflow.com/questions/24631923/alternative-to-jackson-jsonsubtypes public abstract class PolymorphicResponseMixIn { diff --git a/src/main/java/ch/psi/daq/queryrest/response/bson/BSONHTTPResponse.java b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONHTTPResponse.java new file mode 100644 index 0000000..99f06eb --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONHTTPResponse.java @@ -0,0 +1,69 @@ +package ch.psi.daq.queryrest.response.bson; + +import java.io.OutputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.tuple.Triple; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.http.MediaType; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueries; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.operation.Compression; +import ch.psi.daq.domain.query.response.ResponseFormat; +import ch.psi.daq.queryrest.query.QueryManager; +import ch.psi.daq.queryrest.response.AbstractHTTPResponse; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONHTTPResponse; + +public class BSONHTTPResponse extends AbstractHTTPResponse { + private static final Logger LOGGER = LoggerFactory.getLogger(BSONHTTPResponse.class); + + public static final String FORMAT = "bson"; + public static final String CONTENT_TYPE = MediaType.APPLICATION_OCTET_STREAM_VALUE; + + public BSONHTTPResponse() { + super(ResponseFormat.BSON); + } + + public BSONHTTPResponse(Compression compression) { + this(); + setCompression(compression); + } + + @Override + public void respond(ApplicationContext context, DAQQueries queries, HttpServletResponse response) throws Exception { + OutputStream out = handleCompressionAndResponseHeaders(response, CONTENT_TYPE); + + boolean hasMapping = JSONHTTPResponse.validateQueries(queries); + + try { + LOGGER.debug("Executing query '{}'", queries); + + QueryManager queryManager = context.getBean(QueryManager.class); + ResponseStreamWriter streamWriter; + if (hasMapping) { + streamWriter = context.getBean(BSONTableResponseStreamWriter.class); + } else { + streamWriter = context.getBean(BSONResponseStreamWriter.class); + } + + // execute query + List>>> result = + queryManager.getEvents(queries); + // write the response back to the client using java 8 streams + streamWriter.respond(result, out, this); + } catch (Exception e) { + LOGGER.error("Failed to execute query '{}'.", queries, e); + throw e; + } + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/bson/BSONResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONResponseStreamWriter.java new file mode 100644 index 0000000..69ad3e1 --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONResponseStreamWriter.java @@ -0,0 +1,41 @@ +package ch.psi.daq.queryrest.response.bson; + +import java.io.OutputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import javax.annotation.Resource; +import javax.servlet.ServletResponse; + +import org.apache.commons.lang3.tuple.Triple; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONResponseStreamWriter; + +import de.undercouch.bson4jackson.BsonFactory; + +/** + * Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse} + * of the current request. + */ +public class BSONResponseStreamWriter implements ResponseStreamWriter { + + @Resource + private BsonFactory bsonFactory; + + @Resource + private ObjectMapper mapper; + + @Override + public void respond(final List>>> results, + final OutputStream out, final Response response) throws Exception { + JSONResponseStreamWriter.respond(bsonFactory, mapper, results, out, response); + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/bson/BSONTableResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONTableResponseStreamWriter.java new file mode 100644 index 0000000..c8912ec --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/bson/BSONTableResponseStreamWriter.java @@ -0,0 +1,64 @@ +package ch.psi.daq.queryrest.response.bson; + +import java.io.OutputStream; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.servlet.ServletResponse; + +import org.apache.commons.lang3.tuple.Triple; +import org.springframework.context.ApplicationContext; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.operation.Aggregation; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.config.QueryRestConfig; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONTableResponseStreamWriter; + +import de.undercouch.bson4jackson.BsonFactory; + +/** + * Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse} + * of the current request. + */ +public class BSONTableResponseStreamWriter implements ResponseStreamWriter { + + @Resource + private ApplicationContext context; + + @Resource + private BsonFactory bsonFactory; + + @Resource + private ObjectMapper mapper; + + @Resource(name = QueryRestConfig.BEAN_NAME_DEFAULT_RESPONSE_AGGREGATIONS) + private Set defaultResponseAggregations; + + private Set defaultResponseAggregationsStr; + + @PostConstruct + public void afterPropertiesSet() { + defaultResponseAggregationsStr = + defaultResponseAggregations.stream().map(Aggregation::name) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + @Override + public void respond(final List>>> results, + final OutputStream out, final Response response) throws Exception { + JSONTableResponseStreamWriter.respond(context, bsonFactory, mapper, defaultResponseAggregationsStr, results, out, + response); + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/csv/CSVResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/csv/CSVResponseStreamWriter.java index 00f8189..a412e5c 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/csv/CSVResponseStreamWriter.java +++ b/src/main/java/ch/psi/daq/queryrest/response/csv/CSVResponseStreamWriter.java @@ -61,24 +61,25 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter { public static final char DELIMITER_CHANNELNAME_FIELDNAME = '.'; public static final String EMPTY_VALUE = ""; public static final String FIELDNAME_EXTREMA = "extrema"; - private static final Function KEY_PROVIDER = (event) -> new ChannelName(event.getChannel(), event.getBackend()); + private static final Function KEY_PROVIDER = (event) -> new ChannelName(event.getChannel(), + event.getBackend()); // try to match sync data (bsread) with non sync data (epics) based on the time usin 10 millis // buckets. private static final ToLongFunction MATCHER_PROVIDER = (event) -> event.getGlobalMillis() / 10L; @Resource private ApplicationContext context; - + @Resource private Function queryAnalizerFactory; @Override public void respond(final List>>> results, final OutputStream out, final Response response) throws Exception { - if(results.size() > 1){ + if (results.size() > 1) { throw new IllegalStateException("CSV format does not allow for multiple queries."); } - + AtomicReference exception = new AtomicReference<>(); final Map> streams = new LinkedHashMap<>(results.size()); @@ -96,7 +97,7 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter { .sequential() .forEach(triple -> { backendQueryRef.compareAndSet(null, triple.getLeft()); - + if (triple.getRight() instanceof Stream) { setupChannelColumns(query, triple.getLeft(), triple.getMiddle(), header, accessors); @@ -115,7 +116,7 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter { // online matching of the stream's content StreamMatcher> streamMatcher = new StreamMatcher<>( - KEY_PROVIDER, + KEY_PROVIDER, MATCHER_PROVIDER, new MapCreator<>(), new MapFiller<>(), @@ -163,6 +164,14 @@ public class CSVResponseStreamWriter implements ResponseStreamWriter { writer.close(); } + if (streamMatcher != null) { + try { + streamMatcher.close(); + } catch (Throwable t) { + LOGGER.error("Something went wrong while closing stream matcher for csv response writer.", t); + } + } + if (csvFilePrinter != null) { csvFilePrinter.close(); } diff --git a/src/main/java/ch/psi/daq/queryrest/response/json/JSONHTTPResponse.java b/src/main/java/ch/psi/daq/queryrest/response/json/JSONHTTPResponse.java index 47ba852..5968180 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/json/JSONHTTPResponse.java +++ b/src/main/java/ch/psi/daq/queryrest/response/json/JSONHTTPResponse.java @@ -46,7 +46,7 @@ public class JSONHTTPResponse extends AbstractHTTPResponse { public void respond(ApplicationContext context, DAQQueries queries, HttpServletResponse response) throws Exception { OutputStream out = handleCompressionAndResponseHeaders(response, CONTENT_TYPE); - boolean hasMapping = validateQueries(queries); + boolean hasMapping = JSONHTTPResponse.validateQueries(queries); try { LOGGER.debug("Executing query '{}'", queries); @@ -71,7 +71,7 @@ public class JSONHTTPResponse extends AbstractHTTPResponse { } - protected boolean validateQueries(DAQQueries queries) { + public static boolean validateQueries(DAQQueries queries) { boolean hasMapping = false; for (DAQQueryElement query : queries) { diff --git a/src/main/java/ch/psi/daq/queryrest/response/json/JSONResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/json/JSONResponseStreamWriter.java index 2533ea5..3ac7f34 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/json/JSONResponseStreamWriter.java +++ b/src/main/java/ch/psi/daq/queryrest/response/json/JSONResponseStreamWriter.java @@ -51,60 +51,7 @@ public class JSONResponseStreamWriter implements ResponseStreamWriter { @Override public void respond(final List>>> results, final OutputStream out, final Response response) throws Exception { - AtomicReference exception = new AtomicReference<>(); - JsonGenerator generator = jsonFactory.createGenerator(out, JsonEncoding.UTF8); - - try { - if (results.size() > 1) { - generator.writeStartArray(); - } - - results - .forEach(entryy -> { - DAQQueryElement daqQuery = entryy.getKey(); - Set includedFields = getFields(daqQuery, true); - ObjectWriter writer = configureWriter(includedFields, mapper); - - try { - generator.writeStartArray(); - - entryy.getValue() - /* ensure elements are sequentially written */ - .sequential() - .forEach( - triple -> { - try { - generator.writeStartObject(); - generator.writeFieldName(QueryField.channel.name()); - writer.writeValue(generator, triple.getMiddle()); - generator.writeFieldName(DATA_RESP_FIELD); - writer.writeValue(generator, triple.getRight()); - generator.writeEndObject(); - } catch (Exception e) { - LOGGER.error("Could not write channel name of channel '{}'", triple.getMiddle(), - e); - exception.compareAndSet(null, e); - } - }); - - generator.writeEndArray(); - } catch (Exception e) { - LOGGER.error("Exception while writing json for '{}'", daqQuery.getChannels(), e); - exception.compareAndSet(null, e); - } - }); - } finally { - if (results.size() > 1) { - generator.writeEndArray(); - } - - generator.flush(); - generator.close(); - } - - if (exception.get() != null) { - throw exception.get(); - } + respond(jsonFactory, mapper, results, out, response); } public static Set getFields(DAQQueryElement query, boolean removeIdentifiers) { @@ -138,6 +85,68 @@ public class JSONResponseStreamWriter implements ResponseStreamWriter { return includedFields; } + + public static void respond(final JsonFactory factory, final ObjectMapper mapper, final List>>> results, + final OutputStream out, final Response response) throws Exception { + AtomicReference exception = new AtomicReference<>(); + JsonGenerator generator = factory.createGenerator(out, JsonEncoding.UTF8); + + try { + if (results.size() > 1) { + generator.writeStartArray(); + } + + results + .forEach(entryy -> { + DAQQueryElement daqQuery = entryy.getKey(); + Set includedFields = getFields(daqQuery, true); + ObjectWriter writer = configureWriter(includedFields, mapper); + + try { + generator.writeStartArray(); + + entryy.getValue() + /* ensure elements are sequentially written */ + .sequential() + .forEach( + triple -> { + try { + generator.writeStartObject(); + generator.writeFieldName(QueryField.channel.name()); + writer.writeValue(generator, triple.getMiddle()); + generator.writeFieldName(DATA_RESP_FIELD); + writer.writeValue(generator, triple.getRight()); + generator.writeEndObject(); + } catch (Exception e) { + LOGGER.error("Could not write channel name of channel '{}'", triple.getMiddle(), + e); + exception.compareAndSet(null, e); + } finally{ + if(triple.getRight() instanceof Stream){ + ((Stream)(triple.getRight())).close(); + } + } + }); + + generator.writeEndArray(); + } catch (Exception e) { + LOGGER.error("Exception while writing json for '{}'", daqQuery.getChannels(), e); + exception.compareAndSet(null, e); + } + }); + } finally { + if (results.size() > 1) { + generator.writeEndArray(); + } + + generator.flush(); + generator.close(); + } + + if (exception.get() != null) { + throw exception.get(); + } + } /** * Configures the writer dynamically by including the fields which should be included in the diff --git a/src/main/java/ch/psi/daq/queryrest/response/json/JSONTableResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/json/JSONTableResponseStreamWriter.java index 9970759..7ccb458 100644 --- a/src/main/java/ch/psi/daq/queryrest/response/json/JSONTableResponseStreamWriter.java +++ b/src/main/java/ch/psi/daq/queryrest/response/json/JSONTableResponseStreamWriter.java @@ -92,11 +92,18 @@ public class JSONTableResponseStreamWriter implements ResponseStreamWriter { @Override public void respond(final List>>> results, + final OutputStream out, final Response response) throws Exception { + respond(context, jsonFactory, mapper, defaultResponseAggregationsStr, results, out, response); + } + + + public static void respond(final ApplicationContext context, final JsonFactory factory, + final ObjectMapper mapper, final Set defaultResponseAggregationsStr, + final List>>> results, final OutputStream out, final Response response) throws Exception { AtomicReference exception = new AtomicReference<>(); - - JsonGenerator generator = jsonFactory.createGenerator(out, JsonEncoding.UTF8); - + JsonGenerator generator = factory.createGenerator(out, JsonEncoding.UTF8); + try { if (results.size() > 1) { generator.writeStartArray(); @@ -177,6 +184,15 @@ public class JSONTableResponseStreamWriter implements ResponseStreamWriter { } catch (Exception e) { LOGGER.error("Exception while writing json for '{}'", daqQuery.getChannels(), e); exception.compareAndSet(null, e); + } finally { + if (streamMatcher != null) { + try { + streamMatcher.close(); + } catch (Throwable t) { + LOGGER.error( + "Something went wrong while closing stream matcher for JSON table response writer.", t); + } + } } }); } catch (IOException e) { diff --git a/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackHTTPResponse.java b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackHTTPResponse.java new file mode 100644 index 0000000..6130bc5 --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackHTTPResponse.java @@ -0,0 +1,69 @@ +package ch.psi.daq.queryrest.response.msgpack; + +import java.io.OutputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.tuple.Triple; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.http.MediaType; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueries; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.operation.Compression; +import ch.psi.daq.domain.query.response.ResponseFormat; +import ch.psi.daq.queryrest.query.QueryManager; +import ch.psi.daq.queryrest.response.AbstractHTTPResponse; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONHTTPResponse; + +public class MsgPackHTTPResponse extends AbstractHTTPResponse { + private static final Logger LOGGER = LoggerFactory.getLogger(MsgPackHTTPResponse.class); + + public static final String FORMAT = "msgp"; + public static final String CONTENT_TYPE = MediaType.APPLICATION_OCTET_STREAM_VALUE; + + public MsgPackHTTPResponse() { + super(ResponseFormat.MSGP); + } + + public MsgPackHTTPResponse(Compression compression) { + this(); + setCompression(compression); + } + + @Override + public void respond(ApplicationContext context, DAQQueries queries, HttpServletResponse response) throws Exception { + OutputStream out = handleCompressionAndResponseHeaders(response, CONTENT_TYPE); + + boolean hasMapping = JSONHTTPResponse.validateQueries(queries); + + try { + LOGGER.debug("Executing query '{}'", queries); + + QueryManager queryManager = context.getBean(QueryManager.class); + ResponseStreamWriter streamWriter; + if (hasMapping) { + streamWriter = context.getBean(MsgPackTableResponseStreamWriter.class); + } else { + streamWriter = context.getBean(MsgPackResponseStreamWriter.class); + } + + // execute query + List>>> result = + queryManager.getEvents(queries); + // write the response back to the client using java 8 streams + streamWriter.respond(result, out, this); + } catch (Exception e) { + LOGGER.error("Failed to execute query '{}'.", queries, e); + throw e; + } + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackResponseStreamWriter.java new file mode 100644 index 0000000..7a34f67 --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackResponseStreamWriter.java @@ -0,0 +1,40 @@ +package ch.psi.daq.queryrest.response.msgpack; + +import java.io.OutputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import javax.annotation.Resource; +import javax.servlet.ServletResponse; + +import org.apache.commons.lang3.tuple.Triple; +import org.msgpack.jackson.dataformat.MessagePackFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONResponseStreamWriter; + +/** + * Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse} + * of the current request. + */ +public class MsgPackResponseStreamWriter implements ResponseStreamWriter { + + @Resource + private MessagePackFactory msgPackFactory; + + @Resource + private ObjectMapper mapper; + + @Override + public void respond(final List>>> results, + final OutputStream out, final Response response) throws Exception { + JSONResponseStreamWriter.respond(msgPackFactory, mapper, results, out, response); + } +} diff --git a/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackTableResponseStreamWriter.java b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackTableResponseStreamWriter.java new file mode 100644 index 0000000..7f25f67 --- /dev/null +++ b/src/main/java/ch/psi/daq/queryrest/response/msgpack/MsgPackTableResponseStreamWriter.java @@ -0,0 +1,62 @@ +package ch.psi.daq.queryrest.response.msgpack; + +import java.io.OutputStream; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.servlet.ServletResponse; + +import org.apache.commons.lang3.tuple.Triple; +import org.msgpack.jackson.dataformat.MessagePackFactory; +import org.springframework.context.ApplicationContext; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.json.ChannelName; +import ch.psi.daq.domain.query.DAQQueryElement; +import ch.psi.daq.domain.query.backend.BackendQuery; +import ch.psi.daq.domain.query.operation.Aggregation; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.config.QueryRestConfig; +import ch.psi.daq.queryrest.response.ResponseStreamWriter; +import ch.psi.daq.queryrest.response.json.JSONTableResponseStreamWriter; + +/** + * Takes a Java 8 stream and writes it to the output stream provided by the {@link ServletResponse} + * of the current request. + */ +public class MsgPackTableResponseStreamWriter implements ResponseStreamWriter { + + @Resource + private ApplicationContext context; + + @Resource + private MessagePackFactory msgPackFactory; + + @Resource + private ObjectMapper mapper; + + @Resource(name = QueryRestConfig.BEAN_NAME_DEFAULT_RESPONSE_AGGREGATIONS) + private Set defaultResponseAggregations; + + private Set defaultResponseAggregationsStr; + + @PostConstruct + public void afterPropertiesSet() { + defaultResponseAggregationsStr = + defaultResponseAggregations.stream().map(Aggregation::name) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + + @Override + public void respond(final List>>> results, + final OutputStream out, final Response response) throws Exception { + JSONTableResponseStreamWriter.respond(context, msgPackFactory, mapper, defaultResponseAggregationsStr, results, out, response); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTableTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTableTest.java new file mode 100644 index 0000000..d39575b --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTableTest.java @@ -0,0 +1,120 @@ +package ch.psi.daq.test.queryrest.controller; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.junit.After; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.common.time.TimeUtils; +import ch.psi.daq.domain.DataEvent; +import ch.psi.daq.domain.backend.Backend; +import ch.psi.daq.domain.config.DomainConfig; +import ch.psi.daq.domain.json.ChannelEventTableImpl; +import ch.psi.daq.domain.query.DAQQuery; +import ch.psi.daq.domain.query.mapping.Mapping; +import ch.psi.daq.domain.query.operation.QueryField; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.domain.request.range.RequestRangePulseId; +import ch.psi.daq.test.queryrest.AbstractDaqRestTest; + +/** + * Tests the {@link DaqController} implementation. + */ +public abstract class AbstractQueryRestControllerTableTest extends AbstractDaqRestTest { + + public static final String TEST_CHANNEL_01 = "testChannel1"; + public static final String TEST_CHANNEL_02 = "testChannel2"; + public static final String TEST_CHANNEL_WAVEFORM_01 = "testChannelWaveform1"; + public static final String TEST_CHANNEL_WAVEFORM_02 = "testChannelWaveform2"; + public static final String[] TEST_CHANNEL_NAMES = new String[] {TEST_CHANNEL_01, TEST_CHANNEL_02}; + + @Resource(name = DomainConfig.BEAN_NAME_BACKEND_DEFAULT) + private Backend backend; + + @After + public void tearDown() throws Exception {} + + protected abstract ObjectMapper getResponseMapper(); + + protected abstract Response getResponse(); + + @Test + public void testPulseRangeQuery() throws Exception { + DAQQuery request = new DAQQuery( + new RequestRangePulseId( + 100, + 101), + TEST_CHANNEL_NAMES); + request.setMapping(new Mapping()); + request.addField(QueryField.pulseId); + request.addField(QueryField.globalSeconds); + request.addField(QueryField.globalMillis); + request.addField(QueryField.iocSeconds); + request.addField(QueryField.iocMillis); + request.addField(QueryField.value); + request.setResponse(getResponse()); + + String content = mapper.writeValueAsString(request); + System.out.println(content); + + MvcResult result = this.mockMvc + .perform(MockMvcRequestBuilders + .post(DomainConfig.PATH_QUERY) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + byte[] responseBytes = result.getResponse().getContentAsByteArray(); + System.out.println("ResponseSize: "+responseBytes.length); + ChannelEventTableImpl table = getResponseMapper().readValue(responseBytes, ChannelEventTableImpl.class); + + assertEquals(2, table.size()); + List events = table.getEvents(0).collect(Collectors.toList()); + assertEquals(2, events.size()); + DataEvent event = events.get(0); + assertEquals(TEST_CHANNEL_01, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(100, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 0), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 0), event.getIocTime()); + assertEquals(100, event.getValue(Number.class).longValue()); + event = events.get(1); + assertEquals(TEST_CHANNEL_02, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(100, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 0), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 0), event.getIocTime()); + assertEquals(100, event.getValue(Number.class).longValue()); + + events = table.getEvents(1).collect(Collectors.toList()); + assertEquals(2, events.size()); + event = events.get(0); + assertEquals(TEST_CHANNEL_01, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(101, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getIocTime()); + assertEquals(101, event.getValue(Number.class).longValue()); + event = events.get(1); + assertEquals(TEST_CHANNEL_02, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(101, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getIocTime()); + assertEquals(101, event.getValue(Number.class).longValue()); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTest.java new file mode 100644 index 0000000..7672ba4 --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/AbstractQueryRestControllerTest.java @@ -0,0 +1,124 @@ +package ch.psi.daq.test.queryrest.controller; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.annotation.Resource; + +import org.junit.After; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.common.time.TimeUtils; +import ch.psi.daq.domain.DataEvent; +import ch.psi.daq.domain.backend.Backend; +import ch.psi.daq.domain.config.DomainConfig; +import ch.psi.daq.domain.json.ChannelEventsImpl; +import ch.psi.daq.domain.json.ChannelEventsList; +import ch.psi.daq.domain.query.DAQQuery; +import ch.psi.daq.domain.query.operation.QueryField; +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.domain.request.range.RequestRangePulseId; +import ch.psi.daq.test.queryrest.AbstractDaqRestTest; + +/** + * Tests the {@link DaqController} implementation. + */ +public abstract class AbstractQueryRestControllerTest extends AbstractDaqRestTest { + + public static final String TEST_CHANNEL_01 = "testChannel1"; + public static final String TEST_CHANNEL_02 = "testChannel2"; + public static final String TEST_CHANNEL_WAVEFORM_01 = "testChannelWaveform1"; + public static final String[] TEST_CHANNEL_NAMES = new String[] {TEST_CHANNEL_01, TEST_CHANNEL_02}; + + @Resource(name = DomainConfig.BEAN_NAME_BACKEND_DEFAULT) + private Backend backend; + + @After + public void tearDown() throws Exception {} + + protected abstract ObjectMapper getResponseMapper(); + + protected abstract Response getResponse(); + + @Test + public void testPulseRangeQuery() throws Exception { + DAQQuery request = new DAQQuery( + new RequestRangePulseId( + 100, + 101), + TEST_CHANNEL_NAMES); + request.addField(QueryField.pulseId); + request.addField(QueryField.globalSeconds); + request.addField(QueryField.globalMillis); + request.addField(QueryField.iocSeconds); + request.addField(QueryField.iocMillis); + request.addField(QueryField.value); + request.setResponse(getResponse()); + + String content = mapper.writeValueAsString(request); + System.out.println(content); + + MvcResult result = this.mockMvc + .perform(MockMvcRequestBuilders + .post(DomainConfig.PATH_QUERY) + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + byte[] responseBytes = result.getResponse().getContentAsByteArray(); + System.out.println("ResponseSize: "+responseBytes.length); + ChannelEventsList eventsList = getResponseMapper().readValue(responseBytes, ChannelEventsList.class); + + assertEquals(2, eventsList.size()); + ChannelEventsImpl chEvents = eventsList.get(0); + assertEquals(TEST_CHANNEL_01, chEvents.getChannel().getName()); + assertEquals(Backend.SF_DATABUFFER, chEvents.getChannel().getBackend()); + List events = chEvents.getEvents().collect(Collectors.toList()); + assertEquals(2, events.size()); + DataEvent event = events.get(0); + assertEquals(TEST_CHANNEL_01, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(100, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 0), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 0), event.getIocTime()); + assertEquals(100, event.getValue(Number.class).longValue()); + event = events.get(1); + assertEquals(TEST_CHANNEL_01, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(101, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getIocTime()); + assertEquals(101, event.getValue(Number.class).longValue()); + + chEvents = eventsList.get(1); + assertEquals(TEST_CHANNEL_02, chEvents.getChannel().getName()); + assertEquals(Backend.SF_DATABUFFER, chEvents.getChannel().getBackend()); + events = chEvents.getEvents().collect(Collectors.toList()); + assertEquals(2, events.size()); + event = events.get(0); + assertEquals(TEST_CHANNEL_02, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(100, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 0), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 0), event.getIocTime()); + assertEquals(100, event.getValue(Number.class).longValue()); + event = events.get(1); + assertEquals(TEST_CHANNEL_02, event.getChannel()); + assertEquals(Backend.SF_DATABUFFER, event.getBackend()); + assertEquals(101, event.getPulseId()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getGlobalTime()); + assertEquals(TimeUtils.getTime(1, 10000000), event.getIocTime()); + assertEquals(101, event.getValue(Number.class).longValue()); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTableTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTableTest.java new file mode 100644 index 0000000..c353bab --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTableTest.java @@ -0,0 +1,31 @@ +package ch.psi.daq.test.queryrest.controller; + +import org.junit.After; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.bson.BSONHTTPResponse; + +import de.undercouch.bson4jackson.BsonFactory; + +/** + * Tests the {@link DaqController} implementation. + */ +public class BsonQueryRestControllerTableTest extends AbstractQueryRestControllerTableTest { + + private ObjectMapper responseMapper = new ObjectMapper(new BsonFactory()); + + @After + public void tearDown() throws Exception {} + + @Override + protected ObjectMapper getResponseMapper(){ + return responseMapper; + } + + @Override + protected Response getResponse() { + return new BSONHTTPResponse(); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTest.java new file mode 100644 index 0000000..56303c7 --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/BsonQueryRestControllerTest.java @@ -0,0 +1,31 @@ +package ch.psi.daq.test.queryrest.controller; + +import org.junit.After; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.bson.BSONHTTPResponse; + +import de.undercouch.bson4jackson.BsonFactory; + +/** + * Tests the {@link DaqController} implementation. + */ +public class BsonQueryRestControllerTest extends AbstractQueryRestControllerTest { + + private ObjectMapper responseMapper = new ObjectMapper(new BsonFactory()); + + @After + public void tearDown() throws Exception {} + + @Override + protected ObjectMapper getResponseMapper(){ + return responseMapper; + } + + @Override + protected Response getResponse() { + return new BSONHTTPResponse(); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerCsvTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/CSVQueryRestControllerTest.java similarity index 99% rename from src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerCsvTest.java rename to src/test/java/ch/psi/daq/test/queryrest/controller/CSVQueryRestControllerTest.java index ffe6992..0f109f3 100644 --- a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerCsvTest.java +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/CSVQueryRestControllerTest.java @@ -44,7 +44,7 @@ import ch.psi.daq.test.queryrest.AbstractDaqRestTest; /** * Tests the {@link DaqController} implementation. */ -public class QueryRestControllerCsvTest extends AbstractDaqRestTest { +public class CSVQueryRestControllerTest extends AbstractDaqRestTest { public static final String TEST_CHANNEL = "testChannel"; public static final String TEST_CHANNEL_01 = TEST_CHANNEL + "1"; diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTableTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTableTest.java similarity index 99% rename from src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTableTest.java rename to src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTableTest.java index f340047..3e1e97e 100644 --- a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTableTest.java +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTableTest.java @@ -41,7 +41,7 @@ import ch.psi.daq.test.queryrest.AbstractDaqRestTest; /** * Tests the {@link DaqController} implementation. */ -public class QueryRestControllerJsonTableTest extends AbstractDaqRestTest { +public class JsonQueryRestControllerTableTest extends AbstractDaqRestTest { public static final String TEST_CHANNEL_01 = "testChannel1"; public static final String TEST_CHANNEL_02 = "testChannel2"; diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTest.java similarity index 99% rename from src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTest.java rename to src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTest.java index 3861149..dab1ca2 100644 --- a/src/test/java/ch/psi/daq/test/queryrest/controller/QueryRestControllerJsonTest.java +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/JsonQueryRestControllerTest.java @@ -38,7 +38,7 @@ import ch.psi.daq.test.queryrest.AbstractDaqRestTest; /** * Tests the {@link DaqController} implementation. */ -public class QueryRestControllerJsonTest extends AbstractDaqRestTest { +public class JsonQueryRestControllerTest extends AbstractDaqRestTest { public static final String TEST_CHANNEL_01 = "testChannel1"; public static final String TEST_CHANNEL_02 = "testChannel2"; diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTableTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTableTest.java new file mode 100644 index 0000000..37d47d0 --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTableTest.java @@ -0,0 +1,30 @@ +package ch.psi.daq.test.queryrest.controller; + +import org.junit.After; +import org.msgpack.jackson.dataformat.MessagePackFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.msgpack.MsgPackHTTPResponse; + +/** + * Tests the {@link DaqController} implementation. + */ +public class MsgPackQueryRestControllerTableTest extends AbstractQueryRestControllerTableTest { + + private ObjectMapper responseMapper = new ObjectMapper(new MessagePackFactory()); + + @After + public void tearDown() throws Exception {} + + @Override + protected ObjectMapper getResponseMapper(){ + return responseMapper; + } + + @Override + protected Response getResponse() { + return new MsgPackHTTPResponse(); + } +} diff --git a/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTest.java b/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTest.java new file mode 100644 index 0000000..f8d0347 --- /dev/null +++ b/src/test/java/ch/psi/daq/test/queryrest/controller/MsgPackQueryRestControllerTest.java @@ -0,0 +1,30 @@ +package ch.psi.daq.test.queryrest.controller; + +import org.junit.After; +import org.msgpack.jackson.dataformat.MessagePackFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.psi.daq.domain.query.response.Response; +import ch.psi.daq.queryrest.response.msgpack.MsgPackHTTPResponse; + +/** + * Tests the {@link DaqController} implementation. + */ +public class MsgPackQueryRestControllerTest extends AbstractQueryRestControllerTest { + + private ObjectMapper responseMapper = new ObjectMapper(new MessagePackFactory()); + + @After + public void tearDown() throws Exception {} + + @Override + protected ObjectMapper getResponseMapper(){ + return responseMapper; + } + + @Override + protected Response getResponse() { + return new MsgPackHTTPResponse(); + } +}