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

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

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

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

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

可能是什么原因?是否可能无法通过POST发送自己的类型?
(PS:Kundein类型我的例子是可序列化的,并用@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("<service-url>").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的目标.

点赞