私は 2 つの HATEOAS クライアントを作成しました。1 つは Java で、もう 1 つは Ruby で作成しました。あなたのフラストレーションを共有します。どちらの場合も、私が行っていたことに対するツールのサポートが完全に欠如していました。たとえば、私が使用していた REST API は、各ハイパーテキスト コントロールに使用する HTTP メソッドを教えてくれますが、HttpClientではメソッドを渡すことができないため、次の醜いコードになってしまいました (ところで、すべてのコードは内部に存在します)。カスタム Ant タスク、したがってBuildException
s):
private HttpMethod getHypermediaControl(Node href, Node method,
NodeList children) {
if (href == null) {
return null;
}
HttpMethod control;
if (method == null || method.getNodeValue().equals("")
|| method.getNodeValue().equalsIgnoreCase("GET")) {
control = new GetMethod(href.getNodeValue());
} else if (method.getNodeValue().equalsIgnoreCase("POST")) {
control = new PostMethod(href.getNodeValue());
} else if (method.getNodeValue().equalsIgnoreCase("PUT")) {
control = new PutMethod(href.getNodeValue());
} else if (method.getNodeValue().equalsIgnoreCase("DELETE")) {
control = new DeleteMethod(href.getNodeValue());
} else {
throw new BuildException("Unknown/Unimplemented method "
+ method.getNodeValue());
}
control.addRequestHeader(accept);
return control;
}
これが、私が使用する REST クライアント ユーティリティ メソッドの基礎となりました。
private HttpMethod getHypermediaControl(String path, Document source)
throws TransformerException, IOException {
Node node = XPathAPI.selectSingleNode(source, path);
return getHypermediaControl(node);
}
private HttpMethod getHypermediaControl(Node node) {
if (node == null) {
return null;
}
NamedNodeMap attributes = node.getAttributes();
if (attributes == null) {
return null;
}
Node href = attributes.getNamedItem("href");
Node method = attributes.getNamedItem("method");
HttpMethod control = getHypermediaControl(href, method,
node.getChildNodes());
return control;
}
private Document invokeHypermediaControl(HttpClient client, Document node,
final String path) throws TransformerException, IOException,
HttpException, URIException, SAXException,
ParserConfigurationException, FactoryConfigurationError {
HttpMethod method = getHypermediaControl(path, node);
if (method == null) {
throw new BuildException("Unable to find hypermedia controls for "
+ path);
}
int status = client.executeMethod(method);
if (status != HttpStatus.SC_OK) {
log(method.getStatusLine().toString(), Project.MSG_ERR);
log(method.getResponseBodyAsString(), Project.MSG_ERR);
throw new BuildException("Unexpected status code ("
+ method.getStatusCode() + ") from " + method.getURI());
}
String strResp = method.getResponseBodyAsString();
StringReader reader = new StringReader(strResp);
Document resp = getBuilder().parse(new InputSource(reader));
Node rval = XPathAPI.selectSingleNode(resp, "/");
if (rval == null) {
log(method.getStatusLine().toString(), Project.MSG_ERR);
log(method.getResponseBodyAsString(), Project.MSG_ERR);
throw new BuildException("Could not handle response");
}
method.releaseConnection();
return resp;
}
この少しのコードで、返されるドキュメント内のハイパーメディア コントロールをトラバースするクライアントをかなり簡単に作成できます。欠落している主なビットは、フォーム パラメーターのサポートです。幸いなことに、私が使用しているすべてのコントロールは、1 つを除いてパラメーターがありません (リファクタリングに関しては 3 つのルールに従います)。完全を期すために、そのコード スニペットは次のようになります。
HttpMethod licenseUpdateMethod = getHypermediaControl(
"/license/update", licenseNode);
if (licenseUpdateMethod == null) {
log(getStringFromDoc(licenseNode), Project.MSG_ERR);
throw new BuildException(
"Unable to find hypermedia controls to get the test suites or install the license");
} else if (license != null) {
EntityEnclosingMethod eem = (EntityEnclosingMethod) licenseUpdateMethod;
Part[] parts = { new StringPart("license", this.license) };
eem.setRequestEntity(new MultipartRequestEntity(parts, eem
.getParams()));
int status2 = client.executeMethod(eem);
if (status2 != HttpStatus.SC_OK) {
log(eem.getStatusLine().toString(), Project.MSG_ERR);
log(eem.getResponseBodyAsString(), Project.MSG_ERR);
throw new BuildException("Unexpected status code ("
+ eem.getStatusCode() + ") from " + eem.getURI());
}
eem.releaseConnection();
}
ここで、 の子を調べて、/license/update
どのパラメータを渡す必要があるかを判断する必要がありますが、従う必要があるパラメータ化されたフォームがさらに 2 つになるまで待つ必要があります。
ところで、すべての努力の結果、クライアントに影響を与えずにサーバーを変更することは非常に満足のいくものであり、簡単でした. とても気持ちが良かったので、一部の州では禁止されていないことに驚きました.