Java REST web服务在使用包含自己对象(例如enities)的FormParam发布时出现HTTP 400错误

Java REST web服务在使用包含自己对象(例如enities)的FormParam发布时出现HTTP 400错误,java,rest,bad-request,http-status-code-400,form-parameter,Java,Rest,Bad Request,Http Status Code 400,Form Parameter,对于REST服务中的订购过程,我必须将“文章”列表从客户端发送到服务器。这些项目对象是自制的实体类型。我已经发现,通过@FormParam发送字符串或整数对象列表确实有效 但是,只要我尝试发送我自己的对象列表(即使只有一个对象),我总是会收到一个HTTP 400错误“错误请求” 我尝试了下面同样的代码(只更改了form.add()的参数和服务器方法的参数)和poset字符串、整数和字符串列表。它只会在发送自己的对象类型时出现问题。 日志记录告诉我未到达服务器方法。这个过程在以前的某个地方被打破了

对于REST服务中的订购过程,我必须将“文章”列表从客户端发送到服务器。这些项目对象是自制的实体类型。我已经发现,通过@FormParam发送字符串或整数对象列表确实有效

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

我尝试了下面同样的代码(只更改了form.add()的参数和服务器方法的参数)和poset字符串、整数和字符串列表。它只会在发送自己的对象类型时出现问题。
日志记录告诉我未到达服务器方法。这个过程在以前的某个地方被打破了

我还尝试使用代理(ApacheJMeter)获取请求。这里表示参数
kunde
包含值
entities.kunde%40af8358
。因此,我猜对象没有完全序列化(或者根本没有序列化)。但是,在响应中将这种对象从服务器发送到客户机效果很好——在这里,XML序列化是没有问题的

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

提前感谢您的帮助
雅娜

注意:我将SAP Netweaver用作。但直到现在,它的行为和其他Java一样,所以我不认为这是原因。其他所有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中):

其中,服务是这样构建的:

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());
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=newdefaultclientconfig();
Client=Client.create(config);
service=client.resource(UriBuilder.fromUri(“”.build());

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

我明确地将实体类转换为XML/JSON(无论哪种方式都有效),并将该XML/JSON作为字符串放入表单中。在服务器端,我将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());
...
...
OutputStream out = new ByteArrayOutputStream();

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, kunde);
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();
}
...
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();
}

2)JSON解决方案:

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

...
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());
...
...
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 = JAXB.unmarshal(inputStream, Kunde.class);       

    return "Der Name des Kunden ist: "+kunde.getVorname()+" "+kunde.getNachname();
}
...
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
。但我不建议这样做,因为您将在URL中以文本字符串的形式传输整个XML。这同样适用于
@PathParam


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

您能检查发送的实际HTTP请求并发布它吗?我如何获得构建的HTTP请求?(从来没有这样做过)你可以试试看,这可能很难。我在一家公司的非管理员电脑上工作。我不允许在这里下载安装文件(exe)(我可以在家里下载),但我不确定是否可以在这里成功使用甚至安装WireShark。。。(但我会尝试一下!)还有其他可能性吗?我尝试使用代理(ApacheJMeter)获取请求。这里表示参数
kunde
的值为
entities.kunde%40af8358
。因此,我猜对象没有完全序列化(或者根本没有序列化)。但是,在响应中将这种对象从服务器发送到客户机效果很好——在这里,XML序列化是没有问题的。