ATEST-242

This commit is contained in:
Fabian Märki
2015-10-13 13:18:04 +02:00
parent e9a60664de
commit 1c1ddf773a
5 changed files with 67 additions and 49 deletions

View File

@ -20,6 +20,26 @@ Following files define and describe application properties:
It is possible to overwrite properties by defining new values in `${HOME}/.config/daq/queryrest.properties`
## Maven
Upload jar to the Maven repository (from ch.psi.daq.buildall):
```bash
./gradlew ch.psi.daq.queryrest:uploadArchives
```
## DropIt
Upload jar DropIt (from ch.psi.daq.buildall):
```bash
./gradlew ch.psi.daq.queryrest:dropIt -x test
```
## Local Instance
[DAQLocal](https://github.psi.ch/projects/ST/repos/ch.psi.daq.daqlocal/browse) provides a local instance of the DAQ system for testing purposes (allowing users/developers to verify their code before they come to PSI to do their research and interact with the DAQ cluster).
<a name="rest_interface"/>
# REST Interface

View File

@ -18,10 +18,6 @@ applicationDefaultJvmArgs = [
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5006"
]
//configurations {
// compile.exclude group: "com.fasterxml.jackson.core"
//}
dependencies {
compile (project(':ch.psi.daq.query'))
compile 'org.hibernate:hibernate-validator:5.2.0.Final'
@ -42,6 +38,6 @@ uploadArchives {
}
}
task dropItQueryREST(dependsOn: build) << {
task dropIt(dependsOn: build) << {
exec{ executable "curl"; args "-X", "POST", "-F", "file=@build/libs/ch.psi.daq.queryrest-" + version + ".jar", "http://dropit.psi.ch:8080/upload"; }
}

View File

@ -7,6 +7,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.slf4j.Logger;
@ -70,6 +71,39 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter {
@Resource
private Environment env;
@Resource
private ObjectMapper objectMapper;
@PostConstruct
public void afterPropertiesSet() {
// add deserializers to ObjectMapper
String packageName = AbstractQuery.class.getPackage().getName();
Class<AbstractQuery> abstractQueryClass = AbstractQuery.class;
AttributeBasedDeserializer<AbstractQuery> abstractQueryDeserializer =
new AttributeBasedDeserializer<AbstractQuery>(abstractQueryClass).register(packageName);
SimpleModule module = new SimpleModule("PolymorphicAbstractQuery", Version.unknownVersion());
module.addDeserializer(abstractQueryClass, abstractQueryDeserializer);
objectMapper.registerModule(module);
// only include non-null values
objectMapper.setSerializationInclusion(Include.NON_NULL);
// Mixin which is used dynamically to filter out which properties get serialised and which
// won't. This way, the user can specify which columns are to be received.
objectMapper.addMixIn(DataEvent.class, PropertyFilterMixin.class);
objectMapper.addMixIn(StorelessStatistics.class, PropertyFilterMixin.class);
objectMapper.addMixIn(EnumMap.class, PropertyFilterMixin.class);
// defines how to writer inner Streams (i.e. Stream<Entry<String, Stream<?>>> toSerialize)
module = new SimpleModule("Streams API", Version.unknownVersion());
module.addSerializer(new JsonStreamSerializer());
objectMapper.registerModule(module);
// by default, byte[] are written as String
module = new SimpleModule("byte[]", Version.unknownVersion());
module.addSerializer(new JsonByteArraySerializer());
objectMapper.registerModule(module);
}
/**
* {@inheritDoc}
@ -81,44 +115,11 @@ public class QueryRestConfig extends WebMvcConfigurerAdapter {
* This is necessary so that the message conversion uses the configured object mapper.
* Otherwise, a separate object mapper is instantiated for Springs message conversion.
*/
converter.setObjectMapper(objectMapper());
converter.setObjectMapper(objectMapper);
converters.add(converter);
super.configureMessageConverters(converters);
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
String packageName = AbstractQuery.class.getPackage().getName();
Class<AbstractQuery> abstractQueryClass = AbstractQuery.class;
AttributeBasedDeserializer<AbstractQuery> abstractQueryDeserializer =
new AttributeBasedDeserializer<AbstractQuery>(abstractQueryClass).register(packageName);
SimpleModule module = new SimpleModule("PolymorphicAbstractQuery", Version.unknownVersion());
module.addDeserializer(abstractQueryClass, abstractQueryDeserializer);
mapper.registerModule(module);
// only include non-null values
mapper.setSerializationInclusion(Include.NON_NULL);
// Mixin which is used dynamically to filter out which properties get serialised and which
// won't. This way, the user can specify which columns are to be received.
mapper.addMixIn(DataEvent.class, PropertyFilterMixin.class);
mapper.addMixIn(StorelessStatistics.class, PropertyFilterMixin.class);
mapper.addMixIn(EnumMap.class, PropertyFilterMixin.class);
// defines how to writer inner Streams (i.e. Stream<Entry<String, Stream<?>>> toSerialize)
module = new SimpleModule("Streams API", Version.unknownVersion());
module.addSerializer(new JsonStreamSerializer());
mapper.registerModule(module);
// by default, byte[] are written as String
module = new SimpleModule("byte[]", Version.unknownVersion());
module.addSerializer(new JsonByteArraySerializer());
mapper.registerModule(module);
return mapper;
}
@Bean
public JsonFactory jsonFactory() {
return new JsonFactory();

View File

@ -107,6 +107,15 @@ public class QueryRestController {
try {
LOGGER.debug("Executing query '{}'", query.getClass().getSimpleName());
// write the response back to the client using java 8 streams
responseStreamWriter.respond(executeQuery(query), query, res);
} catch (Throwable t) {
LOGGER.error("Failed execute query '{}'.", query, t);
throw t;
}
}
public Stream<Entry<String, ?>> executeQuery(AbstractQuery query) {
QueryAnalyzer queryAnalizer = queryAnalizerFactory.apply(query);
// all the magic happens here
@ -115,13 +124,8 @@ public class QueryRestController {
// do post-process
Stream<Entry<String, ?>> channelToData = queryAnalizer.postProcess(channelToDataEvents);
// write the response back to the client using java 8 streams
responseStreamWriter.respond(channelToData, query, res);
} catch (Throwable t) {
LOGGER.error("Failed execute query '{}'.", query, t);
throw t;
}
return channelToData;
}
private QueryProcessor getQueryProcessor(DBMode dbMode) {

View File

@ -1,6 +1,3 @@
# port for the Spring boot application's embedded Tomcat server
server.port=8080
# defines the fields that are included in the response
# if no fields have been specified by the user
queryrest.default.response.fields=channel,pulseId,globalMillis,globalNanos,iocMillis,iocNanos,shape,value