From 5eb649fb3412d7b3b65283f3b2a3ede4cdd93014 Mon Sep 17 00:00:00 2001 From: Zellweger Christof Ralf Date: Wed, 24 Jun 2015 17:26:26 +0200 Subject: [PATCH 1/4] ATEST-81: - first draft for distributed querying --- .../java/ch/psi/daq/rest/DaqRestApplication.java | 1 + .../ch/psi/daq/rest/DaqRestConfiguration.java | 15 +++++++-------- src/main/resources/rest.properties | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/ch/psi/daq/rest/DaqRestApplication.java b/src/main/java/ch/psi/daq/rest/DaqRestApplication.java index 2beaadf..3832b2b 100644 --- a/src/main/java/ch/psi/daq/rest/DaqRestApplication.java +++ b/src/main/java/ch/psi/daq/rest/DaqRestApplication.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.ComponentScan; // comment below @ComponentScan(basePackages = { "ch.psi.daq.rest", + "ch.psi.daq.hazelcast", "ch.psi.daq.cassandra.config", // define the package name with the CassandraConfig // configuration, or @Import it (see above) "ch.psi.daq.cassandra.reader", diff --git a/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java b/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java index e4132d3..e7507cf 100644 --- a/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java +++ b/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java @@ -3,23 +3,22 @@ package ch.psi.daq.rest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import ch.psi.daq.common.statistic.StorelessStatistics; -import ch.psi.daq.domain.cassandra.ChannelEvent; -import ch.psi.daq.hazelcast.query.processor.QueryProcessor; -import ch.psi.daq.hazelcast.query.processor.cassandra.CassandraQueryProcessorLocal; -import ch.psi.daq.rest.model.PropertyFilterMixin; - import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.databind.ObjectMapper; +import ch.psi.daq.common.statistic.StorelessStatistics; +import ch.psi.daq.domain.cassandra.ChannelEvent; +import ch.psi.daq.hazelcast.query.processor.QueryProcessor; +import ch.psi.daq.hazelcast.query.processor.cassandra.CassandraQueryProcessorDistributed; +import ch.psi.daq.rest.model.PropertyFilterMixin; + @Configuration public class DaqRestConfiguration { @Bean public QueryProcessor queryProcessor() { -// return new DummyQueryProcessor(); - return new CassandraQueryProcessorLocal(); + return new CassandraQueryProcessorDistributed(); } @Bean diff --git a/src/main/resources/rest.properties b/src/main/resources/rest.properties index 919cb7d..653644d 100644 --- a/src/main/resources/rest.properties +++ b/src/main/resources/rest.properties @@ -1 +1,3 @@ +server.port=8080 + cassandra.basekeyspace=daq_zellweger_rest \ No newline at end of file From 2cc816ee9a85a10b54b57b39b9d23c5de63bf2e9 Mon Sep 17 00:00:00 2001 From: Zellweger Christof Ralf Date: Thu, 25 Jun 2015 11:20:10 +0200 Subject: [PATCH 2/4] ATEST-81: - rename and move some components - setup component scanning to work properly - create a HazelcastClient to connect to hazelcast cluster, configure it properly --- .../ch/psi/daq/rest/DaqRestConfiguration.java | 53 --------- ...tApplication.java => RestApplication.java} | 12 +-- .../daq/rest/config/RestConfiguration.java | 102 ++++++++++++++++++ .../{ => controller}/DaqRestController.java | 3 +- src/main/resources/rest.properties | 5 +- .../daq/test/rest/AbstractDaqRestTest.java | 4 +- ...ation.java => DaqWebMvcConfiguration.java} | 6 +- 7 files changed, 119 insertions(+), 66 deletions(-) delete mode 100644 src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java rename src/main/java/ch/psi/daq/rest/{DaqRestApplication.java => RestApplication.java} (90%) create mode 100644 src/main/java/ch/psi/daq/rest/config/RestConfiguration.java rename src/main/java/ch/psi/daq/rest/{ => controller}/DaqRestController.java (97%) rename src/test/java/ch/psi/daq/test/rest/{DaqRestApplicationConfiguration.java => DaqWebMvcConfiguration.java} (78%) diff --git a/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java b/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java deleted file mode 100644 index e7507cf..0000000 --- a/src/main/java/ch/psi/daq/rest/DaqRestConfiguration.java +++ /dev/null @@ -1,53 +0,0 @@ -package ch.psi.daq.rest; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.databind.ObjectMapper; - -import ch.psi.daq.common.statistic.StorelessStatistics; -import ch.psi.daq.domain.cassandra.ChannelEvent; -import ch.psi.daq.hazelcast.query.processor.QueryProcessor; -import ch.psi.daq.hazelcast.query.processor.cassandra.CassandraQueryProcessorDistributed; -import ch.psi.daq.rest.model.PropertyFilterMixin; - -@Configuration -public class DaqRestConfiguration { - - @Bean - public QueryProcessor queryProcessor() { - return new CassandraQueryProcessorDistributed(); - } - - @Bean - public JsonFactory jsonFactory() { - return new JsonFactory(); - } - - @Bean - public ResponseStreamWriter responseStreamWriter() { - return new ResponseStreamWriter(); - } - - @Bean - public ObjectMapper objectMapper() { - ObjectMapper mapper = new ObjectMapper(); - // 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(ChannelEvent.class, PropertyFilterMixin.class); - mapper.addMixIn(StorelessStatistics.class, PropertyFilterMixin.class); - return mapper; - } - - // a nested configuration - // this guarantees that the ordering of the properties file is as expected - // see: - // https://jira.spring.io/browse/SPR-10409?focusedCommentId=101393&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-101393 - // @Configuration - // @Import(CassandraConfig.class) - // static class InnerConfiguration { } -} diff --git a/src/main/java/ch/psi/daq/rest/DaqRestApplication.java b/src/main/java/ch/psi/daq/rest/RestApplication.java similarity index 90% rename from src/main/java/ch/psi/daq/rest/DaqRestApplication.java rename to src/main/java/ch/psi/daq/rest/RestApplication.java index 3832b2b..86a2c04 100644 --- a/src/main/java/ch/psi/daq/rest/DaqRestApplication.java +++ b/src/main/java/ch/psi/daq/rest/RestApplication.java @@ -30,23 +30,23 @@ import org.springframework.context.annotation.ComponentScan; // @Import(CassandraConfig.class) // either define the context to be imported, or see ComponentScan // comment below @ComponentScan(basePackages = { - "ch.psi.daq.rest", - "ch.psi.daq.hazelcast", "ch.psi.daq.cassandra.config", // define the package name with the CassandraConfig // configuration, or @Import it (see above) "ch.psi.daq.cassandra.reader", - "ch.psi.daq.cassandra.writer" + "ch.psi.daq.cassandra.writer", + "ch.psi.daq.hazelcast", + "ch.psi.daq.rest", }) -public class DaqRestApplication extends SpringBootServletInitializer { +public class RestApplication extends SpringBootServletInitializer { public static void main(final String[] args) { - SpringApplication.run(DaqRestApplication.class, args); + SpringApplication.run(RestApplication.class, args); } @Override protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) { - return application.sources(DaqRestApplication.class); + return application.sources(RestApplication.class); } } diff --git a/src/main/java/ch/psi/daq/rest/config/RestConfiguration.java b/src/main/java/ch/psi/daq/rest/config/RestConfiguration.java new file mode 100644 index 0000000..d904006 --- /dev/null +++ b/src/main/java/ch/psi/daq/rest/config/RestConfiguration.java @@ -0,0 +1,102 @@ +package ch.psi.daq.rest.config; + +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hazelcast.client.HazelcastClient; +import com.hazelcast.client.config.ClientConfig; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.ManagedContext; +import com.hazelcast.spring.context.SpringManagedContext; + +import ch.psi.daq.common.statistic.StorelessStatistics; +import ch.psi.daq.domain.cassandra.ChannelEvent; +import ch.psi.daq.hazelcast.config.HazelcastConfig; +import ch.psi.daq.hazelcast.query.processor.QueryProcessor; +import ch.psi.daq.hazelcast.query.processor.cassandra.CassandraQueryProcessorDistributed; +import ch.psi.daq.rest.ResponseStreamWriter; +import ch.psi.daq.rest.model.PropertyFilterMixin; + +@Configuration +@PropertySource(value = { "classpath:rest.properties" }) +@PropertySource(value = { "file:${user.home}/.config/daq/rest.properties" }, ignoreResourceNotFound = true) +public class RestConfiguration { + + private static final Logger logger = LoggerFactory.getLogger(RestConfiguration.class); + + @Autowired + private Environment env; + + @Bean + public QueryProcessor queryProcessor() { + return new CassandraQueryProcessorDistributed(); + } + + @Bean + public JsonFactory jsonFactory() { + return new JsonFactory(); + } + + @Bean + public ResponseStreamWriter responseStreamWriter() { + return new ResponseStreamWriter(); + } + + @Bean(name = HazelcastConfig.BEAN_NAME_HAZELCAST_CLIENT) + public HazelcastInstance hazelcastClientInstance() { + return HazelcastClient.newHazelcastClient(hazelcastClientConfig()); + } + + private ClientConfig hazelcastClientConfig() { + ClientConfig config = new ClientConfig(); + config.setManagedContext(managedContext()); + + config.getNetworkConfig().setAddresses(hazelcastMembers()); + + return config; + } + + + private ManagedContext managedContext() { + return new SpringManagedContext(); + } + + @Bean + public List hazelcastMembers() { + List clusterMembers = Arrays.asList(StringUtils.commaDelimitedListToStringArray(env.getProperty("hazelcast.initialcandidates"))); + logger.info("The following hosts have been defined to form a Hazelcast cluster: {}", clusterMembers); + return clusterMembers; + } + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper mapper = new ObjectMapper(); + // 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(ChannelEvent.class, PropertyFilterMixin.class); + mapper.addMixIn(StorelessStatistics.class, PropertyFilterMixin.class); + return mapper; + } + + // a nested configuration + // this guarantees that the ordering of the properties file is as expected + // see: + // https://jira.spring.io/browse/SPR-10409?focusedCommentId=101393&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-101393 + // @Configuration + // @Import(CassandraConfig.class) + // static class InnerConfiguration { } +} diff --git a/src/main/java/ch/psi/daq/rest/DaqRestController.java b/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java similarity index 97% rename from src/main/java/ch/psi/daq/rest/DaqRestController.java rename to src/main/java/ch/psi/daq/rest/controller/DaqRestController.java index 5d14b55..a9ea4c8 100644 --- a/src/main/java/ch/psi/daq/rest/DaqRestController.java +++ b/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java @@ -1,4 +1,4 @@ -package ch.psi.daq.rest; +package ch.psi.daq.rest.controller; import java.io.IOException; import java.util.Map; @@ -19,6 +19,7 @@ import ch.psi.daq.cassandra.writer.CassandraWriter; import ch.psi.daq.domain.cassandra.ChannelEvent; import ch.psi.daq.domain.cassandra.DataEvent; import ch.psi.daq.hazelcast.query.processor.QueryProcessor; +import ch.psi.daq.rest.ResponseStreamWriter; import ch.psi.daq.rest.queries.AbstractQuery; import ch.psi.daq.rest.queries.PulseRangeQuery; import ch.psi.daq.rest.queries.TimeRangeQuery; diff --git a/src/main/resources/rest.properties b/src/main/resources/rest.properties index 653644d..9873024 100644 --- a/src/main/resources/rest.properties +++ b/src/main/resources/rest.properties @@ -1,3 +1,6 @@ +# port for the Spring boot application's embedded Tomcat server server.port=8080 -cassandra.basekeyspace=daq_zellweger_rest \ No newline at end of file +# defines the list of hosts who are tried for an initial connection to the cluster +#hazelcast.members=sf-nube-11.psi.ch,sf-nube-12.psi.ch,sf-nube-13.psi.ch,sf-nube-14.psi.ch +hazelcast.initialcandidates=localhost \ No newline at end of file diff --git a/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java b/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java index 583bbce..f2537d5 100644 --- a/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java +++ b/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java @@ -16,13 +16,13 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import ch.psi.daq.rest.DaqRestApplication; +import ch.psi.daq.rest.RestApplication; import ch.psi.daq.test.cassandra.CassandraDaqUnitDependencyInjectionTestExecutionListener; import com.fasterxml.jackson.databind.ObjectMapper; -@SpringApplicationConfiguration(classes = {DaqRestApplication.class, DaqRestApplicationConfiguration.class}) +@SpringApplicationConfiguration(classes = {RestApplication.class, DaqWebMvcConfiguration.class}) @TestExecutionListeners({ CassandraDaqUnitDependencyInjectionTestExecutionListener.class, DependencyInjectionTestExecutionListener.class}) diff --git a/src/test/java/ch/psi/daq/test/rest/DaqRestApplicationConfiguration.java b/src/test/java/ch/psi/daq/test/rest/DaqWebMvcConfiguration.java similarity index 78% rename from src/test/java/ch/psi/daq/test/rest/DaqRestApplicationConfiguration.java rename to src/test/java/ch/psi/daq/test/rest/DaqWebMvcConfiguration.java index 0a49467..0ab6185 100644 --- a/src/test/java/ch/psi/daq/test/rest/DaqRestApplicationConfiguration.java +++ b/src/test/java/ch/psi/daq/test/rest/DaqWebMvcConfiguration.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Import; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; -import ch.psi.daq.rest.DaqRestConfiguration; +import ch.psi.daq.rest.config.RestConfiguration; import ch.psi.daq.test.cassandra.LocalCassandraTestConfig; @Configuration @@ -16,9 +16,9 @@ import ch.psi.daq.test.cassandra.LocalCassandraTestConfig; // "ch.psi.daq.cassandra.reader", // "ch.psi.daq.cassandra.writer" //}) -@Import(value = {LocalCassandraTestConfig.class, DaqRestConfiguration.class}) +@Import(value = {LocalCassandraTestConfig.class, RestConfiguration.class}) @EnableWebMvc -public class DaqRestApplicationConfiguration extends WebMvcConfigurationSupport { +public class DaqWebMvcConfiguration extends WebMvcConfigurationSupport { // add test-specific beans and configurations here } \ No newline at end of file From 899d50492ce5c151a2a7f2cfdfdd82bd3fdde514 Mon Sep 17 00:00:00 2001 From: Zellweger Christof Ralf Date: Thu, 25 Jun 2015 12:36:43 +0200 Subject: [PATCH 3/4] ATEST-81: - correct build setup - add javadoc --- build.gradle | 1 - .../rest/controller/DaqRestController.java | 21 ++------ .../psi/daq/rest/queries/AbstractQuery.java | 53 ++++++++++++------- .../psi/daq/rest/queries/PulseRangeQuery.java | 33 +++++++++--- .../psi/daq/rest/queries/TimeRangeQuery.java | 46 ++++++++++------ 5 files changed, 92 insertions(+), 62 deletions(-) diff --git a/build.gradle b/build.gradle index 755793a..d10603e 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,6 @@ applicationDefaultJvmArgs = [ //} dependencies { - compile (project(':ch.psi.daq.cassandra')) compile (project(':ch.psi.daq.hazelcast')) compile 'org.springframework.boot:spring-boot-starter-web:1.2.4.RELEASE' compile 'com.google.code.gson:gson:2+' diff --git a/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java b/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java index a9ea4c8..99d34c6 100644 --- a/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java +++ b/src/main/java/ch/psi/daq/rest/controller/DaqRestController.java @@ -38,12 +38,8 @@ public class DaqRestController { @Autowired private QueryProcessor queryProcessor; - /** - * - * @param query - * @param res - * @throws IOException - */ + + @RequestMapping(value = "/pulserange") public void pulseRange(@RequestBody PulseRangeQuery query, HttpServletResponse res) throws IOException { @@ -53,12 +49,6 @@ public class DaqRestController { } - /** - * - * @param query - * @param res - * @throws IOException - */ @RequestMapping(value = "/timerange") public void timeRange(@RequestBody TimeRangeQuery query, HttpServletResponse res) throws IOException { @@ -67,12 +57,7 @@ public class DaqRestController { executeQuery(query, res); } - /** - * - * @param query - * @param res - * @throws IOException - */ + private void executeQuery(AbstractQuery query, HttpServletResponse res) throws IOException { // all the magic happens here diff --git a/src/main/java/ch/psi/daq/rest/queries/AbstractQuery.java b/src/main/java/ch/psi/daq/rest/queries/AbstractQuery.java index 9bed2ea..bcf67c3 100644 --- a/src/main/java/ch/psi/daq/rest/queries/AbstractQuery.java +++ b/src/main/java/ch/psi/daq/rest/queries/AbstractQuery.java @@ -9,6 +9,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + import ch.psi.daq.cassandra.reader.Ordering; import ch.psi.daq.hazelcast.query.Aggregation; import ch.psi.daq.hazelcast.query.AggregationType; @@ -17,12 +23,6 @@ import ch.psi.daq.hazelcast.query.bin.BinningStrategy; import ch.psi.daq.hazelcast.query.bin.BinningStrategyFactory; import ch.psi.daq.hazelcast.query.range.QueryRange; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonSubTypes.Type; -import com.fasterxml.jackson.annotation.JsonTypeInfo; - /** * * @author zellweger_c @@ -38,9 +38,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; @Type(value = TimeRangeQuery.class, name = "timerange"), }) public abstract class AbstractQuery implements Query { - + private static Logger logger = LoggerFactory.getLogger(AbstractQuery.class); - + private List channels; private LinkedHashSet fields; @@ -60,12 +60,23 @@ public abstract class AbstractQuery implements Query { private QueryRange queryRange; /** + * Constructor. * * @param ordering whether to add a 'orderBy' clause into the database query * @param channels all the channelIds (channel names) we want to query * @param fields the fields (who map to fields in the DB) we are interested in returning to the * client, needs to be in insertion order (hence the {@link LinkedHashSet} type) - * @param queryRange TODO + * @param binningStrategyEnum enum that maps the user's String to a concrete + * {@link BinningStrategy} implementation + * @param binLengthOrCount depending on the chosen binning strategy, this field defines either the + * count (how many pulse ids are to be put inside 1 bin) or the time frame for 1 bin + * @param aggregateChannels whether aggregation will include all channels, default is on a + * per-channel basis + * @param aggregationType defines whether aggregation takes place in an index- or value-based + * manner + * @param aggregations list of aggregations / statistics to calculate, e.g. min, max and average + * @param queryRange object containing the ranges for either pulse-based queries or time-based + * queries */ @JsonCreator public AbstractQuery( @@ -75,7 +86,7 @@ public abstract class AbstractQuery implements Query { @JsonProperty(value = "channels") List channels, @JsonProperty(value = "fields") LinkedHashSet fields, @JsonProperty(value = "binningStrategy") BinningStrategyEnum binningStrategyEnum, - @JsonProperty(value = "binDuration") long lengthOrCount, + @JsonProperty(value = "binDuration") long binLengthOrCount, @JsonProperty(value = "aggregateChannels") boolean aggregateChannels, @JsonProperty(value = "aggregationType") AggregationType aggregationType, @JsonProperty(value = "aggregations") List aggregations, @@ -93,23 +104,24 @@ public abstract class AbstractQuery implements Query { this.channels = channels; this.fields = fields; - this.binningStrategyEnum = binningStrategyEnum; // can be null: default then will be BinCountBinningStrategy - - + this.binningStrategyEnum = binningStrategyEnum; // can be null: default then will be + // BinCountBinningStrategy + + if (binningStrategyEnum != null) { switch (binningStrategyEnum) { case count: - this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) lengthOrCount); + this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) binLengthOrCount); break; case length: - this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), lengthOrCount); + this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), binLengthOrCount); break; default: logger.warn("No binning strategy has been set. Selecting BinningStrategyBinCount."); - this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) lengthOrCount); + this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) binLengthOrCount); } } else { - this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) lengthOrCount); + this.binningStrategy = BinningStrategyFactory.getBinningStrategy(getQueryRange(), (int) binLengthOrCount); } } @@ -138,6 +150,7 @@ public abstract class AbstractQuery implements Query { } + @Override public boolean isAggregateChannels() { return aggregateChannels; } @@ -145,7 +158,7 @@ public abstract class AbstractQuery implements Query { public BinningStrategyEnum getBinningStrategyEnum() { return binningStrategyEnum; } - + @Override public BinningStrategy getBinningStrategy() { return binningStrategy; @@ -158,7 +171,7 @@ public abstract class AbstractQuery implements Query { public List getAggregations() { return aggregations; } - + /** * {@inheritDoc} */ @@ -166,7 +179,7 @@ public abstract class AbstractQuery implements Query { public QueryRange getQueryRange() { return queryRange; } - + public void setQueryRange(QueryRange queryRange) { this.queryRange = queryRange; } diff --git a/src/main/java/ch/psi/daq/rest/queries/PulseRangeQuery.java b/src/main/java/ch/psi/daq/rest/queries/PulseRangeQuery.java index ba8f9f1..0237c95 100644 --- a/src/main/java/ch/psi/daq/rest/queries/PulseRangeQuery.java +++ b/src/main/java/ch/psi/daq/rest/queries/PulseRangeQuery.java @@ -3,21 +3,42 @@ package ch.psi.daq.rest.queries; import java.util.LinkedHashSet; import java.util.List; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import ch.psi.daq.cassandra.reader.Ordering; import ch.psi.daq.hazelcast.query.Aggregation; import ch.psi.daq.hazelcast.query.AggregationType; +import ch.psi.daq.hazelcast.query.bin.BinningStrategy; import ch.psi.daq.hazelcast.query.range.QueryRange; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - /** * */ public class PulseRangeQuery extends AbstractQuery { + + /** + * Constructor. + * + * @param ordering whether to add a 'orderBy' clause into the database query + * @param channels all the channelIds (channel names) we want to query + * @param fields the fields (who map to fields in the DB) we are interested in returning to the + * client, needs to be in insertion order (hence the {@link LinkedHashSet} type) + * @param binningStrategyEnum enum that maps the user's String to a concrete + * {@link BinningStrategy} implementation + * @param binLengthOrCount depending on the chosen binning strategy, this field defines either the + * count (how many pulse ids are to be put inside 1 bin) or the time frame for 1 bin + * @param aggregateChannels whether aggregation will include all channels, default is on a + * per-channel basis + * @param aggregationType defines whether aggregation takes place in an index- or value-based + * manner + * @param aggregations list of aggregations / statistics to calculate, e.g. min, max and average + * @param queryRange object containing the ranges for either pulse-based queries or time-based + * queries + */ @JsonCreator public PulseRangeQuery( // note that those annotations are needed for the polymorphic @@ -26,13 +47,13 @@ public class PulseRangeQuery extends AbstractQuery { @JsonProperty(value = "channels") List channels, @JsonProperty(value = "fields") LinkedHashSet fields, @JsonProperty(value = "binningStrategy") BinningStrategyEnum binningStrategyEnum, - @JsonProperty(value = "binDuration") long binDurationOrBinCount, + @JsonProperty(value = "binDuration") long binLengthOrCount, @JsonProperty(value = "aggregateChannels") boolean aggregateChannels, @JsonProperty(value = "aggregationType") AggregationType aggregationType, @JsonProperty(value = "aggregations") List aggregations, @JsonProperty(value = "queryRange") QueryRange queryRange) { - super(ordering, channels, fields, binningStrategyEnum, binDurationOrBinCount, aggregateChannels, aggregationType, + super(ordering, channels, fields, binningStrategyEnum, binLengthOrCount, aggregateChannels, aggregationType, aggregations, queryRange); } diff --git a/src/main/java/ch/psi/daq/rest/queries/TimeRangeQuery.java b/src/main/java/ch/psi/daq/rest/queries/TimeRangeQuery.java index 45404bf..af4c1cc 100644 --- a/src/main/java/ch/psi/daq/rest/queries/TimeRangeQuery.java +++ b/src/main/java/ch/psi/daq/rest/queries/TimeRangeQuery.java @@ -6,18 +6,19 @@ import java.util.Date; import java.util.LinkedHashSet; import java.util.List; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + import ch.psi.daq.cassandra.reader.Ordering; import ch.psi.daq.hazelcast.query.Aggregation; import ch.psi.daq.hazelcast.query.AggregationType; +import ch.psi.daq.hazelcast.query.bin.BinningStrategy; import ch.psi.daq.hazelcast.query.range.QueryRange; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - public class TimeRangeQuery extends AbstractQuery { @@ -26,19 +27,28 @@ public class TimeRangeQuery extends AbstractQuery { private static Logger logger = LoggerFactory.getLogger(TimeRangeQuery.class); /** + * Constructor * * @param ordering whether to add a 'orderBy' clause into the database query - * @param channelIds all the sourceIds (channel names) we want to query + * @param channels all the channelIds (channel names) we want to query * @param fields the fields (who map to fields in the DB) we are interested in returning to the * client, needs to be in insertion order (hence the {@link LinkedHashSet} type) - * @param binningStrategyEnum - * @param binDurationOrBinCount - * @param aggregateChannels - * @param aggregationType - * @param aggregations - * @param queryRange - * @param startDateTime - * @param endDateTime + * @param binningStrategyEnum enum that maps the user's String to a concrete + * {@link BinningStrategy} implementation + * @param binLengthOrCount depending on the chosen binning strategy, this field defines either the + * count (how many pulse ids are to be put inside 1 bin) or the time frame for 1 bin + * @param aggregateChannels whether aggregation will include all channels, default is on a + * per-channel basis + * @param aggregationType defines whether aggregation takes place in an index- or value-based + * manner + * @param aggregations list of aggregations / statistics to calculate, e.g. min, max and average + * @param queryRange object containing the ranges for either pulse-based queries or time-based + * queries + * @param startDateTime if set, the date string (format is: + * {@link TimeRangeQuery#DATE_FORMAT_STRING} will be parsed and converted into + * milliseconds + * @param endDateTime set, the date string (format is: {@link TimeRangeQuery#DATE_FORMAT_STRING} + * will be parsed and converted into milliseconds */ @JsonCreator public TimeRangeQuery( @@ -48,7 +58,7 @@ public class TimeRangeQuery extends AbstractQuery { @JsonProperty(value = "channels") List channels, @JsonProperty(value = "fields") LinkedHashSet fields, @JsonProperty(value = "binningStrategy") BinningStrategyEnum binningStrategyEnum, - @JsonProperty(value = "binDuration") long binDurationOrBinCount, + @JsonProperty(value = "binDuration") long binLengthOrCount, @JsonProperty(value = "aggregateChannels") boolean aggregateChannels, @JsonProperty(value = "aggregationType") AggregationType aggregationType, @JsonProperty(value = "aggregations") List aggregations, @@ -56,15 +66,17 @@ public class TimeRangeQuery extends AbstractQuery { @JsonProperty(value = "startDateTime") String startDateTime, @JsonProperty(value = "endDateTime") String endDateTime) { - super(ordering, channels, fields, binningStrategyEnum, binDurationOrBinCount, aggregateChannels, aggregationType, aggregations, queryRange); - + super(ordering, channels, fields, binningStrategyEnum, binLengthOrCount, aggregateChannels, aggregationType, + aggregations, queryRange); + if (startDateTime != null && endDateTime != null) { logger.info("startDateTime and endDateTime specified. This takes precedence over the start / end fields."); try { Date startDate = DATE_FORMAT.parse(startDateTime); Date endDate = DATE_FORMAT.parse(endDateTime); - getQueryRange().setTimeRange(startDate.getTime(), queryRange.getStartNanos(), endDate.getTime(), queryRange.getEndNanos()); + getQueryRange().setTimeRange(startDate.getTime(), queryRange.getStartNanos(), endDate.getTime(), + queryRange.getEndNanos()); } catch (ParseException e) { logger.error("Parsing the start- and/or endDate was unsuccessful. " + "The format must be '" + DATE_FORMAT_STRING + "'", e); From fad99c2ac3739da5944d5bbc4689ff4e548899c3 Mon Sep 17 00:00:00 2001 From: Zellweger Christof Ralf Date: Fri, 26 Jun 2015 13:33:40 +0200 Subject: [PATCH 4/4] ATEST-81: - fixing tests using updated Cassandra startup routine --- .../ch/psi/daq/test/rest/AbstractDaqRestTest.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java b/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java index f2537d5..0ed239a 100644 --- a/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java +++ b/src/test/java/ch/psi/daq/test/rest/AbstractDaqRestTest.java @@ -1,6 +1,5 @@ package ch.psi.daq.test.rest; -import org.cassandraunit.spring.EmbeddedCassandra; import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; @@ -16,17 +15,17 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import com.fasterxml.jackson.databind.ObjectMapper; + import ch.psi.daq.rest.RestApplication; import ch.psi.daq.test.cassandra.CassandraDaqUnitDependencyInjectionTestExecutionListener; -import com.fasterxml.jackson.databind.ObjectMapper; - -@SpringApplicationConfiguration(classes = {RestApplication.class, DaqWebMvcConfiguration.class}) @TestExecutionListeners({ - CassandraDaqUnitDependencyInjectionTestExecutionListener.class, - DependencyInjectionTestExecutionListener.class}) -@EmbeddedCassandra + CassandraDaqUnitDependencyInjectionTestExecutionListener.class, + DependencyInjectionTestExecutionListener.class}) +@SpringApplicationConfiguration(classes = {RestApplication.class, DaqWebMvcConfiguration.class}) +//@EmbeddedCassandra @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD) @WebAppConfiguration @RunWith(SpringJUnit4ClassRunner.class)