使用Fetch API通过React应用程序调用Servlet-导致无法加载资源错误(406-不可接受)

时间:2018-12-09 06:51:37

标签: java reactjs servlets jersey fetch-api

我对React JS和Java servlet非常陌生。我已经使用Jersey在React中创建了一个视图,并在servlet中创建了一个API端点。前端和后端都在本地计算机上的Tomcat服务器上运行。 Servlet尝试访问在http://localhost:37070/expenseClaimService/start运行的服务以发布新的声明。该服务经过单独测试,并返回创建的新声明的id

现在,我正在尝试使用React应用中的Fetch在servlet中调用端点。但是我在React应用程序中不断收到Failed to load resource: the server responded with a status of 406

error

React应用中的提取调用

  handleAddClaim = () => {
    console.log("in method");
    fetch("http://localhost:8080/eca/api/claims/new-claim", {
      method: "POST",
      headers: {
        Accept: "text/plain",
        "Content-Type": "application/json",
        "Access-Control_Allow-Orign": "*"
      },
      body: JSON.stringify({
        empName: "Test Vendor4",
        empFirstname: "Test",
        empLastname: "Vendor4",
        empEmail: "test4@mail.com",
        empId: "test3",
        empJobTitle: "SE",
        date: "08 December, 2018",
        refNo: "testRef999",
        memo: "OPD test claim 11",
        claims: [
          {
            amount: "9500.00",
            memo: "Test claim - Medicine",
            billDate: "4 December, 2018"
          }
        ]
      })
    })
    .then(response => {
        console.log(response);
    })
    .catch(error => {
        console.error(error);
    });
  };

Servlet中的端点

@Path("/claims")
public class OPDClaimEndpoint {

    @POST
    @Path("/new-claim")
    @Produces(MediaType.TEXT_HTML)
    @Consumes(MediaType.APPLICATION_JSON)
    public String addNewClaim(JsonObject body){            
        return ExecutionUtils.generatePostRequest(body.toString());
    }
}

生成帖子请求(使用Apache HttpClient)

public static String generatePostRequest(String input){
    String url = "http://localhost:37070/expenseClaimService/start";

    try {
        StringEntity requestEntity = new StringEntity(
                input,
                ContentType.APPLICATION_JSON);

        HttpPost request = new HttpPost(url);
        request.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
        request.setEntity(requestEntity);
        HttpClient client = HttpClientBuilder.create().build();
        HttpResponse response = client.execute(request);
        return response.toString();
    }
    catch ( IOException e) {
        logger.info(e.getMessage());
    }
    return "Failed";
}

web.xml

<servlet>
    <servlet-name>eca-api</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.org.eca.client.api.endpoint</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>eca-api</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

如何解决此问题,以便可以从React应用程序调用服务? 非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

看看您的fetch调用和Servlet端点,您的@Produces批注指定servlet将产生“ text / html”,而Fetch调用则指定它仅接受“ text / plain”类型(“ “标题)。

尝试更改其中至少一项(取决于您的需要)以相互匹配,问题应该得到解决。

答案 1 :(得分:1)

您需要发送JSON 类型,因此将ACCEPT替换为CONTENT_TYPE

request.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);

使用:

request.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
  

HTTP Content-Type标头字段名称。

答案 2 :(得分:0)

终于找到了解决方案!

在tomcat日志文件中,可以看到Jersey不支持Gson的JsonObject。

enter image description here

正如this答案所表明的那样,Jersey仅支持本机类型,并且String作为其方法中的输入。因此,我更改了端点方法签名以接受字符串public String addNewClaim(String body),现在它甚至适用于笨重的Json字符串。 (请注意,这是在Jersey 1.19中,在Jersey 2.x中可能有所不同)。但是,它可以像本answer中所述接受Java对象。