diff --git a/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java b/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java index 72555fd..9e8f1fb 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java +++ b/src/main/java/io/sinistral/proteus/server/handlers/HandlerGenerator.java @@ -56,6 +56,7 @@ import io.sinistral.proteus.server.ServerRequest; import io.sinistral.proteus.server.ServerResponse; import io.sinistral.proteus.server.endpoints.EndpointInfo; +import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tags; @@ -282,7 +283,7 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla .addStatement("final $T router = new $T()", io.undertow.server.RoutingHandler.class, io.undertow.server.RoutingHandler.class); final Map parameterizedLiteralsNameMap = Arrays.stream(clazz.getDeclaredMethods()) - .filter(m -> m.getAnnotation(Operation.class) != null) + .filter(m -> m.getAnnotation(Operation.class) != null || m.getAnnotation(ApiOperation.class) != null) .flatMap( m -> Arrays.stream(m.getParameters()).map(Parameter::getParameterizedType) .filter(t -> t.getTypeName().contains("<") && !t.getTypeName().contains("concurrent"))) @@ -293,9 +294,11 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla return (handler.equals(TypeHandler.ModelType) || handler.equals(TypeHandler.OptionalModelType)); }).collect(Collectors.toMap(java.util.function.Function.identity(), HandlerGenerator::typeReferenceNameForParameterizedType)); + + Arrays.stream(clazz.getDeclaredMethods()) - .filter(m -> m.getAnnotation(Operation.class) != null) + .filter(m -> m.getAnnotation(Operation.class) != null || m.getAnnotation(ApiOperation.class) != null) .flatMap(m -> Arrays.stream(m.getParameters())) .forEach(p -> { @@ -318,7 +321,7 @@ protected void addClassMethodHandlers(TypeSpec.Builder typeBuilder, Class cla }); final Map literalsNameMap = Arrays.stream(clazz.getDeclaredMethods()) - .filter(m -> m.getAnnotation(Operation.class) != null) + .filter(m -> m.getAnnotation(Operation.class) != null || m.getAnnotation(ApiOperation.class) != null) .flatMap(m -> Arrays.stream(m.getParameters()) .map(Parameter::getParameterizedType)).filter(t -> { @@ -883,7 +886,7 @@ else if (producesContentType.contains(MediaType.TEXT_HTML)) * @TODO wrap blocking in BlockingHandler */ - if (Optional.ofNullable(m.getAnnotation(Operation.class)).isPresent()) + if (Optional.ofNullable(m.getAnnotation(Operation.class)).isPresent() || Optional.ofNullable(m.getAnnotation(ApiOperation.class)).isPresent()) { SecurityRequirement securityRequirementAnnotation = m.getAnnotation(SecurityRequirement.class); diff --git a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java b/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java index 5f8eb38..8996a9c 100644 --- a/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java +++ b/src/main/java/io/sinistral/proteus/server/handlers/TypeHandler.java @@ -24,6 +24,7 @@ * Enum that assists in code generation for different method parameter types */ + public enum TypeHandler { @@ -254,6 +255,10 @@ public static void addStatement(MethodSpec.Builder builder, Parameter parameter) TypeHandler handler = TypeHandler.forType(parameter.getParameterizedType(), isBeanParameter); +// if(handler.equals(TypeHandler.ModelType)) +// { +// HandlerGenerator.log.warn("found modeltype for " + parameter.getParameterizedType()); +// } addStatement(builder, parameter, handler); } diff --git a/src/main/java/io/sinistral/proteus/services/OpenAPIService.java b/src/main/java/io/sinistral/proteus/services/OpenAPIService.java index badc1ac..ad223a7 100644 --- a/src/main/java/io/sinistral/proteus/services/OpenAPIService.java +++ b/src/main/java/io/sinistral/proteus/services/OpenAPIService.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import java.util.jar.JarFile; import java.util.stream.Collectors; @@ -72,302 +73,333 @@ @Singleton public class OpenAPIService extends BaseService implements Supplier { - private static Logger log = LoggerFactory.getLogger(OpenAPIService.class.getCanonicalName()); - protected final String resourcePathPrefix = "openapi"; - protected ObjectMapper mapper = null; - protected ObjectWriter writer = null; - protected ObjectMapper yamlMapper = null; - protected Path resourcePath = null; - protected ClassLoader serviceClassLoader = null; - protected OpenAPI openApi = null; - protected String spec = null; - protected String indexHTML = null; - @Inject - @Named("openapi.resourcePrefix") - protected String resourcePrefix; - @Inject - @Named("openapi.basePath") - protected String basePath; - @Inject - @Named("openapi.specFilename") - protected String specFilename; - @Inject - @Named("openapi") - protected Config openAPIConfig; - @Inject - @Named("application.name") - protected String applicationName; - @Inject - @Named("openapi.port") - protected Integer port; - @Inject - @Named("application.path") - protected String applicationPath; - @Inject - protected RoutingHandler router; - @Inject - @Named("registeredEndpoints") - protected Set registeredEndpoints; - @Inject - @Named("registeredControllers") - protected Set> registeredControllers; - @Inject - @Named("registeredHandlerWrappers") - protected Map registeredHandlerWrappers; - - public OpenAPIService() - { - mapper = Json.mapper(); - - mapper.registerModule(new Jdk8Module()); - - yamlMapper = Yaml.mapper(); - writer = Yaml.pretty(); - } - - public void generateHTML() - { - try { - - try (InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream(resourcePrefix + "/index.html")) { - - byte[] templateBytes = IOUtils.toByteArray(templateInputStream); - String templateString = new String(templateBytes, Charset.defaultCharset()); - - templateString = templateString.replaceAll("\\{\\{ basePath \\}\\}", basePath); - templateString = templateString.replaceAll("\\{\\{ title \\}\\}", applicationName + " Swagger UI"); - this.indexHTML = templateString; - } - - URL url = this.getClass().getClassLoader().getResource(resourcePrefix); - - if (url.toExternalForm().contains("!")) - { - log.debug("Copying OpenAPI resources..."); - - String jarPathString = url.toExternalForm().substring(0, url.toExternalForm().indexOf("!")).replaceAll("file:", "").replaceAll("jar:", ""); - File srcFile = new File(jarPathString); - - try (JarFile jarFile = new JarFile(srcFile, false)) { - - String appName = config.getString("application.name").replaceAll(" ", "_"); - Path tmpDirParent = Files.createTempDirectory(appName); - Path tmpDir = tmpDirParent.resolve("openapi/"); - - if (tmpDir.toFile().exists()) - { - log.debug("Deleting existing OpenAPI directory at " + tmpDir); - - try { - FileUtils.deleteDirectory(tmpDir.toFile()); - } catch (java.lang.IllegalArgumentException e) { - - log.debug("Tmp directory is not a directory..."); - tmpDir.toFile().delete(); - } - } - - java.nio.file.Files.createDirectory(tmpDir); - - this.resourcePath = tmpDir; - - jarFile.stream().filter(ze -> ze.getName().endsWith("js") || ze.getName().endsWith("css") || ze.getName().endsWith("map") || ze.getName().endsWith("html")).forEach(ze -> { - try { - - final InputStream entryInputStream = jarFile.getInputStream(ze); - String filename = ze.getName().substring(resourcePrefix.length() + 1); - Path entryFilePath = tmpDir.resolve(filename); - - java.nio.file.Files.createDirectories(entryFilePath.getParent()); - java.nio.file.Files.copy(entryInputStream, entryFilePath, StandardCopyOption.REPLACE_EXISTING); - - } catch (Exception e) { - log.error(e.getMessage() + " for entry " + ze.getName()); - } - } ); - } - } - else - { - this.resourcePath = Paths.get(this.getClass().getClassLoader().getResource(this.resourcePrefix).toURI()); - this.serviceClassLoader = this.getClass().getClassLoader(); - } - - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } - - @SuppressWarnings("rawtypes") - public void generateSpec() throws Exception - { - Set> classes = this.registeredControllers; - - OpenAPIExtensions.setExtensions(Collections.singletonList(new ServerParameterExtension())); - - OpenAPI openApi = new OpenAPI(); - Info info = mapper.convertValue(openAPIConfig.getValue("info").unwrapped(), Info.class); - - openApi.setInfo(info); - - Map securitySchemes = mapper.convertValue(openAPIConfig.getValue("securitySchemes").unwrapped(), - new TypeReference>(){}); - - if (openApi.getComponents() == null) - { - openApi.setComponents(new Components()); - } - - openApi.getComponents().setSecuritySchemes(securitySchemes); - - List servers = mapper.convertValue(openAPIConfig.getValue("servers").unwrapped(),new TypeReference>(){}); - - openApi.setServers(servers); - - SwaggerConfiguration config = new SwaggerConfiguration().resourceClasses(classes.stream().map(c -> c.getName()).collect(Collectors.toSet())).openAPI(openApi); - - config.setModelConverterClassess(Collections.singleton(ServerModelResolver.class.getName())); - - OpenApiContext ctx = new GenericOpenApiContext().openApiConfiguration(config) - .openApiReader(new Reader(config)) - .openApiScanner(new JaxrsApplicationAndAnnotationScanner().openApiConfiguration(config)) - .init(); - - openApi = ctx.read(); - this.openApi = openApi; - this.spec = writer.writeValueAsString(openApi); - } - - - @Override - protected void shutDown() throws Exception - { - - } - - - @Override - protected void startUp() throws Exception - { - this.generateSpec(); - this.generateHTML(); - log.debug("\nOpenAPI Spec:\n" + writer.writeValueAsString(this.openApi)); - router.addAll(this.get()); - } - - public RoutingHandler get() - { - RoutingHandler router = new RoutingHandler(); - - /* - * YAML path - */ - String pathTemplate = this.applicationPath + File.separator + this.specFilename; - FileResourceManager resourceManager = new FileResourceManager(this.resourcePath.toFile(), 1024); - - router.add(HttpMethod.GET, - pathTemplate, - new HttpHandler() - { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception - { - exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, io.sinistral.proteus.server.MediaType.TEXT_YAML.contentType()); - - exchange.getResponseSender().send(spec); - } - }); - - this.registeredEndpoints.add(EndpointInfo.builder() - .withConsumes("*/*") - .withPathTemplate(pathTemplate) - .withControllerName(this.getClass().getSimpleName()) - .withMethod(Methods.GET) - .withProduces(io.sinistral.proteus.server.MediaType.TEXT_YAML.contentType()) - .build()); - - pathTemplate = this.basePath; - - router.add(HttpMethod.GET, - pathTemplate, - new HttpHandler() - { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception - { - exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, MediaType.TEXT_HTML); - exchange.getResponseSender().send(indexHTML); - } - }); - - this.registeredEndpoints.add(EndpointInfo.builder() - .withConsumes(MediaType.WILDCARD) - .withProduces(MediaType.TEXT_HTML) - .withPathTemplate(pathTemplate) - .withControllerName(this.getClass().getSimpleName()) - .withMethod(Methods.GET) - .build()); - - try { - - pathTemplate = this.basePath + "/*"; - - router.add(HttpMethod.GET, - pathTemplate, - new ResourceHandler(resourceManager) - { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception - { - String canonicalPath = CanonicalPathUtils.canonicalize((exchange.getRelativePath())); - - canonicalPath = canonicalPath.split(basePath)[1]; - - exchange.setRelativePath(canonicalPath); - - if (serviceClassLoader == null) - { - super.handleRequest(exchange); - } - else - { - canonicalPath = resourcePrefix + canonicalPath; - - try (final InputStream resourceInputStream = serviceClassLoader.getResourceAsStream(canonicalPath)) { - - if (resourceInputStream == null) - { - ResponseCodeHandler.HANDLE_404.handleRequest(exchange); - - return; - } - - byte[] resourceBytes = IOUtils.toByteArray(resourceInputStream); - - io.sinistral.proteus.server.MediaType mediaType = io.sinistral.proteus.server.MediaType.getByFileName(canonicalPath); - - exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, mediaType.toString()); - exchange.getResponseSender().send(ByteBuffer.wrap(resourceBytes)); - } - } - } - }); - - this.registeredEndpoints.add(EndpointInfo.builder() - .withConsumes(MediaType.WILDCARD) - .withProduces(MediaType.WILDCARD) - .withPathTemplate(pathTemplate) - .withControllerName(this.getClass().getSimpleName()) - .withMethod(Methods.GET) - .build()); - - } catch (Exception e) { - log.error(e.getMessage(), e); - } - - return router; - } -} + private static Logger log = LoggerFactory.getLogger(OpenAPIService.class.getCanonicalName()); + protected final String resourcePathPrefix = "openapi"; + protected ObjectMapper mapper = null; + protected ObjectWriter writer = null; + protected ObjectMapper yamlMapper = null; + protected Path resourcePath = null; + protected ClassLoader serviceClassLoader = null; + protected OpenAPI openApi = null; + protected String spec = null; + protected String indexHTML = null; + @Inject + @Named("openapi.resourcePrefix") + protected String resourcePrefix; + @Inject + @Named("openapi.basePath") + protected String basePath; + @Inject + @Named("openapi.specFilename") + protected String specFilename; + @Inject + @Named("openapi") + protected Config openAPIConfig; + @Inject + @Named("application.name") + protected String applicationName; + @Inject + @Named("openapi.port") + protected Integer port; + @Inject + @Named("application.path") + protected String applicationPath; + @Inject + protected RoutingHandler router; + @Inject + @Named("registeredEndpoints") + protected Set registeredEndpoints; + @Inject + @Named("registeredControllers") + protected Set> registeredControllers; + @Inject + @Named("registeredHandlerWrappers") + protected Map registeredHandlerWrappers; + + public OpenAPIService() + { + mapper = Json.mapper(); + + mapper.registerModule(new Jdk8Module()); + + yamlMapper = Yaml.mapper(); + writer = Yaml.pretty(); + } + + public void generateHTML() + { + try + { + + try (InputStream templateInputStream = this.getClass().getClassLoader().getResourceAsStream(resourcePrefix + "/index.html")) + { + + byte[] templateBytes = IOUtils.toByteArray(templateInputStream); + String templateString = new String(templateBytes, Charset.defaultCharset()); + + templateString = templateString.replaceAll("\\{\\{ basePath \\}\\}", basePath); + templateString = templateString.replaceAll("\\{\\{ title \\}\\}", applicationName + " Swagger UI"); + this.indexHTML = templateString; + } + + URL url = this.getClass().getClassLoader().getResource(resourcePrefix); + + if (url.toExternalForm().contains("!")) + { + log.debug("Copying OpenAPI resources..."); + + String jarPathString = url.toExternalForm().substring(0, url.toExternalForm().indexOf("!")).replaceAll("file:", "").replaceAll("jar:", ""); + File srcFile = new File(jarPathString); + + try (JarFile jarFile = new JarFile(srcFile, false)) + { + + String appName = config.getString("application.name").replaceAll(" ", "_"); + Path tmpDirParent = Files.createTempDirectory(appName); + Path tmpDir = tmpDirParent.resolve("openapi/"); + + if (tmpDir.toFile().exists()) + { + log.debug("Deleting existing OpenAPI directory at " + tmpDir); + + try + { + FileUtils.deleteDirectory(tmpDir.toFile()); + } catch (java.lang.IllegalArgumentException e) + { + + log.debug("Tmp directory is not a directory..."); + tmpDir.toFile().delete(); + } + } + + java.nio.file.Files.createDirectory(tmpDir); + + this.resourcePath = tmpDir; + + jarFile.stream().filter(ze -> ze.getName().endsWith("js") || ze.getName().endsWith("css") || ze.getName().endsWith("map") || ze.getName().endsWith("html")) + .forEach(ze -> + { + try + { + + final InputStream entryInputStream = jarFile.getInputStream(ze); + String filename = ze.getName().substring(resourcePrefix.length() + 1); + Path entryFilePath = tmpDir.resolve(filename); + + java.nio.file.Files.createDirectories(entryFilePath.getParent()); + java.nio.file.Files.copy(entryInputStream, entryFilePath, StandardCopyOption.REPLACE_EXISTING); + + } catch (Exception e) + { + log.error(e.getMessage() + " for entry " + ze.getName()); + } + }); + } + } + else + { + this.resourcePath = Paths.get(this.getClass().getClassLoader().getResource(this.resourcePrefix).toURI()); + + this.serviceClassLoader = this.getClass().getClassLoader(); + } + + } catch (Exception e) + { + log.error(e.getMessage(), e); + } + } + + @SuppressWarnings("rawtypes") + public void generateSpec() throws Exception + { + Set> classes = this.registeredControllers; + + OpenAPIExtensions.setExtensions(Collections.singletonList(new ServerParameterExtension())); + + OpenAPI openApi = new OpenAPI(); + Info info = mapper.convertValue(openAPIConfig.getValue("info").unwrapped(), Info.class); + + openApi.setInfo(info); + + Map securitySchemes = mapper.convertValue( openAPIConfig.getValue("securitySchemes").unwrapped(), + new TypeReference>() + { + }); + + if (openApi.getComponents() == null) + { + openApi.setComponents(new Components()); + } + openApi.getComponents().setSecuritySchemes(securitySchemes); + List servers = mapper.convertValue(openAPIConfig.getValue("servers").unwrapped(), new TypeReference>() + { + }); + + openApi.setServers(servers); + SwaggerConfiguration config = new SwaggerConfiguration().resourceClasses(classes.stream().map(c -> c.getName()).collect(Collectors.toSet())).openAPI(openApi); + + config.setModelConverterClassess(Collections.singleton(ServerModelResolver.class.getName())); + + OpenApiContext ctx = new GenericOpenApiContext().openApiConfiguration(config) + .openApiReader(new Reader(config)) + .openApiScanner(new JaxrsApplicationAndAnnotationScanner().openApiConfiguration(config)) + .init(); + + openApi = ctx.read(); + this.openApi = openApi; + this.spec = writer.writeValueAsString(openApi); + } + + @Override + protected void shutDown() throws Exception + { + + } + + @Override + protected void startUp() throws Exception + { + + generateHTML(); + + CompletableFuture.runAsync(() -> + { + + try + { + + generateSpec(); + + log.debug("\nOpenAPI Spec:\n" + writer.writeValueAsString(this.openApi)); + + } catch (Exception e) + { + log.error("Error generating OpenAPI spec", e); + } + + }); + + router.addAll(this.get()); + } + + public RoutingHandler get() + { + RoutingHandler router = new RoutingHandler(); + + /* + * YAML path + */ + String pathTemplate = this.applicationPath + File.separator + this.specFilename; + + FileResourceManager resourceManager = new FileResourceManager(this.resourcePath.toFile(), 1024); + + router.add( HttpMethod.GET, + pathTemplate, + new HttpHandler() + { + @Override + public void handleRequest(HttpServerExchange exchange) throws Exception + { + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, io.sinistral.proteus.server.MediaType.TEXT_YAML.contentType()); + + exchange.getResponseSender().send(spec); + } + }); + + this.registeredEndpoints.add(EndpointInfo.builder() + .withConsumes("*/*") + .withPathTemplate(pathTemplate) + .withControllerName(this.getClass().getSimpleName()) + .withMethod(Methods.GET) + .withProduces(io.sinistral.proteus.server.MediaType.TEXT_YAML.contentType()) + .build()); + + pathTemplate = this.basePath; + + router.add( HttpMethod.GET, + pathTemplate, + new HttpHandler() + { + @Override + public void handleRequest(HttpServerExchange exchange) throws Exception + { + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, MediaType.TEXT_HTML); + exchange.getResponseSender().send(indexHTML); + } + }); + + this.registeredEndpoints.add(EndpointInfo.builder() + .withConsumes(MediaType.WILDCARD) + .withProduces(MediaType.TEXT_HTML) + .withPathTemplate(pathTemplate) + .withControllerName(this.getClass().getSimpleName()) + .withMethod(Methods.GET) + .build()); + + try + { + + pathTemplate = this.basePath + "/*"; + + router.add( HttpMethod.GET, + pathTemplate, + new ResourceHandler(resourceManager) + { + @Override + public void handleRequest(HttpServerExchange exchange) throws Exception + { + String canonicalPath = CanonicalPathUtils.canonicalize((exchange.getRelativePath())); + + canonicalPath = canonicalPath.split(basePath)[1]; + + exchange.setRelativePath(canonicalPath); + + if (serviceClassLoader == null) + { + super.handleRequest(exchange); + } + else + { + canonicalPath = resourcePrefix + canonicalPath; + + try (final InputStream resourceInputStream = serviceClassLoader.getResourceAsStream(canonicalPath)) + { + + if (resourceInputStream == null) + { + ResponseCodeHandler.HANDLE_404.handleRequest(exchange); + + return; + } + + byte[] resourceBytes = IOUtils.toByteArray(resourceInputStream); + + io.sinistral.proteus.server.MediaType mediaType = io.sinistral.proteus.server.MediaType.getByFileName(canonicalPath); + + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, mediaType.toString()); + exchange.getResponseSender().send(ByteBuffer.wrap(resourceBytes)); + } + } + } + }); + + this.registeredEndpoints.add(EndpointInfo.builder() + .withConsumes(MediaType.WILDCARD) + .withProduces(MediaType.WILDCARD) + .withPathTemplate(pathTemplate) + .withControllerName(this.getClass().getSimpleName()) + .withMethod(Methods.GET) + .build()); + + } catch (Exception e) + { + log.error(e.getMessage(), e); + } + + return router; + } +} diff --git a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java index 593735d..bd50c25 100644 --- a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java +++ b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java @@ -246,6 +246,28 @@ public ServerResponse> genericSet( ServerRequest request, @QueryParam } + @POST + @Path("/generic/set/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + @Operation(description = "Generic bean set endpoint" ) + public ServerResponse> genericBeanSet( ServerRequest request, @BeanParam Set ids ) throws Exception + { + return response( ids ).applicationJson(); + } + + + @POST + @Path("/generic/list/bean") + @Produces((MediaType.APPLICATION_JSON)) + @Consumes(MediaType.APPLICATION_JSON) + + @Operation(description = "Generic bean list endpoint" ) + public ServerResponse> genericBeanList( ServerRequest request, @BeanParam List ids ) throws Exception + { + return response( ids ).applicationJson(); + } + @GET @Path("/optional/set") @Produces((MediaType.APPLICATION_JSON)) diff --git a/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java b/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java index 730e4d0..72c4b59 100644 --- a/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java +++ b/src/test/java/io/sinistral/proteus/test/server/DefaultServer.java @@ -86,7 +86,7 @@ private static void runInternal(final RunNotifier notifier) try { - Thread.sleep(2000); + Thread.sleep(5000); System.out.println(app.getPorts()); @@ -96,7 +96,7 @@ private static void runInternal(final RunNotifier notifier) } catch (Exception e) { - log.error(e.getMessage(),e); + e.printStackTrace(); } diff --git a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java b/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java index cb31e42..d3723f2 100644 --- a/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java +++ b/src/test/java/io/sinistral/proteus/test/server/TestControllerEndpoints.java @@ -16,6 +16,7 @@ import java.nio.file.Files; import java.sql.Timestamp; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -33,6 +34,8 @@ import org.junit.Test; import org.junit.runner.RunWith; +import com.fasterxml.jackson.databind.ObjectMapper; + import io.restassured.http.ContentType; import io.sinistral.proteus.test.models.User; import io.sinistral.proteus.test.models.User.UserType; @@ -112,6 +115,80 @@ public void genericSet() given().accept(ContentType.JSON).when().queryParam("ids", idSet).get("tests/generic/set").then().statusCode(200).body(containsString("1")); } + @Test + public void genericBeanSet() + { + Set randomLongs = new HashSet<>(); + + Random random = new Random(); + + Long firstNumber = null; + + for(int i = 0; i < 10; i++) + { + Long v = random.nextLong(); + + randomLongs.add(v); + + if(firstNumber == null) + { + firstNumber = v; + } + } + + ObjectMapper mapper = new ObjectMapper(); + + try + { + + + String body = mapper.writeValueAsString(randomLongs); + + given().contentType(ContentType.JSON).accept(ContentType.JSON).body(body).post("tests/generic/set/bean").then().statusCode(200).body(containsString(firstNumber.toString())); + + } catch (Exception e) + { + e.printStackTrace(); + } + } + + @Test + public void genericBeanList() + { + List randomLongs = new ArrayList<>(); + + Random random = new Random(); + + Long firstNumber = null; + + for(int i = 0; i < 10; i++) + { + Long v = random.nextLong(); + + randomLongs.add(v); + + if(firstNumber == null) + { + firstNumber = v; + } + } + + ObjectMapper mapper = new ObjectMapper(); + + try + { + + + String body = mapper.writeValueAsString(randomLongs); + + given().contentType(ContentType.JSON).accept(ContentType.JSON).body(body).post("tests/generic/list/bean").then().statusCode(200).body(containsString(firstNumber.toString())); + + } catch (Exception e) + { + e.printStackTrace(); + } + } + @Test public void optionalGenericSet() {