繁体   English   中英

POST期间在REST Web服务中使用FormParam包含自己的对象(例如实体)的HTTP 400错误

[英]HTTP 400 error in REST web service during POST with FormParam containing own objects (e.g. enities)

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

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

我尝试了如下相同的代码(仅更改了form.add()的参数和server方法的参数),并且成功地发布了Postet字符串,整数和字符串列表。 这只会使发送自己的对象类型产生问题。
日志记录告诉我未达到服务器方法。 这个过程以前被打破了。

我还尝试通过使用代理(Apache JMeter)来获取请求。 这里说参数kunde包含值entities.Kunde%40af8358 因此,我猜该对象没有被彻底(或根本没有)序列化。 但是在响应中将这种对象从服务器发送到客户端可以很好地工作-在这里XML序列化没有问题。

可能是什么原因? 是否可能无法通过POST发送自己的类型?
(PS:类型Kunde在我的例子是可序列化和带注释@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());

由于新的信息,即实体“ Kunde”的传输不正确,我发现
解决方案

我明确地将实体类转换为XML / JSON(无论哪种方式都可行),然后将该XML / JSON作为String形式放入表单中。 在服务器端,我将XML / JSON字符串转换回了Entity,这很有效。
(似乎无法传输不像String或Integer 那样的对象。)

希望这将帮助遇到相同问题的每个人都通过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转换回服务器端的对象:

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

要在客户端将Entity更改为JSON String:

...
OutputStream out = new ByteArrayOutputStream();

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, kunde);
out.close();

Form form = new Form();
form.add("entity", out.toString());
...

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

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

PS:因为现在传输纯字符串,所以您也可以使用@QueryParam 但是我不建议这样做,因为您会将整个XML作为URL中的文本String传输。 @PathParam

我建议使用JSON ,因为该格式比XML格式更细长,而细长是REST的目标。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM