Getting started with MVC(5)
Handle PUT and DELETE request
When you try to submit aPUTorDELETEhttp request via form submission, and you want to invoke the methods annotated with@PUTor@DELETEin the Controller to handle the request.
Unfortunately it does not work.
There is a simple solution which can help us to overcome this issue.
If you have used Spring MVC before and I think you could know there is aHiddenMethodFilterin the Spirng MVC to fix this issue. Java EE 8 MVC does not ship the similar Filter, we can create one.
Solution Create a Filter to convert the request method to the target HTTP method. Add a hidden field named_methodin the form, which value is the target HTTP method. The@PUTmethod in theTaskController.
Source codes Clone the codes from my github.com account. https://github.com/hantsy/ee8-sandbox/ Open the mvc project in NetBeans IDE. Run it on Glassfish. After it is deployed and runging on Glassfish application server, navigate http://localhost:8080/ee8-mvc/mvc/tasks in browser.
When you try to submit aPUTorDELETEhttp request via form submission, and you want to invoke the methods annotated with@PUTor@DELETEin the Controller to handle the request.
Unfortunately it does not work.
There is a simple solution which can help us to overcome this issue.
If you have used Spring MVC before and I think you could know there is aHiddenMethodFilterin the Spirng MVC to fix this issue. Java EE 8 MVC does not ship the similar Filter, we can create one.
Solution
@WebFilter(filterName = "HiddenHttpMethodFilter", urlPatterns = {"/*"}, dispatcherTypes = {DispatcherType.REQUEST})
public class HiddenHttpMethodFilter implements Filter {
@Inject
Logger log;
/**
* Default method parameter: {@code _method}
*/
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* Set the parameter name to look for HTTP methods.
*
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
this.methodParam = methodParam;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws ServletException, IOException {
log.log(Level.INFO, "entering HttpHiddenFilter...");
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String paramValue = request.getParameter(this.methodParam);
log.log(Level.INFO, "paramValue @" + paramValue);
log.log(Level.INFO, "request method @" + request.getMethod());
if ("POST".equals(request.getMethod()) && paramValue != null && paramValue.trim().length() > 0) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
filterChain.doFilter(wrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied
* method for {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
}
<form action="${markDoingUrl}" method="post">
<input type="hidden" name="_method" value="PUT"><jsp:text /></input>
<input type="hidden" name="status" value="DOING"><jsp:text /></input>
<button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-play" aria-hidden="true"><jsp:text /></span>
START
</button>
</form>
@PUT
@Path("{id}/status")
public Response updateStatus(@PathParam(value = "id") Long id, @NotNull @FormParam(value = "status") String status) {
log.log(Level.INFO, "updating status of the existed task@id:{0}, status:{1}", new Object[]{id, status});
Task task = taskRepository.findById(id);
task.setStatus(Task.Status.valueOf(status));
taskRepository.update(task);
flashMessage.notify(Type.info, "Task status was updated successfully!");
return Response.ok("redirect:tasks").build();
}
Source codes