ATEST-124:

- implement the QueryValidator class
- adjust / fix tests
This commit is contained in:
Zellweger Christof Ralf
2015-07-31 10:17:11 +02:00
parent 1d07c618a9
commit 22c2adf7cc
6 changed files with 81 additions and 45 deletions

View File

@ -2,6 +2,7 @@ package ch.psi.daq.queryrest.config;
import java.util.EnumMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
@ -14,8 +15,11 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonFactory;
@ -42,7 +46,7 @@ import ch.psi.daq.queryrest.response.ResponseStreamWriter;
@Configuration
@PropertySource(value = {"classpath:queryrest.properties"})
@PropertySource(value = {"file:${user.home}/.config/daq/queryrest.properties"}, ignoreResourceNotFound = true)
public class QueryRestConfig {
public class QueryRestConfig extends WebMvcConfigurerAdapter {
private static final String QUERYREST_DEFAULT_RESPONSE_AGGREGATIONS = "queryrest.default.response.aggregations";
@ -65,6 +69,21 @@ public class QueryRestConfig {
@Resource
private Environment env;
/**
* {@inheritDoc}
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
/**
* 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());
converters.add(converter);
super.configureMessageConverters(converters);
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
@ -92,7 +111,7 @@ public class QueryRestConfig {
return mapper;
}
@Bean
public JsonFactory jsonFactory() {
return new JsonFactory();

View File

@ -14,6 +14,9 @@ import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -40,6 +43,9 @@ public class QueryRestController {
public static final String CHANNELS_REGEX = CHANNELS + "/{regex}";
public static final String QUERY = "query";
@Resource
private Validator queryValidator;
@Resource
private ResponseStreamWriter responseStreamWriter;
@ -55,10 +61,19 @@ public class QueryRestController {
@Resource(name = QueryRestConfig.BEAN_NAME_DEFAULT_RESPONSE_AGGREGATIONS)
private Set<Aggregation> defaultResponseAggregations;
@InitBinder
protected void initBinder(WebDataBinder binder) {
/*
* This allows to use the @Valid annotation in the methods below.
*/
binder.addValidators(queryValidator);
}
@RequestMapping(
value = CHANNELS,
method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON_VALUE})
consumes = {MediaType.APPLICATION_JSON_VALUE},
method = RequestMethod.GET)
public @ResponseBody Collection<String> getChannels() throws Throwable {
try {
return queryProcessor.getChannels();
@ -71,8 +86,7 @@ public class QueryRestController {
@RequestMapping(
value = CHANNELS_REGEX,
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
consumes = {MediaType.APPLICATION_JSON_VALUE})
public @ResponseBody Collection<String> getChannels(@RequestBody String regex) throws Throwable {
try {
return queryProcessor.getChannels(regex);
@ -86,16 +100,13 @@ public class QueryRestController {
value = QUERY,
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE})
// , produces = {MediaType.APPLICATION_JSON_VALUE})
public void executeQuery(@RequestBody @Valid AbstractQuery query, HttpServletResponse res) throws IOException {
try {
LOGGER.debug("Execute query '{}'", query.getClass().getSimpleName());
LOGGER.debug("Executing query '{}'", query.getClass().getSimpleName());
QueryAnalyzer queryAnalizer = queryAnalizerFactory.apply(query);
queryAnalizer.validate();
// extendQuery(query);
// all the magic happens here
Stream<Entry<String, Stream<? extends DataEvent>>> channelToDataEvents = queryProcessor.process(queryAnalizer);
@ -110,14 +121,6 @@ public class QueryRestController {
}
}
// private void extendQuery(AbstractQuery query) {
// if (query.getFields() == null || query.getFields().isEmpty()) {
// query.setFields(new LinkedHashSet<>(defaultResponseFields));
// }
// if(query.getAggregations() == null || query.getAggregations().isEmpty()){
// query.setAggregations(new LinkedList<>(defaultResponseAggregations));
// }
// }
// ==========================================================================================
// TODO: This is simply for initial / rudimentary testing - remove once further evolved

View File

@ -5,6 +5,7 @@ import javax.annotation.Resource;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
@ -18,6 +19,7 @@ import org.springframework.web.context.WebApplicationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import ch.psi.daq.queryrest.QueryRestApplication;
import ch.psi.daq.queryrest.config.QueryRestConfig;
import ch.psi.daq.test.cassandra.CassandraDaqUnitDependencyInjectionTestExecutionListener;
@ -25,13 +27,17 @@ import ch.psi.daq.test.cassandra.CassandraDaqUnitDependencyInjectionTestExecutio
@TestExecutionListeners({
CassandraDaqUnitDependencyInjectionTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class})
@SpringApplicationConfiguration(classes = {QueryRestConfig.class, DaqWebMvcConfig.class})
@SpringApplicationConfiguration(classes = {
QueryRestApplication.class
,QueryRestConfig.class
,DaqWebMvcConfig.class
})
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public abstract class AbstractDaqRestTest {
@Resource
@Autowired
protected WebApplicationContext webApplicationContext;
protected MockMvc mockMvc;

View File

@ -1,6 +1,7 @@
package ch.psi.daq.test.queryrest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@ -17,10 +18,11 @@ import ch.psi.daq.test.query.config.LocalQueryTestConfig;
import ch.psi.daq.test.queryrest.query.DummyDataReader;
@Configuration
@ComponentScan
@EnableWebMvc
@PropertySources(value = {
@PropertySource(value = {"classpath:queryrest-test.properties"})
})
@EnableWebMvc
public class DaqWebMvcConfig extends WebMvcConfigurationSupport {
// ensure that properties in dispatcher.properties are loaded first and then overwritten by the

View File

@ -48,6 +48,23 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
@After
public void tearDown() throws Exception {}
@Test
public void testChannelNameQuery() throws Exception {
this.mockMvc.perform(
MockMvcRequestBuilders
.get("/" + QueryRestController.CHANNELS)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$").isArray())
.andExpect(MockMvcResultMatchers.jsonPath("$[0]").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$[0]").value("testChannel1"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1]").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$[1]").value("testChannel2"))
.andExpect(MockMvcResultMatchers.jsonPath("$[2]").doesNotExist());
}
@Test
public void testPulseRangeQuery() throws Exception {
PulseRangeQuery request = new PulseRangeQuery(
@ -56,9 +73,13 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
TEST_CHANNEL_NAMES);
String content = mapper.writeValueAsString(request);
System.out.println(content);
content = "{\"channels\":[\"testChannel1\",\"testChannel2\"],\"startPulseId\":100,\"endPulseId\":101}";
this.mockMvc
.perform(MockMvcRequestBuilders.post(QueryRestController.QUERY)
.perform(MockMvcRequestBuilders
.post("/" + QueryRestController.QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content))
@ -86,8 +107,8 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
String content = mapper.writeValueAsString(request);
this.mockMvc
.perform(MockMvcRequestBuilders.post(QueryRestController.QUERY)
this.mockMvc.perform(MockMvcRequestBuilders
.post("/" + QueryRestController.QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content))
@ -120,7 +141,8 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
this.mockMvc
.perform(
MockMvcRequestBuilders.post(QueryRestController.QUERY)
MockMvcRequestBuilders
.post("/" + QueryRestController.QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
)
@ -152,7 +174,7 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
String content = mapper.writeValueAsString(request);
this.mockMvc
.perform(MockMvcRequestBuilders.post(QueryRestController.QUERY)
.perform(MockMvcRequestBuilders.post("/" + QueryRestController.QUERY)
.contentType(MediaType.APPLICATION_JSON)
.content(content))
@ -179,20 +201,4 @@ public class DaqRestControllerTest extends AbstractDaqRestTest {
.andExpect(MockMvcResultMatchers.jsonPath("$.minima.max.event.pulseId").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.minima.max.event.pulseId").value(101));
}
@Test
public void testChannelNameQuery() throws Exception {
this.mockMvc
.perform(MockMvcRequestBuilders.get(QueryRestController.CHANNELS)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$").isArray())
.andExpect(MockMvcResultMatchers.jsonPath("$[0]").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$[0]").value("testChannel1"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1]").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$[1]").value("testChannel2"))
.andExpect(MockMvcResultMatchers.jsonPath("$[2]").doesNotExist());
}
}

View File

@ -1,7 +1,6 @@
package ch.psi.daq.test.queryrest.query;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.LongStream;
import java.util.stream.Stream;
@ -52,7 +51,8 @@ public class DummyDataReader implements DataReader {
i,
i,
0,
"data_" + UUID.randomUUID().toString());
123 // dummy value
);
});
}
}