diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index c625ccf0c..87e412fd9 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-integration-tests jar diff --git a/omod-1.10/pom.xml b/omod-1.10/pom.xml index b4f12b012..cca4e0f9b 100644 --- a/omod-1.10/pom.xml +++ b/omod-1.10/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-1.10 jar diff --git a/omod-1.11/pom.xml b/omod-1.11/pom.xml index 9248f7e60..469b49d01 100644 --- a/omod-1.11/pom.xml +++ b/omod-1.11/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-1.11 jar diff --git a/omod-1.12/pom.xml b/omod-1.12/pom.xml index f3dab1546..a6b639110 100644 --- a/omod-1.12/pom.xml +++ b/omod-1.12/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-1.12 jar diff --git a/omod-1.8/pom.xml b/omod-1.8/pom.xml index d43b6c9fb..12d6491d0 100644 --- a/omod-1.8/pom.xml +++ b/omod-1.8/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-1.8 jar diff --git a/omod-1.9/pom.xml b/omod-1.9/pom.xml index 215ff6d20..01085e291 100644 --- a/omod-1.9/pom.xml +++ b/omod-1.9/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-1.9 jar diff --git a/omod-2.0/pom.xml b/omod-2.0/pom.xml index 39d51ebde..e0f5471b9 100644 --- a/omod-2.0/pom.xml +++ b/omod-2.0/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-2.0 jar diff --git a/omod-2.1/pom.xml b/omod-2.1/pom.xml index f1cb6ea96..c9e77387c 100644 --- a/omod-2.1/pom.xml +++ b/omod-2.1/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-2.1 jar diff --git a/omod-2.2/pom.xml b/omod-2.2/pom.xml index 87c3bcc86..3812def77 100644 --- a/omod-2.2/pom.xml +++ b/omod-2.2/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-2.2 jar diff --git a/omod-2.3/pom.xml b/omod-2.3/pom.xml index cf93ce932..6097318e8 100644 --- a/omod-2.3/pom.xml +++ b/omod-2.3/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-2.3 jar diff --git a/omod-2.4/pom.xml b/omod-2.4/pom.xml index e6e2dcb0e..c83d277dc 100644 --- a/omod-2.4/pom.xml +++ b/omod-2.4/pom.xml @@ -3,7 +3,7 @@ webservices.rest org.openmrs.module - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT 4.0.0 diff --git a/omod-common/pom.xml b/omod-common/pom.xml index 57b4c40d5..417160fdf 100644 --- a/omod-common/pom.xml +++ b/omod-common/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod-common jar diff --git a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java index d2919db85..1d47c9336 100644 --- a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java +++ b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java @@ -61,11 +61,11 @@ public class ConversionUtil { // This would better be a Map, Type> but adding the dependency for // org.apache.commons.lang3.tuple.Pair (through omrs-api) messed up other tests - private static Map typeVariableMap = new ConcurrentHashMap(); + private static final Map typeVariableMap = new ConcurrentHashMap(); private static ConcurrentMap, Converter> converterCache; - private static Converter nullConverter; + private static final Converter nullConverter; static { converterCache = new ConcurrentHashMap, Converter>(); @@ -170,8 +170,9 @@ public static Object convert(Object object, Type toType, Object instance) throws */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static Object convert(Object object, Type toType) throws ConversionException { - if (object == null) - return object; + if (object == null) { + return null; + } Class toClass = toType instanceof Class ? ((Class) toType) : (Class) (((ParameterizedType) toType) .getRawType()); @@ -188,7 +189,7 @@ public static Object convert(Object object, Type toType) throws ConversionExcept Object ret = Array.newInstance(targetElementType, input.size()); int i = 0; - for (Object element : (Collection) object) { + for (Object element : input) { Array.set(ret, i, convert(element, targetElementType)); ++i; } @@ -210,8 +211,9 @@ public static Object convert(Object object, Type toType) throws ConversionExcept // if we have generic type information for the target collection, we can use it to do conversion ParameterizedType toParameterizedType = (ParameterizedType) toType; Type targetElementType = toParameterizedType.getActualTypeArguments()[0]; - for (Object element : (Collection) object) + for (Object element : (Collection) object) { ret.add(convert(element, targetElementType)); + } } else { // otherwise we must just add all items in a non-type-safe manner ret.addAll((Collection) object); @@ -221,8 +223,9 @@ public static Object convert(Object object, Type toType) throws ConversionExcept // otherwise we're converting _to_ a non-collection type - if (toClass.isAssignableFrom(object.getClass())) + if (toClass.isAssignableFrom(object.getClass())) { return object; + } // Numbers with a decimal are always assumed to be Double, so convert to Float, if necessary if (toClass.isAssignableFrom(Float.class) && object instanceof Double) { diff --git a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/DynamicBeanConfiguration.java b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/DynamicBeanConfiguration.java index 0e9a46338..346716cf9 100644 --- a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/DynamicBeanConfiguration.java +++ b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/DynamicBeanConfiguration.java @@ -13,7 +13,9 @@ import java.util.Arrays; import java.util.List; +import org.openmrs.api.APIException; import org.openmrs.api.context.Context; +import org.openmrs.api.context.ServiceContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; @@ -35,17 +37,17 @@ public class DynamicBeanConfiguration { * otherwise it falls back to the old one. */ @Bean(name = "jsonHttpMessageConverter") - public HttpMessageConverter getMappingJacksonHttpMessageConverter() throws Exception { + public HttpMessageConverter getMappingJacksonHttpMessageConverter() throws Exception { Class clazz; try { - clazz = Context.loadClass("org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"); + clazz = Context.loadClass("org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"); } catch (ClassNotFoundException e) { - clazz = Context.loadClass("org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"); + clazz = Context.loadClass("org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"); } - return (HttpMessageConverter) clazz.newInstance(); + return (HttpMessageConverter) clazz.newInstance(); } /** @@ -75,7 +77,7 @@ public AbstractHandlerExceptionResolver getHandlerExceptionResolver() throws Exc bean = (AbstractHandlerExceptionResolver) clazz.newInstance(); - Method method = bean.getClass().getMethod("setMessageConverters", new Class[] { HttpMessageConverter[].class }); + Method method = bean.getClass().getMethod("setMessageConverters", HttpMessageConverter[].class); method.invoke(bean, new Object[] { new HttpMessageConverter[] { stringHttpMessageConverter, jsonHttpMessageConverter, xmlMarshallingHttpMessageConverter } }); } @@ -85,15 +87,12 @@ public AbstractHandlerExceptionResolver getHandlerExceptionResolver() throws Exc bean = (AbstractHandlerExceptionResolver) clazz.newInstance(); - Method method = bean.getClass().getMethod("setMessageConverters", new Class[] { List.class }); - method.invoke(bean, new Object[] { Arrays.asList( stringHttpMessageConverter, - jsonHttpMessageConverter, xmlMarshallingHttpMessageConverter ) }); + Method method = bean.getClass().getMethod("setMessageConverters", List.class); + method.invoke(bean, Arrays.asList(stringHttpMessageConverter, + jsonHttpMessageConverter, xmlMarshallingHttpMessageConverter)); } - if (bean != null) { - bean.setOrder(1); - - } + bean.setOrder(1); return bean; } @@ -110,10 +109,10 @@ public AbstractHandlerMapping getHandlerMapping() throws Exception { Class clazz; try { - clazz = Context.loadClass("org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"); + clazz = Context.loadClass("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"); } catch (ClassNotFoundException e) { - clazz = Context.loadClass("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"); + clazz = Context.loadClass("org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"); } return (AbstractHandlerMapping) clazz.newInstance(); diff --git a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImpl.java b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImpl.java index be9e67ba1..9ffc4c06e 100644 --- a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImpl.java +++ b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImpl.java @@ -508,8 +508,10 @@ private Resource newResource(Class resourceClass) { * required parameters * Should return null if given parameters are missing a parameter required by search handlers * eligible for given resource name and parameters + * Should return default search handler if two search handlers match given resource and parameters and no search handler + * id is specified and one of the matching search handlers is the default * Should fail if two search handlers match given resource and parameters and no search handler - * id is specified + * id is specified and neither matching search hander is the default * Should return null if a non special request parameter in given parameters cannot be found in * any search handler * Should return null if no search handler is found for given resource name @@ -568,15 +570,23 @@ public SearchHandler getSearchHandler(String resourceName, Map return null; } else if (candidateSearchHandlers.size() == 1) { return candidateSearchHandlers.iterator().next(); - } else { - List candidateSearchHandlerIds = new ArrayList(); - for (SearchHandler candidateSearchHandler : candidateSearchHandlers) { - candidateSearchHandlerIds.add(RestConstants.REQUEST_PROPERTY_FOR_SEARCH_ID + "=" - + candidateSearchHandler.getSearchConfig().getId()); + } + // if multiple, return default + for (SearchHandler candidateSearchHandler : candidateSearchHandlers) { + if ("default".equals(candidateSearchHandler.getSearchConfig().getId())) { + return candidateSearchHandler; } - throw new InvalidSearchException("The search is ambiguous. Please specify " - + StringUtils.join(candidateSearchHandlerIds, " or ")); } + + // multiple and no default, throw exception + List candidateSearchHandlerIds = new ArrayList(); + for (SearchHandler candidateSearchHandler : candidateSearchHandlers) { + candidateSearchHandlerIds.add(RestConstants.REQUEST_PROPERTY_FOR_SEARCH_ID + "=" + + candidateSearchHandler.getSearchConfig().getId()); + } + throw new InvalidSearchException("The search is ambiguous. Please specify " + + StringUtils.join(candidateSearchHandlerIds, " or ")); + } } diff --git a/omod-common/src/main/resources/webModuleApplicationContext.xml b/omod-common/src/main/resources/webModuleApplicationContext.xml index c0a6c616e..f99920551 100644 --- a/omod-common/src/main/resources/webModuleApplicationContext.xml +++ b/omod-common/src/main/resources/webModuleApplicationContext.xml @@ -17,19 +17,15 @@ - - - + - - + + - - - + @@ -47,17 +43,13 @@ - - - + - - - + diff --git a/omod-common/src/test/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImplTest.java b/omod-common/src/test/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImplTest.java index 4cd1c5632..747895c40 100644 --- a/omod-common/src/test/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImplTest.java +++ b/omod-common/src/test/java/org/openmrs/module/webservices/rest/web/api/impl/RestServiceImplTest.java @@ -695,7 +695,7 @@ public void getSearchHandler_shouldReturnNullIfGivenParametersAreMissingAParamet * @see RestServiceImpl#getSearchHandler(String, Map) */ @Test - public void getSearchHandler_shouldFailIfTwoSearchHandlersMatchGivenResourceAndParametersAndNoSearchHandlerIdIsSpecified() + public void getSearchHandler_shouldReturnDefaultSearchHandlerIfDefaultAndCustomSearchHandlersMatchGivenResourceAndParametersAndNoSearchHandlerIdIsSpecified() throws Exception { SearchHandler searchHandler1 = mock(SearchHandler.class); @@ -717,7 +717,34 @@ public void getSearchHandler_shouldFailIfTwoSearchHandlersMatchGivenResourceAndP Map parameters = new HashMap(); parameters.put("source", new String[] { "some name" }); parameters.put("code", new String[] { "some code" }); - + + assertThat(restService.getSearchHandler("v1/concept", parameters), is(searchHandler1)); + } + + @Test + public void getSearchHandler_shouldFailIfTwoSearchHandlersMatchGivenResourceAndParametersAndNoSearchHandlerIdIsSpecified() + throws Exception { + + SearchHandler searchHandler1 = mock(SearchHandler.class); + SearchConfig searchConfig1 = new SearchConfig("conceptByName", "v1/concept", "1.8.*", new SearchQuery.Builder( + "description").withRequiredParameters("source").withOptionalParameters("code").build()); + when(searchHandler1.getSearchConfig()).thenReturn(searchConfig1); + + SearchHandler searchHandler2 = mock(SearchHandler.class); + SearchConfig searchConfig2 = new SearchConfig("conceptByMapping", "v1/concept", "1.8.*", new SearchQuery.Builder( + "description").withRequiredParameters("source").withOptionalParameters("code").build()); + when(searchHandler2.getSearchConfig()).thenReturn(searchConfig2); + + setCurrentOpenmrsVersion("1.8.10"); + + when(restHelperService.getRegisteredSearchHandlers()).thenReturn(asList(searchHandler1, searchHandler2)); + + RestUtil.disableContext(); //to avoid a Context call + + Map parameters = new HashMap(); + parameters.put("source", new String[] { "some name" }); + parameters.put("code", new String[] { "some code" }); + expectedException.expect(InvalidSearchException.class); expectedException.expectMessage("The search is ambiguous. Please specify s="); restService.getSearchHandler("v1/concept", parameters); diff --git a/omod/pom.xml b/omod/pom.xml index b91f81b30..1cc36704d 100644 --- a/omod/pom.xml +++ b/omod/pom.xml @@ -3,7 +3,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT webservices.rest-omod jar diff --git a/pom.xml b/pom.xml index f698fb6be..ae596b32d 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.openmrs.module webservices.rest - 2.40.0-SNAPSHOT + 2.41.0-SNAPSHOT pom Rest Web Services Parent project for the Rest Web Services Module