【问题标题】:REST Client InboundJaxrsResponse Status 500 , when attempting to POSTREST 客户端 InboundJaxrsResponse 状态 500 ,尝试发布时
【发布时间】:2015-04-17 18:50:17
【问题描述】:

问题 1. 当我使用 Todo 构造函数设置 Todo 对象时,我得到一个 Http Status 500。它适用于 TodoDao 中设置的现有值。我在这里缺少什么?(请在下面找到代码和堆栈跟踪):

问题2。我正在尝试如下设置表单参数,但我无法解决以下编译错误:

> The method post(Entity<?>, Class<T>) in the type SyncInvoker is not
> applicable for the arguments (Class<Form>, Form)

代码 sn -p 设置表格:

Form form = new Form();
                    form.param("id","45");
                    form.param("summary","Summary for id 45");
                    response =         target.path("rest").path("todos").path(todo.getId()).request()
                  .accept(MediaType.APPLICATION_FORM_URLENCODED).post(Form.class,form);

堆栈跟踪: `

Response Code is : 500
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><todoes><todo><description>Rest todo Description 2 </description><id>2</id><summary>Summary 2 - REST</summary></todo><todo><description>Rest todo Description 1</description><id>1</id><summary>Summary 1 - REST</summary></todo><todo><id>45</id><summary>Summary for id 45</summary></todo></todoes>

Post response200

`

TodosResourceClient.java

package com.dcr.jersey.client;



import java.net.URI;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.Form;

import org.glassfish.jersey.client.ClientConfig;


import com.dcr.jersey.jaxb.model.Todo; 

public class TodosResourceClient {


    public static void main(String[] args) {
        ClientConfig config = new ClientConfig();
        Client client = ClientBuilder.newClient(config);
        WebTarget target = client.target(getBaseURI());

        Todo todo = new Todo("38","38 - Summary ReEntred");

        target.path("rest").path("todos").request().post(Entity.json(todo));

        Response response = target.path("rest").path("todos").path(todo.getId()).request()
                .accept(MediaType.APPLICATION_XML).get(Response.class);

        System.out.println("\n POST Response Code is : "+ response.getStatus());



       System.out.println(target.path("rest").path("todos").path(todo.getId()).request()
                        .accept(MediaType.APPLICATION_JSON).get(Response.class)
                        .toString()+"\n");

    System.out.println(target.path("rest").path("todos").request()
                        .accept(MediaType.APPLICATION_JSON).get(String.class)+"\n");

    System.out.println(target.path("rest").path("todos").request()
                        .accept(MediaType.APPLICATION_XML).get(String.class)+"\n");

    System.out.println(target.path("rest").path("todos/34").request()
                        .accept(MediaType.APPLICATION_JSON).get(String.class)+"\n");


                //target.path("rest").path("todos/38").request().delete();

                System.out.println(target.path("rest").path("todos").request()
                        .accept(MediaType.APPLICATION_XML).get(String.class)+"\n");

                Form form = new Form();
                form.param("id","45");
                form.param("summary","Summary for id 45");
                response = target.path("rest").path("todos").request().post(Entity.form(form));

                System.out.println("\nPost by FORM response code is "+ response.getStatus()+"\n");

                response = target.path("rest").path("todos/45").request().delete();// deletes a request

                System.out.println("\nDelete by FORM response code is "+ response.getStatus()+"\n");


    }
    private static URI getBaseURI() {

        return UriBuilder.fromUri("http://localhost:8080/com.dcr.jersey.first").build();

      }

}

Todo.java

package com.dcr.jersey.jaxb.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement

public class Todo {

    private String id;
    private String summary;
    private String description;
    public Todo(){}
    public Todo(String id,String summary){
        this.id=id;
        this.summary=summary;

    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    public String getSummary() {
        return summary;
    }
    public void setSummary(String summary) {
        this.summary = summary;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }


}

create_todo.htm:(保存在 Deployed Resources>webapp 文件夹下)

 <!DOCTYPE html>
<html>
 <head>
  <title>Form to create a new resource</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 

  <style>
    tab { padding-left: 4em; }
    </style>
 </head>
<body>

<form id= "myForm" action="../com.dcr.jersey.first/rest/todos" >

  <label for="id">ID</label>
  <input name="id" />
  <br/>
  <label for="summary">Summary</label>
  <input name="summary" />
  <br/>
  Description:
  <TEXTAREA NAME="description" COLS=40 ROWS=6></TEXTAREA>
  <br/> 
  <button type="button" value="Submit">Submit</button>  <tab> <button type="button" value="Delete">Delete</button>
  <script type="text/javascript">
        $("button.Submit").click(function(){
            $("#myForm").attr("method", "POST");
            $("#myForm").attr("action", "../com.dcr.jersey.first/rest/todos");
        });

