私はいくつかのサーブレットを持っています。
- JSON でエンコードされたリクエストを入力として受け取り、
- それらを処理し、
- JSON でエンコードされたオブジェクトとしてクライアントに応答を返します。
これまでは Android をクライアントとして使用していました (Android のサンプル コードは以下を参照してください)。
ここで、リクエストを送信してレスポンスを受信する単純な古い Java プログラムを作成したいと思います (Android コードと同じことを行います)。この目的のために、私は Java テスト (コードは以下のセクションJava コードを参照) を作成し、実行しました。
クライアント側では、次のエラーが発生します。
21:43:38.930 [main] ERROR r.a.c.t.TestAcceptanceProcedure1 -
java.io.IOException: Server returned HTTP response code: 405 for URL: http://myserver/myapp/rest/GetUserIdService
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) ~[na:1.6.0_23]
at testclient.TestAcceptanceProcedure1.test(TestAcceptanceProcedure1.java:47) ~[test-classes/:na]
サーバー ログに次のメッセージが表示されます。
WARNING: No operation matching request path "/myapp/rest/GetUserIdService" is found, Relative Path: /, HTTP Method: GET, ContentType: */*, Accept: text/html,image/gif,image/jpeg,*/*,*/*;q=.2,. Please enable FINE/TRACE log level for more details
質問:このエラーを修正するには、Java テストをどのように変更すればよいですか?
サーバーが稼働していることに注意してください (Android コードを実行すると動作します)。
Android コード:
リクエストの送信とレスポンスの受信:
final GetSimulationStatusRequest request = new GetSimulationStatusRequest();
final String json = Utils.convertToJson(request, getClass());
final String serverUrl = Utils.getServerUrl(this, "GetSimulationStatusService");
final IGetSimulationStatusAsyncTask getSimulationStatusTask =
asyncTaskFactory.createGetSimulationStatusAsyncTask(getWebServiceHelper());
Utils.setRequestAndServerUrl(json, serverUrl, getSimulationStatusTask);
final GetSimulationStatusResponse simulationStatusReponse =
getSimulationStatusTask.get();
Utils.convertToJson:
public static String convertToJson(final Object aRequest, Class<? extends Activity> aClass) {
final ObjectMapper mapper = new ObjectMapper();
String json = null;
try {
json = mapper.writeValueAsString(aRequest);
} catch (final JsonProcessingException exception) {
Log.e(aClass.getSimpleName(), exception.getLocalizedMessage(),
exception);
}
return json;
}
Utils.setRequestAndServerUrl:
public static void setRequestAndServerUrl(final String aJson,
final String aServerUrl, final IAsyncTask aTask) {
aTask.addNameValuePair("request", aJson);
aTask.sendRequest(new String[] { aServerUrl });
}
GetSimulationStatusAsyncTask:
public class GetSimulationStatusAsyncTask
extends AsyncTask<String, String, GetSimulationStatusResponse>
implements IGetSimulationStatusAsyncTask {
private static final String TAG = GetSimulationStatusAsyncTask.class.getSimpleName();
private IWebServiceTaskHelper helper;
private ICcpResponseParser<GetSimulationStatusResponse> responseParser =
new CcpResponseParser<GetSimulationStatusResponse>();
public GetSimulationStatusAsyncTask(final IWebServiceTaskHelper aHelper) {
helper = aHelper;
}
@Override
public void addNameValuePair(final String aName, final String aValue) {
helper.addNameValuePair(aName, aValue);
}
@Override
protected GetSimulationStatusResponse doInBackground(String... aArgs) {
return (GetSimulationStatusResponse)Utils.processResponse(this.helper, TAG, responseParser,
GetSimulationStatusResponse.class, aArgs);
}
@Override
public void sendRequest(final String[] aArgs) {
execute(aArgs);
}
}
Java コード:
@Test
public void test() throws JsonProcessingException, MalformedURLException {
final GetUserIdRequest request = new GetUserIdRequest();
request.setDeviceId("PC1");
final String requestAsString = convertToJson(request);
final String serverUrl = getServerUrl("GetUserIdService");
final URL url = new URL(serverUrl);
HttpURLConnection connection = null;
InputStream inputStream = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("request", requestAsString);
connection.connect();
inputStream = connection.getInputStream();
final String responseAsString = IOUtils.toString(inputStream);
LOGGER.debug("responseAsString: " + responseAsString);
} catch (final IOException exception) {
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
}
}
private String convertToJson(final GetUserIdRequest aRequest) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(aRequest);
}
private String getServerUrl(final String aServiceName)
{
return "http://myserver.com/myapp/rest/" + aServiceName;
}
更新 1 (2013 年 9 月 10 日 12:23 MSK):
@Path("/GetSimulationStatusService")
public class GetSimulationStatusService extends BaseCcpService {
private GetSimulationStatusRequestParser requestParser =
new GetSimulationStatusRequestParser();
@POST
@Produces("text/plain")
public String getSimulationStatus(@FormParam("request") final String aRequestJson)
throws JsonProcessingException
{
final GetSimulationStatusRequest request = requestParser.convert(aRequestJson);
final GetSimulationStatusResponse response = new GetSimulationStatusResponse();
response.setRequestId(request.getId());
response.setCycle(getPersistence().getCurrentCycle(request.getUserId()));
response.setLabourForce(getPersistence().getLabourForceSimulationParameter(
request.getUserId()));
return getObjectMapper().writeValueAsString(response);
}
}
更新 2 (2013 年 9 月 10 日 20:48 MSK):以下に示すようにコードを変更すると、500 HTTP 応答が返されます。サーバー側ではaRequest
、メソッドの引数GetUserIdService.getUserId
は null です。
connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("request", requestAsString);
connection.setRequestMethod("POST"); // Added this line
connection.connect();
更新 3 (09.10.2013 23:15):これは動作します:
@Test
public void test() throws JsonProcessingException, MalformedURLException
{
final GetUserIdRequest request = new GetUserIdRequest();
request.setDeviceId("PC1");
final String requestAsString = convertToJson(request);
final String serverUrl = getServerUrl("GetUserIdService");
final URL url = new URL(serverUrl);
HttpURLConnection connection = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.connect();
outputStream = connection.getOutputStream();
IOUtils.write("request=" + requestAsString, outputStream);
inputStream = connection.getInputStream();
final String responseAsString = IOUtils.toString(inputStream);
LOGGER.debug("responseAsString: " + responseAsString);
} catch (final IOException exception) {
LOGGER.error("", exception);
}
finally
{
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}