使用 JSON 字符串的请求正文进行发布的 Jax-RS 客户端

发布于 2024-10-16 02:59:40 字数 2632 浏览 3 评论 0原文

我正在使用 JaxRS 创建与供应商的 API 交互的客户端代码。我已经能够编写执行 GET 和 POST 的代码,这两者都没有请求正文。我目前在尝试执行仅发送请求正文的 POST 时遇到问题。我正在尝试发送一个简单的 JSON 字符串:

{"server":{"name":"HelloKitty","imageId":71,"flavorId":1}}

以下是我正在使用的 WebClient 的定义(用 Scala 编写,但我知道标头和授权已正确完成):

def postClient: WebClient = {
   val authClient = WebClient.create(authServer)
   authClient.header("X-Auth-User", apiUsername)
   authClient.header("X-Auth-Key", apiKey)

   val response = authClient.get
   val metadata = response getMetadata () map { case (k, v) => k -> v(0).toString }

   val client = WebClient.create(metadata.get("X-Server-Management-Url").getOrElse("Error in authentication response"))
   client.header("X-Auth-User", apiUsername)
   client.header("X-Auth-Key", apiKey)
   client.header("X-Auth-Token", metadata.get("X-Auth-Token").getOrElse("Error in authentication response"))
   client.header("Content-Type","application/json")
}

这是我的资源接口:

@Produces(Array("text/json"))
trait RackspaceServerApi {
    @Path("/servers.json")
    @GET
    def listServers(): String

    @Path("/servers/detail.json")
    @GET
    def listServersDetailed(): String

    @POST
    @Path("/servers")
    @Consumes(Array("application/json"))
    def createServerData(server: String)
}

这是我的方法创建代理并尝试发送请求

def createServer(name: String, imageId: Long, flavorId: Int) = {
    // this creates a simple pojo for the server
    val serverObject = new RackspaceCreateServerObject(name, imageId, flavorId, None, None)

    // i am using lift-web to handle the json
    // here I am unmarshalling the serverObject into a json string
    val jsonServerData = write(serverObject)

    val postProxy = JAXRSClientFactory.fromClient(RackspaceConnection.postClient, classOf[RackspaceServerApi], true)
    postProxy.createServerData(jsonServerData)
}

这是我得到的特定 WebApplicationException:

状态代码:[500]
实体:[没有找到响应类的消息正文编写器:JAXBElement。]

但是,如果我尝试使用 Web 客户端而不是像这样的代理发送请求:

def createServer(name: String, imageId: Long, flavorId: Int) = {
    // this creates a simple pojo for the server
    val serverObject = new RackspaceCreateServerObject(name, imageId, flavorId, None, None)

    // i am using lift-web to handle the json
    // here I am unmarshalling the serverObject into a json string
    val jsonServerData = write(serverObject)

    val webClient = RackspaceConnection.postClient
    webClient.path("/servers")
    webClient.post(jsonServerData)
}

它可以工作。我在界面中做错了什么吗(缺少一些神奇的注释组合?)?还是我没有设置什么? 我正在使用 Jax-RS 2.3.2。

I am using JaxRS to create client side code that interacts with a vendor's API. I have been able to write code that performs GET and POST, both of which do not have a request body. I am currently running into a problem trying to do a POST where there is only a request body being sent. I am trying to send a simple JSON string:

{"server":{"name":"HelloKitty","imageId":71,"flavorId":1}}

The following is the definition for the WebClient I am using (written in Scala, but I know that the headers and authorizations are being done correctly):

def postClient: WebClient = {
   val authClient = WebClient.create(authServer)
   authClient.header("X-Auth-User", apiUsername)
   authClient.header("X-Auth-Key", apiKey)

   val response = authClient.get
   val metadata = response getMetadata () map { case (k, v) => k -> v(0).toString }

   val client = WebClient.create(metadata.get("X-Server-Management-Url").getOrElse("Error in authentication response"))
   client.header("X-Auth-User", apiUsername)
   client.header("X-Auth-Key", apiKey)
   client.header("X-Auth-Token", metadata.get("X-Auth-Token").getOrElse("Error in authentication response"))
   client.header("Content-Type","application/json")
}

Here is my resource interface:

@Produces(Array("text/json"))
trait RackspaceServerApi {
    @Path("/servers.json")
    @GET
    def listServers(): String

    @Path("/servers/detail.json")
    @GET
    def listServersDetailed(): String

    @POST
    @Path("/servers")
    @Consumes(Array("application/json"))
    def createServerData(server: String)
}

Here is my method that creates a proxy and tries to send the request

def createServer(name: String, imageId: Long, flavorId: Int) = {
    // this creates a simple pojo for the server
    val serverObject = new RackspaceCreateServerObject(name, imageId, flavorId, None, None)

    // i am using lift-web to handle the json
    // here I am unmarshalling the serverObject into a json string
    val jsonServerData = write(serverObject)

    val postProxy = JAXRSClientFactory.fromClient(RackspaceConnection.postClient, classOf[RackspaceServerApi], true)
    postProxy.createServerData(jsonServerData)
}

And here is the specific WebApplicationException I get:

Status code: [500]
Entity: [No message body writer found for response class : JAXBElement.]

However, if I try to send the request using a webclient instead of a proxy like so:

def createServer(name: String, imageId: Long, flavorId: Int) = {
    // this creates a simple pojo for the server
    val serverObject = new RackspaceCreateServerObject(name, imageId, flavorId, None, None)

    // i am using lift-web to handle the json
    // here I am unmarshalling the serverObject into a json string
    val jsonServerData = write(serverObject)

    val webClient = RackspaceConnection.postClient
    webClient.path("/servers")
    webClient.post(jsonServerData)
}

It works. Am I doing something wrong in the interface (missing some magical combination of annotations?)? Or did I not set something up?
I am using Jax-RS 2.3.2.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

俯瞰星空 2024-10-23 02:59:40

您使用什么 JAX-RS 实现?

该错误消息表明您需要注册一个插件/模块来处理 JAXB bean 到 JSON 的编组。一些 JAX-RS 实现会自动执行此操作,一些则需要一些初始化。

What JAX-RS implementation are you using?

The error message indicates that you need to register a plugin/module to handle the marshalling of JAXB beans to JSON. Some JAX-RS implementations will do this automatically, some require some initialisation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文