        $("button.Delete").click(function(){
            $("#myForm").attr("method", "DELETE");
        });
  </script>

</form>

</body>
</html> 

TodosResource.java

package com.dcr.jersey.jaxb.resources;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

import com.dcr.jersey.jaxb.dao.TodoDao;
import com.dcr.jersey.jaxb.model.Todo;
//Will map the resource to the URL todos
@Path("/todos")
public class TodosResource {

    // Allows to insert contextual objects into the class,
      // e.g. ServletContext, Request, Response, UriInfo
      @Context
      UriInfo uriInfo;
      @Context
      Request request;
      @Context
      Todo todo;
    // Return the list of todos to the user in the browser
      @GET
      @Produces(MediaType.TEXT_XML)
      public List<Todo> getTodosBrowser() {
        List<Todo> todos = new ArrayList<Todo>();
        todos.addAll(TodoDao.instance.getModel().values());
        return todos;
      }
    // Return the list of todos for applications
      @GET
      @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
      public List<Todo> getTodos() {
        List<Todo> todos = new ArrayList<Todo>();
        todos.addAll(TodoDao.instance.getModel().values());
        return todos;
      }
    // retuns the number of todos
      // Use http://localhost:8080/de.vogella.jersey.todo/rest/todos/count
      // to get the total number of records
      @GET
      @Path("count")
      @Produces(MediaType.TEXT_PLAIN)
      public String getCount() {
        int count = TodoDao.instance.getModel().size();
        return String.valueOf(count);
      }

      @POST
      @Produces(MediaType.TEXT_HTML)
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      public void newTodo(@FormParam("id") String id,
          @FormParam("summary") String summary,
          @FormParam("description") String description,
          @Context HttpServletResponse servletResponse) throws IOException {
        Todo todo = new Todo(id, summary);
        if (description != null) {
          todo.setDescription(description);
        }
        TodoDao.instance.getModel().put(id, todo);
        servletResponse.sendRedirect("../Created_PopUp.html");
      }  

      @POST
      @Produces(MediaType.TEXT_HTML)
      @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})

      public void newTodoXMLJSON(Todo todo) throws IOException {
        this.todo=todo;
        TodoDao.instance.getModel().put(todo.getId(), todo);
      }  

      @DELETE
      @Produces(MediaType.TEXT_HTML)
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      public void delTodo(@FormParam("id") String id,
          @Context HttpServletResponse servletResponse) throws IOException {
          Todo c = TodoDao.instance.getModel().remove(id);
            if(c==null)
              throw new RuntimeException("Delete: Todo with " + id +  " not found");
            else servletResponse.sendRedirect("../create_todo.html");
      }  

      @Path("{todo}")
      public TodoResource getTodo(@PathParam("todo") String id) {
            return new TodoResource(uriInfo, request, id);
      }
}

TodoDao.java

package com.dcr.jersey.jaxb.dao;

import java.util.HashMap;
import java.util.Map;

import com.dcr.jersey.jaxb.model.Todo;


public enum TodoDao {
    instance;
    private Map<String,Todo> contentProvider = new HashMap<String, Todo>();
    private TodoDao(){
        Todo todo = new Todo("1","Summary 1 - REST");
        todo.setDescription("Rest todo Description 1");
        contentProvider.put("1",todo);
        todo = new Todo("2","Summary 2 - REST");
        todo.setDescription("Rest todo Description 2 ");
        contentProvider.put("2", todo);
    }
    public Map<String,Todo> getModel(){
        return contentProvider;
    }
}

TodoResource.java

package com.dcr.jersey.jaxb.resources;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
//import javax.ws.rs.POST;
import javax.ws.rs.DELETE;
//import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;

import com.dcr.jersey.jaxb.model.Todo;
import com.dcr.jersey.jaxb.dao.TodoDao;



public class TodoResource {
    @Context
    UriInfo uriInfo;
    @Context
    Request request;
    String id;

    public TodoResource(UriInfo uriInfo, Request request, String id) {
        this.uriInfo = uriInfo;
        this.request = request;
        this.id = id;
      }

    //Application Integration     
      @GET
      @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
      public Todo getTodo() {
        Todo todo = TodoDao.instance.getModel().get(id);
        if(todo==null)
          throw new RuntimeException("Get: Todo with " + id +  " not found");
        return todo;
      }

    // for the browser
      @GET
      @Produces(MediaType.TEXT_XML)
      public Todo getTodoHTML() {
        Todo todo = TodoDao.instance.getModel().get(id);
        if(todo==null)
          throw new RuntimeException("Get: Todo with " + id +  " not found");
        return todo;
      }
      @PUT
      @Consumes(MediaType.APPLICATION_XML)
      public Response putTodo(JAXBElement<Todo> todo) {
        Todo c = todo.getValue();
        return putAndGetResponse(c);
      }

