POST期间REST Web服务中的HTTP 400错误,FormParam包含自己的对象(例如enities)

对于我的REST服务中的订购流程,我必须从客户端向服务器发送“文章”列表。 这些文章对象是自制的实体类型。 我已经发现发送STRING或INTEGER对象列表确实有效,通过@FormParam发送它。

但是一旦我尝试发送我自己的对象列表(甚至只有一个对象),我总是得到HTTP 400错误“错误请求”

我疯狂地尝试了类似下面的代码(只有form.add()的参数和服务器方法的参数被更改)和postet字符串,整数和字符串列表成功。 它只会导致发送自己的对象类型的问题。
记录告诉我没有达到服务器方法。 这个过程在某个地方被打破了。

我还试图通过使用代理(Apache JMeter)来获取请求。 这里它表示参数kunde包含值entities.Kunde%40af8358 。 所以我猜这个对象没有彻底序列化(或根本没有)。 但是在响应中将这种对象从服务器发送到客户端工作正常 – 这里XML序列化没有问题。

可能是什么原因? 是否可能无法通过POST发送自己的类型?
(PS:我的示例中的@XmlRootElement类型是可序列化的,并使用@XmlRootElement注释。)

预先感谢您的帮助!
贾纳

注意 :我正在使用SAP Netweaver AS。 但直到现在它的表现与其他所有Java AS一样,所以我认为这不是原因。 每个其他REST操作都可以工作,甚至没有自己的实体的POST。

另外 :我正在使用JERSEY库。


服务器端的我的代码:

 @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(); } 

我在客户端的代码(该方法在会话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); } 

服务的构建方式如下:

 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("").build()); 

由于新的信息,实体“昆德”未被正确传递,我发现了一个
解决方案

我明确地将实体类转换为XML / JSON(无论哪种方式都在工作)并将XML / JSON作为String放在表单中。 在服务器端,我将XML / JSON字符串转换回实体,这很有用。
(似乎不可能传输一个不是字符串或整数的对象。)

希望这将帮助每个面临同样问题的人通过REST将对象从客户端传输到服务器。
发送XML / JSON转换对象的列表仍然要测试。我将很快在这里添加结果。

问候并感谢chrylis的评论和提示。
贾纳


这是解决方案的代码,但简而言之,它只是新的部分。

1)XML解决方案:

在客户端将实体更改为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()); ... 

要将XML转换回服务器端的Object:

 ... 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)JSON解决方案:

在客户端将实体更改为JSON字符串:

 ... OutputStream out = new ByteArrayOutputStream(); ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(out, kunde); out.close(); Form form = new Form(); form.add("entity", out.toString()); ... 

要将JSON字符串转换回服务器端的Object:

 ... 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(); } 

JAXB,JAXBContext,Marshaller等类来自包javax.xml.bind.* 。 ObjectMapper类来自包org.codehaus.jackson.map.*

PS:因为现在传输普通字符串,你也可以使用@QueryParam 。 但我不推荐这样做,因为你将整个XML作为URL中的文本字符串传输。 @PathParam

我推荐使用JSON ,因为格式比XML格式更纤细,而且细长是REST的目标。

Interesting Posts