4

私の REST サービスでの注文プロセスでは、「記事」のリストをクライアントからサーバーに送信する必要があります。これらの記事オブジェクトは自作のエンティティ タイプです。STRING または INTEGER オブジェクトのリストの送信が機能し、@FormParam を介して送信することが既にわかっています。

しかし、自分のオブジェクトのリストを送信しようとするとすぐに (1 つのオブジェクトのみでも)、常にHTTP 400 エラー "Bad Request" が発生します。

以下のようなまったく同じコード(form.add()のパラメーターとサーバーメソッドのパラメーターのみが変更されました)とpostet文字列、整数、および文字列のリストを正常に試しました。独自のオブジェクトタイプを送信するだけで問題が発生します。
ログは、サーバー メソッドに到達していないことを示しています。プロセスはどこかで壊れています。

また、プロキシ (Apache JMeter) を使用してリクエストを取得しようとしました。ここでは、パラメーターkundeに value が含まれていることが示されていますentities.Kunde%40af8358。したがって、オブジェクトは完全に (またはまったく) シリアル化されていないと思います。しかし、応答でこの種のオブジェクトをサーバーからクライアントに送信すると問題なく動作します。ここでは、XML シリアル化は問題ありません。

その理由は何ですか?POST で独自の型を送信することはできないのでしょうか?
(PS:Kunde私の例の型はシリアライズ可能で、注釈が付けられてい@XmlRootElementます。)

よろしくお願いします。
ジャナ

: SAP Netweaver AS を使用しています。しかし、これまでは他のすべての Java AS と同じように動作していたので、これが理由になるとは思いません。独自のエンティティを持たない POST であっても、他のすべての REST 操作は機能します。

追加: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());
4

1 に答える 1

2

エンティティ「クンデ」が正しく送信されていないという新しい情報により、解決策が見つかりまし
:

エンティティ クラスを明示的に 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());
...

サーバー側で 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 ソリューション:

クライアント側でエンティティを 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文字列をオブジェクトに変換する場合:

...
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 などは package からのものjavax.xml.bind.*です。クラス ObjectMapper は package からのものorg.codehaus.jackson.map.*です。

PS:今はプレーンな String を送信しているため、 も使用できます@QueryParam。しかし、それはお勧めしません。なぜなら、XML 全体を URL のテキスト文字列として送信することになるからです。についても同様です@PathParam

形式は XML 形式よりもスリムであり、スリムであることは REST の目的であるため、JSON をお勧めします。

于 2013-09-10T09:27:01.227 に答える