Skip to content

Commit

Permalink
#20 : Resource methods should support javax.ws.rs.core.Form
Browse files Browse the repository at this point in the history
  • Loading branch information
Gmugra committed Feb 28, 2021
1 parent 1e68d05 commit cfe2cdb
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ The type of the annotated parameter must either:
1. `javax.ws.rs.core.UriBuilder`
1. `javax.ws.rs.core.Link.Builder`
1. `javax.ws.rs.core.Variant.VariantListBuilder`
1. `javax.ws.rs.core.Form`

### Extensions

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package net.cactusthorn.routing.invoke;

import static net.cactusthorn.routing.util.Messages.Key.WRONG_CONTENT_TYPE;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;

import net.cactusthorn.routing.RoutingInitializationException;
import net.cactusthorn.routing.uri.PathTemplate.PathValues;
import net.cactusthorn.routing.util.Messages;

public class FormParameter extends MethodParameter {

// @formatter:off
private static final Set<MediaType> CONTENT_TYPE = Collections
.unmodifiableSet(new HashSet<>(Arrays.asList(
new MediaType[] {MediaType.APPLICATION_FORM_URLENCODED_TYPE, MediaType.MULTIPART_FORM_DATA_TYPE})));
// @formatter:off

public FormParameter(Method method, Parameter parameter, Type genericType, int position, Set<MediaType> consumesMediaTypes) {
super(method, parameter, genericType, position);

for (MediaType contentType : consumesMediaTypes) {
if (!CONTENT_TYPE.contains(contentType)) {
throw new RoutingInitializationException(
Messages.msg(WRONG_CONTENT_TYPE, "javax.ws.rs.core.Form", CONTENT_TYPE, method()));
}
}
}

@Override //
protected Form findValue(HttpServletRequest req, HttpServletResponse res, ServletContext con, PathValues pathValues)
throws Exception {

MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
for (Enumeration<String> e = req.getParameterNames(); e.hasMoreElements();) {
String name = e.nextElement();
String[] values = req.getParameterValues(name);
parameters.addAll(name, values);
}
return new Form(parameters);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javax.ws.rs.PUT;
import javax.ws.rs.PATCH;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.HttpHeaders;

import net.cactusthorn.routing.RoutingConfig;
Expand Down Expand Up @@ -87,6 +88,9 @@ static MethodParameter create(Method method, Parameter parameter, Type genericTy
}
if (method.getAnnotation(POST.class) != null || method.getAnnotation(PUT.class) != null
|| method.getAnnotation(PATCH.class) != null) {
if (Form.class == parameter.getType()) {
return new FormParameter(method, parameter, genericType, position, consumesMediaTypes);
}
return new BodyReaderParameter(method, parameter, genericType, position, consumesMediaTypes, routingConfig.bodyReaders());
}
throw new RoutingInitializationException(Messages.msg(ONLY_POST_PUT_PATCH, method));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package net.cactusthorn.routing.invoke;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

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

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import net.cactusthorn.routing.ComponentProvider;
import net.cactusthorn.routing.RoutingConfig;
import net.cactusthorn.routing.RoutingInitializationException;

public class FormParameterTest extends InvokeTestAncestor {

public static class EntryPoint1 {

@POST public void wrongConsumes(Form form) {
}

@POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) //
public void form(Form form) {
}
}

public static class EntryPoint1Provider implements ComponentProvider {
@Override //
public Object provide(Class<?> clazz, HttpServletRequest request) {
return new EntryPoint1();
}
}

private static final RoutingConfig CONFIG = RoutingConfig.builder(new EntryPoint1Provider()).addResource(EntryPoint1.class).build();

@Test public void wrongContentType() {
assertThrows(RoutingInitializationException.class, () -> parameterInfo(EntryPoint1.class, "wrongConsumes", CONFIG));
}

@Test public void form() throws Exception {
MethodParameter mp = parameterInfo(EntryPoint1.class, "form", CONFIG);

Map<String, String[]> parameters = new HashMap<>();
parameters.put("aaaa", new String[] { "super value" });

Mockito.when(request.getParameterNames()).thenReturn(Collections.enumeration(parameters.keySet()));
Mockito.when(request.getParameterValues("aaaa")).thenReturn(parameters.get("aaaa"));

Form f = (Form) mp.findValue(request, null, null, null);
assertEquals("super value", f.asMap().getFirst("aaaa"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ private static ServletContextHandler createRoutingServlet() {
.addBodyReader(new SimpleGsonBodyReader<>())
.addBodyWriter(new SimpleThymeleafBodyWriter("/thymeleaf/"))
.addParamConverterProvider(new LocalDateParamConverterProvider())
.addExceptionMapper(new UnsupportedOperationExceptionMapper())
.setParametersValidator(new SimpleParametersValidator())
.build();
// @formatter:on
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.cactusthorn.routing.demo.jetty;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

public class UnsupportedOperationExceptionMapper implements ExceptionMapper<UnsupportedOperationException> {

@Override public Response toResponse(UnsupportedOperationException exception) {
return Response.status(Response.Status.SERVICE_UNAVAILABLE).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
Expand Down Expand Up @@ -45,11 +47,15 @@ public Response showUpload() {
return Response.ok(templated).type(MediaType.TEXT_HTML_TYPE).build();
}


@POST @Path("doupload") @Consumes("multipart/form-data") //
public String upload(@FormParam("fname") String fname, @FormPart("myfile") Part part, @FormPart("myfile2") Part part2)
throws IOException {
// @formatter:off
public String upload(
Form form,
@FormPart("myfile") Part part,
@FormPart("myfile2") Part part2) throws IOException {

String result = fname + " :: ";
String result = form.asMap().getFirst("fname") + " :: ";

java.nio.file.Path tmpDir = Files.createTempDirectory("");
String fileName = part.getSubmittedFileName();
Expand All @@ -68,15 +74,17 @@ public String upload(@FormParam("fname") String fname, @FormPart("myfile") Part

return result;
}
// @formatter:on

// @formatter:off
@POST @Path("form") @Consumes("application/x-www-form-urlencoded") //
public String doHtml(
@FormParam("fname") String fname,
@FormParam("lname") String lname,
@FormParam("box") List<Integer> box,
@CookieParam("JSESSIONID") String jsession) {
return fname + " :: " + lname + " :: " + box + " :: " + jsession;
@CookieParam("JSESSIONID") String jsession,
Form form) {
MultivaluedMap<String, String> map = form.asMap();
return fname + " :: " + map.getFirst("lname") + " :: " + map.get("box") + " :: " + jsession;
}
// @formatter:on
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ public void wrongRole() {
public String headers(@Context HttpHeaders headers) {
return headers.getHeaderString(HttpHeaders.USER_AGENT);
}

@GET @Path("/exceptionmapper") //
public String exceptionmapper() {
throw new UnsupportedOperationException();
}
}
4 changes: 2 additions & 2 deletions demo-jetty/src/main/resources/thymeleaf/fileupload.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<html xmlns:th="http://www.thymeleaf.org">

<head>
<title>Micro :: Test</title>
<title>net.cactusthorn.routing :: Demo :: Files uploading</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8">
</head>
Expand All @@ -18,7 +18,7 @@

<label for="myFile">File:</label>
<input type="file" id="myFile" name="myfile"/><br/><br/>

<label for="myFile2">File2:</label>
<input type="file" id="myFile2" name="myfile2"/><br/><br/>

Expand Down
2 changes: 1 addition & 1 deletion demo-jetty/src/main/resources/thymeleaf/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<html xmlns:th="http://www.thymeleaf.org">

<head>
<title>Micro :: Test</title>
<title>net.cactusthorn.routing :: Demo :: Simple HTML</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8">
</head>
Expand Down
4 changes: 3 additions & 1 deletion demo-jetty/src/main/resources/thymeleaf/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<html xmlns:th="http://www.thymeleaf.org">

<head>
<title>Micro :: Test</title>
<title>net.cactusthorn.routing :: Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8">
</head>
Expand Down Expand Up @@ -42,6 +42,8 @@
<a th:href="@{/wrongrole}">@UserRoles -> Forbidden</a><br/><br/>

<a th:href="@{/headers}">HttpHeaders</a><br/><br/>

<a th:href="@{/exceptionmapper}">ExceptionMapper (HTTP 503)</a><br/><br/>
</body>

</html>

0 comments on commit cfe2cdb

Please sign in to comment.