Search code examples
javaeclipserestjersey

Form data to rest PUT method in java


I am beginner for Java and REST API. I have a problem passing form data from HTML to rest PUT method. When I google about this, most solutions available are for POST method, that recommended to use FormParam. In my case, it shows below error:

The method received in the request-line is known by the origin server but not supported by the target resource.

Even I use PathParam, same error is returned:

The method received in the request-line is known by the origin server but not supported by the target resource.

And some solution for Spring Boot. But I did not use that.

PUT method:

@PUT
@Path("/update")
@Produces(MediaType.TEXT_HTML)
public String updCard(@PathParam("cardNo") String cardNo,  
        @PathParam("reportId") int reportId
        ) throws SQLException { 

    Card c = new Card(cardNo, reportId); 

    System.out.println(cardNo + reportId);
    
    return "";
}

Form:

 <form method="PUT" action="rest/card/update">
  <label for = "cardNo">Card No: </label> <input type="text" name = "cardNo" id = "cardNo"><br/>
  <label for = "reportId">Report Id:</label> <input type="text" name = "reportId" id = "reportId"> <br/>
  <button type="submit">Update</button>  

So, how do I get the form data in PUT method in Jersey?


Solution

  • As mentioned by many in Using PUT method in HTML form, PUT is not currently supported by the HTML standard. What most frameworks will do is offer a workaround. Jersey has such a workaround with its HttpMethodOverrideFilter. What you must do is use a POST method and add a _method=put query parameter and the filter will switch the POST to a PUT.

    You first need to register the filter. If you are using a ResourceConfig just do

    @ApplicationPath("api")
    public class JerseyConfig extends ResourceConfig {
    
        public JerseyConfig() {
            ...
            register(HttpMethodOverrideFilter.class);
        }
    }
    

    If you are using a web.xml, then do

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.server.filter.HttpMethodOverrideFilter</param-value>
    </init-param>
    

    Then in your HTML, you will just add the _method=put query param to the URL. Below is an example I used to test

    <form method="post" action="/api/form?_method=put">
        <label>
            Name:
            <input type="text" name="name"/>
        </label>
        <label>
            Age:
            <input type="number" name="age"/>
        </label>
        <br/>
        <input type="submit" value="Submit"/>
    </form>
    

    And in your resource method you will use @PUT and @FormParams for the paramters

    @PUT
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response form(@FormParam("name") String name,
                         @FormParam("age") String age,
                         @Context UriInfo uriInfo) {
    
        URI redirectUri = UriBuilder
                .fromUri(getBaseUriWithoutApiRoot(uriInfo))
                .path("redirect.html")
                .queryParam("name", name)
                .queryParam("age", age)
                .build();
        return Response.temporaryRedirect(redirectUri).build();
    }
    
    private static URI getBaseUriWithoutApiRoot(UriInfo uriInfo) {
        String baseUri = uriInfo.getBaseUri().toASCIIString();
        baseUri = baseUri.endsWith("/")
                ? baseUri.substring(0, baseUri.length() - 1)
                : baseUri;
        return URI.create(baseUri.substring(0, baseUri.lastIndexOf("/")));
    }
    

    It should work from what I tested