Мне не удается запустить простой тест интеграции клиента REST. Я использую Spring 3.1 MVC с настройкой JavaConfig. Я использую Maven, и я могу без проблем создавать, запускать и развертывать мое текущее веб-приложение.
Во-первых, вот код и конфиг
Мой контроллер
@Controller
@RequestMapping("/rest")
public class StubRestController {
@Inject
private TestData testData;
@RequestMapping(value=Endpoints.GET_RESOURCES, method=RequestMethod.GET, produces="application/json")
@ResponseStatus(HttpStatus.OK)
public @ResponseBody JSONObject getResources(@RequestParam(value="q") String query, @RequestParam int indexFrom, @RequestParam int indexTo) throws JSONException {
return makeRequest(query, indexFrom, indexTo, testData.getResources());
}
@RequestMapping(value=Endpoints.GET_LOCATIONS, method=RequestMethod.GET, produces="application/json")
@ResponseStatus(HttpStatus.OK)
public @ResponseBody JSONObject getLocations(@RequestParam(value="q") String query, @RequestParam int indexFrom, @RequestParam int indexTo) throws JSONException {
return makeRequest(query, indexFrom, indexTo, testData.getLocations());
}
private JSONObject makeRequest(String query, int indexFrom, int indexTo, String[] data) throws JSONException {
int count = 0;
final JSONArray resources = new JSONArray();
for (final String resourceName: data) {
final String lowerColor = resourceName.toLowerCase();
final int has = lowerColor.indexOf(query.toLowerCase());
if (!query.isEmpty() && (query.equals("*") || has >= 0)) {
final JSONObject resource = new JSONObject();
resource.put("DisplayName", resourceName);
resource.put("Value", resourceName); // shouldn't this be a unique id? e.g., resourceid
resources.put(resource);
count++;
}
}
final JSONArray partial = new JSONArray();
if (resources.length() > 0) {
final int end = count - 1 > indexTo ? indexTo : count - 1;
for (int i = indexFrom; i <= end; i++) {
partial.put(resources.get(i));
}
}
final JSONObject result = new JSONObject();
result.put("TotalSize", count);
result.put("Options", partial);
return result;
}
@ExceptionHandler(JSONException.class)
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason="No data found matching criteria")
public void notFound() { }
}
Мой тест
@ContextConfiguration(classes={ RestClientContext.class }, loader=AnnotationConfigContextLoader.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class StubRestClientITCase {
private static final String SCHEME = "http";
private static final String HOST = "localhost";
private static final int PORT = 8081;
// requests must match <url-pattern> in order to be handled by DispatcherServlet
private static final String ENDPOINT_PREFIX = "spp-emkt-mui-experimental/EMKT/services/rest";
private static final String QUERY_KEY = "q";
private static final String INDEX_FROM_KEY = "indexFrom";
private static final String INDEX_TO_KEY = "indexTo";
private static final String TOTAL_SIZE_KEY = "TotalSize";
private Logger log = LoggerFactory.getLogger(StubRestClientITCase.class);
@Inject
RestTemplate restTemplate;
@Test
public void testGetResources() {
// Case 1: Discover all resources using * (asterisk), first 25
final URI uri = buildUri("*", 0, 24, Endpoints.GET_RESOURCES);
final HttpEntity<JSONObject> response = obtainResponse(uri);
try {
Assert.assertTrue(response.hasBody());
Assert.assertEquals(25, Integer.parseInt(response.getBody().getString(TOTAL_SIZE_KEY)));
} catch (final JSONException je) {
fail("Could not obtain \"" + TOTAL_SIZE_KEY + "\" from JSON payload for getResources().\n" + je.getMessage());
}
}
private URI buildUri(String query, int indexFrom, int indexTo, String endPointUrl) {
final UriComponents uriComponents =
UriComponentsBuilder.newInstance()
.scheme(SCHEME).host(HOST).port(PORT).path(ENDPOINT_PREFIX + endPointUrl)
.queryParam(QUERY_KEY, query)
.queryParam(INDEX_FROM_KEY, indexFrom)
.queryParam(INDEX_TO_KEY, indexTo)
.build()
.encode();
final URI uri = uriComponents.toUri();
return uri;
}
private HttpEntity<JSONObject> obtainResponse(URI uri) {
final HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setAccept(Arrays.asList(new MediaType[] {MediaType.APPLICATION_JSON}));
requestHeaders.setAcceptCharset(Arrays.asList(new Charset[] {Charset.forName("UTF-8")}));
final HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
final HttpEntity<JSONObject> response = restTemplate.exchange(uri, HttpMethod.GET, requestEntity, JSONObject.class);
return response;
}
}
Мой web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.spp.mui.gwt.server.config.WebAppContextExperimental</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>gwt</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gwt</servlet-name>
<url-pattern>/EMKT/service/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<session-config>
<session-timeout>0</session-timeout>
</session-config>
</web-app>
Я вижу, как мои методы контроллера отображаются при запуске сервера ...
17:48:58,651 INFO [RequestMappingHandlerMapping] Mapped "{[/rest/resources],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}"
17:48:58,651 INFO [RequestMappingHandlerMapping] Mapped "{[/rest/locations],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}"
Когда тест запускается, я получаю ...
17:49:00,617 DEBUG [AutowiredAnnotationBeanPostProcessor] Autowiring by type from bean name 'com.spp.mui.gwt.server.controller.stub.StubRestClientITCase' to bean named 'restTemplate'
17:49:00,648 DEBUG [RestTemplate] Created GET request for "http://localhost:8080/EMKT/services/rest/resources?q=*&indexFrom=0&indexTo=24"
17:49:00,680 DEBUG [RestTemplate] Setting request Accept header to [application/json]
17:49:00,742 WARN [RestTemplate] GET request for "http://localhost:8080/EMKT/services/rest/resources?q=*&indexFrom=0&indexTo=24" resulted in 404 (Not Found); invoking error handler
Наконец ...
Tests in error:
testGetResources(com.spp.mui.gwt.server.controller.stub.StubRestClientITCase): 404 Not Found
В чем может быть дело? Думая, что это как-то связано с url-pattern in servlet-mapping . Я пытался следовать документации Spring по настройке, но безуспешно. Примечание: я негибко настроен на это, поскольку у меня есть настройка GWT-SL для сопоставления служебных интерфейсов RPC.
ОБНОВЛЕНИЕ # 1
Если я попытаюсь использовать
curl --verbose -H "Accept: application/json" "localhost:8081/spp-emkt-mui-experimental/EMKT/service/rest/resources?q=*&indexFrom=0&indexTo=24"
против развертывания Tomcat 6 (с использованием грузового плагина) я получаю другой результат:
* About to connect() to localhost port 8081 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET /spp-emkt-mui-experimental/EMKT/service/rest/resources?q=*&indexFrom=0&indexTo=24 HTTP/1.1
> User-Agent: curl/7.21.1 (i686-pc-mingw32) libcurl/7.21.1 OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:8081
> Accept: */*
>
< HTTP/1.1 406 Not Acceptable
< Server: Apache-Coyote/1.1
< Content-Type: text/html;charset=utf-8
< Content-Length: 1070
< Date: Tue, 28 Feb 2012 05:00:26 GMT
Что, похоже, указывает на то, что я не отправляю соответствующую информацию заголовка в моем запросе Hmmmmmm.
ОБНОВЛЕНИЕ № 2
Тест, как написано, возвращает 404. И завиток 406.
Я просмотрел так много, казалось бы, связанных постов и перепробовал так много вещей, что мне интересно, могут ли Spring MVC, GWT-RPC и GWT-SL быть объединены в одном контейнере. Рассматривается переход на RestyGWT с серверной стороной Spring MVC. Комментарии?