      @DELETE
      public void deleteTodo() {
        Todo c = TodoDao.instance.getModel().remove(id);
        if(c==null)
          throw new RuntimeException("Delete: Todo with " + id +  " not found");
      }

      private Response putAndGetResponse(Todo todo) {
            Response res;
            if(TodoDao.instance.getModel().containsKey(todo.getId())) {
              res = Response.noContent().build();
            } else {
              res = Response.created(uriInfo.getAbsolutePath()).build();
            }
            TodoDao.instance.getModel().put(todo.getId(), todo);
            return res;
          }

}

【问题讨论】:

    标签: java rest jersey-2.0 jaxb2


    【解决方案1】:

    问题 1:

    当查找到的 Todo 为空时,您会收到服务器错误,因为您正在抛出 RuntimException。它始终为空,因为您使用不存在的 id 34 查找它。您可以看到您在 URL 中使用 id 的所有请求都是失败的请求。

    你可能想抛出一些更合适的东西,它会被映射到一个响应,比如NotFoundException,它会被映射到一个 404 响应

    问题 2:

    Response response = target.path("rest").path("todos").path(todo.getId())
                              .request()
                              .accept(MediaType.APPLICATION_FORM_URLENCODED)
                              .post(Form.class,form)
    

    让我们分解一下问题所在。

    1. .path(todo.getId())。从外观上看,您正在尝试向newTodo 发帖。该方法没有模板和 id。彻底摆脱它。
    2. .accept(MediaType.APPLICATION_FORM_URLENCODED)。请求将被重定向到 HTML 页面,因此响应不会是 application/x-www-form-urlencoded。所以你可以完全摆脱它。在这种情况下,您不需要显式设置标头。
    3. .post(Form.class,form)。看看different post methods

      • Response post(Entity&lt;?&gt; entity)
      • &lt;T&gt; T post(Entity&lt;?&gt; entity, Class&lt;T&gt; responseType)
      • &lt;T&gt; T post(Entity&lt;?&gt; entity, GenericType&lt;T&gt; responseType)

      您希望收到Response,因此您将使用第一个。它只需要一个Entity。如果您查看一些 API 方法,您会看到一个静态的form(Form) 方法。

      创建一个“application/x-www-form-urlencoded”表单实体。

      这就是你要使用的Entity.form(form)

    所以你的完整请求可能看起来像

    Form form = new Form();
    form.param("id", "45");
    form.param("summary", "Summary for id 45");
    Response response = client.target(url).request().post(Entity.form(form));
    String html = response.readEntity(String.class);
    System.out.println(html);
    

    【讨论】:

    • 非常感谢您的回答,对于第 1 期,我添加了 TodoDao 代码。关于您的“旁白”,您能否给我一个关于“您应该做的事情是通过 id 查找 Todo,并将其作为响应发回”的意思。
    • 我没有看到TodoResource。我以为子资源定位器正在调用TodosResource
    • 查看更新的第一部分。这是因为您使用的 id 不存在,并且您显式地抛出了一个 RuntimeException,没有 ExceptionMapper 来处理它。所以异常冒泡到容器级别,发出 500
    • 在路径中使用 id 1(替换 34),它应该可以工作。我已经测试过了,它工作正常
    • 好的,500(TodosResourceClient.java) 用于:` Response response = target.path("rest").path("todos").path(todo.getId()).request () .accept(MediaType.APPLICATION_XML).get(Response.class);` .这是构造函数调用Todo todo = new Todo("34","Summary Entred"); 不插入kv("34","Summary Entred")
    【解决方案2】:

    问题 1 的修复:正如 @peeskillet 所建议的,使用 MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON 的新 POST 方法已被编码。此代码已在 TodosResource.java 服务中更新:

    @POST
      @Produces(MediaType.TEXT_HTML)
      @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
    
      public void newTodoXMLJSON(Todo todo) throws IOException {
        this.todo=todo;
        TodoDao.instance.getModel().put(todo.getId(), todo);
      }   
    

    newTodoXMLJSON() 方法的调用来自TodosResourceClient.java,它已使用这些额外的代码行进行了更新:

    Todo todo = new Todo("34","34 - Summary Entered");
    target.path("rest").path("todos").request().post(Entity.json(todo));
    Response response = target.path("rest").path("todos").path(todo.getId()).request()
                    .accept(MediaType.APPLICATION_XML).get(Response.class);     
    System.out.println("\n Response Code is : "+ response.getStatus());
    

    问题 2 的修复:如 @peeskilet 建议的那样

    Form form = new Form();
    form.param("id","45");
    form.param("summary","Summary for id 45");
    response =target.path("rest").path("todos").request().post(Entity.form(form));    
    System.out.println("\nPost response"+ response.getStatus());
    

    【讨论】:

      猜你喜欢
      • 2013-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多