Java POST 期间 REST Web 服务中的 HTTP 400 错误,其中 FormParam 包含自己的对象(例如实体)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18694297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTTP 400 error in REST web service during POST with FormParam containing own objects (e.g. enities)
提问by Jana
For an ordering process in my REST service I have to send a list of "articles" from client to server. These article objects are of a self-made entity type. I already found out that sending a list of STRING or INTEGER objects does work, sending it via @FormParam.
对于 REST 服务中的订购流程,我必须将“文章”列表从客户端发送到服务器。这些物品对象是自制的实体类型。我已经发现发送 STRING 或 INTEGER 对象列表确实有效,通过@FormParam 发送。
But as soon as I try to send a list of my own objects (even only ONE object), I always get a HTTP 400 error "Bad Request".
但是一旦我尝试发送我自己的对象列表(即使只有一个对象),我总是会收到HTTP 400 错误 "Bad Request"。
I tried excatly the same code like below (only the parameters of form.add() and the parameters of the server method were altered) and postet Strings, Integers and lists of Strings successfully. It only makes problems sending own object types.
Logging told me that the server method isn't reached. The process is broken somewhere before.
我尝试了与下面完全相同的代码(仅更改了 form.add() 的参数和服务器方法的参数)和 postet 字符串、整数和字符串列表。它只会在发送自己的对象类型时出现问题。
日志记录告诉我没有到达服务器方法。这个过程之前在某个地方被破坏了。
I also tried to get the request by using a proxy (Apache JMeter). Here it says that the parameter kunde
contains the value entities.Kunde%40af8358
. So I guess the object is not serialized thoroughly (or at all). But sending this kind of object from server to client in a response works fine - here the XML-serialization is no problem.
我还尝试使用代理(Apache JMeter)来获取请求。这里它说参数kunde
包含值entities.Kunde%40af8358
。所以我猜这个对象没有彻底(或根本没有)序列化。但是在响应中将这种对象从服务器发送到客户端工作正常 - 在这里 XML 序列化没有问题。
What might be the reason? Is it maybe NOT possible to send own types through POST?
(PS: The type Kunde
in my example is serializable and annotated with @XmlRootElement
.)
可能是什么原因?是否可能无法通过 POST 发送自己的类型?
(PS:Kunde
我的例子中的类型是可序列化的并用@XmlRootElement
.)
Thank you in advance for your help!
Jana
预先感谢您的帮助!
贾娜
Note: I'm using the SAP Netweaver AS. But until now it behaved like every other Java AS, so I don't think this will be the reason. Every other REST operation does work, even POST without own entities.
注意:我使用的是 SAP Netweaver AS。但到目前为止,它的行为与其他所有 Java AS 一样,所以我认为这不是原因。所有其他 REST 操作都可以工作,即使是没有自己实体的 POST。
Addition: I'm using the JERSEY library.
另外:我正在使用 JERSEY 库。
My Code on server side:
我在服务器端的代码:
@Path("/test")
@POST
@Produces(MediaType.TEXT_XML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String test(
@FormParam("kunde") Kunde kunde) {
return "The name of the customer is: "
+kunde.getVorname()+" "+kunde.getNachname();
}
My code on client side (the method is in a Session Bean):
我在客户端的代码(该方法在会话 Bean 中):
public String test() {
Kunde kunde = new Kunde();
kunde.setNachname("Müller");
kunde.setVorname("Kurt");
Form form = new Form();
form.add("kunde", kunde);
return service
.path("test")
.type(MediaType.APPLICATION_FORM_URLENCODED)
.accept(MediaType.TEXT_XML)
.post(String.class, form);
}
where serviceis built like that:
这里的服务是建立这样的:
com.sun.jersey.api.client.Client;
com.sun.jersey.api.client.WebResource;
com.sun.jersey.api.client.config.ClientConfig;
com.sun.jersey.api.client.config.DefaultClientConfig;
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
service = client.resource(UriBuilder.fromUri("<service-url>").build());
采纳答案by Jana
Due to the new information that the entity "Kunde" isn't trasmitted correctly I found a
SOLUTION:
由于实体“Kunde”未正确传输的新信息,我找到了一个
解决方案:
I explicitely transformed the entity class into XML/JSON (either way is working) and put that XML/JSON as a String in the form. On the server's side I transformed the XML/JSON String back into the Entity, this worked.
(Seems like it is NOT possible to transmit an object not beeing String or Integer as it is.)
我明确地将实体类转换为 XML/JSON(无论哪种方式都有效)并将该 XML/JSON 作为字符串放入表单中。在服务器端,我将 XML/JSON 字符串转换回实体,这奏效了。
(似乎不可能传输一个不是 String 或 Integer 的对象,因为它是。)
Hope this will help everyone who faces the same problem transmitting objects from client to server via REST.
(Sending a Listof XML/JSON-converted objects is still to test. I'll add the result here soon.)
Greetings and thanks to chrylis for his/her comments and hints.
Jana
希望这将帮助面临相同问题的每个人通过 REST 将对象从客户端传输到服务器。
(发送XML/JSON 转换对象的列表仍有待测试。我很快就会在此处添加结果。)
问候并感谢 chrylis 的评论和提示。
贾娜
Here's the code for the solution, but for shortness it's only the new parts.
这是解决方案的代码,但为简短起见,它只是新部分。
1) The XML solution:
1)XML解决方案:
For changing Entity into XML String on Client's side:
在客户端将实体更改为 XML 字符串:
...
OutputStream out = new ByteArrayOutputStream();
JAXBContext context = JAXBContext.newInstance(Kunde.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(kunde, out);
out.close();
Form form = new Form();
form.add("entity", out.toString());
...
For transforming the XML back to an Object on the Server's side:
将 XML 转换回服务器端的对象:
...
public String test(
@FormParam("entity") String entityString) {
InputStream inputStream = new ByteArrayInputStream(entityString.getBytes());
Kunde kunde = JAXB.unmarshal(inputStream, Kunde.class);
return "Der Name des Kunden ist: "+kunde.getVorname()+" "+kunde.getNachname();
}
2) The JSON solution:
2)JSON解决方案:
For changing Entity into JSON String on Client's side:
在客户端将实体更改为 JSON 字符串:
...
OutputStream out = new ByteArrayOutputStream();
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, kunde);
out.close();
Form form = new Form();
form.add("entity", out.toString());
...
For transforming the JSON String back to an Object on the Server's side:
将 JSON 字符串转换回服务器端的对象:
...
public String test(
@FormParam("entity") String entityString) {
InputStream inputStream = new ByteArrayInputStream(entityString.getBytes());
Kunde kunde = new ObjectMapper().read((inputStream, Kunde.class));
return "Der Name des Kunden ist: "+kunde.getVorname()+" "+kunde.getNachname();
}
The classes JAXB, JAXBContext, Marshaller etc. are from package javax.xml.bind.*
. The class ObjectMapper is from package org.codehaus.Hymanson.map.*
.
JAXB、JAXBContext、Marshaller 等类来自 package javax.xml.bind.*
。类 ObjectMapper 来自 package org.codehaus.Hymanson.map.*
。
PS:Because transmitting plain String now, you also could use @QueryParam
. But I wouldn't recomment that, because you'd be transmitting the whole XML as a text String in the URL. Same goes for @PathParam
.
PS:因为现在传输纯字符串,你也可以使用@QueryParam
. 但我不建议这样做,因为您会将整个 XML 作为 URL 中的文本字符串传输。也一样@PathParam
。
I'd recommend JSON, because the format is more slender than the XML format, and being slender is the aim of REST.
我推荐 JSON,因为格式比 XML 格式更细长,而细长是 REST 的目标。