From 2469d296d4a22710addb9402541aa3ae6475a4b3 Mon Sep 17 00:00:00 2001 From: wwhitlow Date: Tue, 20 Feb 2018 23:18:21 -0500 Subject: [PATCH] Negated a potential NPE that was caused be HTTP methods that had a similar structure to accessor methods. --- java2typescript-jackson/pom.xml | 5 +++ .../jackson/module/Configuration.java | 24 ++++++++++++ .../visitors/TSJsonObjectFormatVisitor.java | 35 +++++++++++++++++- .../jaxrs/ServiceDescriptorGenerator.java | 15 +++++++- .../jaxrs/DescriptorGeneratorTest.java | 37 +++++++++++++++++-- 5 files changed, 110 insertions(+), 6 deletions(-) diff --git a/java2typescript-jackson/pom.xml b/java2typescript-jackson/pom.xml index 8b3f9e8..5251b15 100644 --- a/java2typescript-jackson/pom.xml +++ b/java2typescript-jackson/pom.xml @@ -43,6 +43,11 @@ jackson-annotations ${jackson.core.version} + + javax.ws.rs + jsr311-api + 1.1.1 + com.fasterxml.jackson.core jackson-core diff --git a/java2typescript-jackson/src/main/java/java2typescript/jackson/module/Configuration.java b/java2typescript-jackson/src/main/java/java2typescript/jackson/module/Configuration.java index ff91c26..9c13e73 100644 --- a/java2typescript-jackson/src/main/java/java2typescript/jackson/module/Configuration.java +++ b/java2typescript-jackson/src/main/java/java2typescript/jackson/module/Configuration.java @@ -13,10 +13,16 @@ import java2typescript.jackson.module.grammar.ArrayType; import java2typescript.jackson.module.grammar.base.AbstractType; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; + public class Configuration { private Map customTypes = Collections.emptyMap(); private List ignoredMethodNames = new ArrayList(); private TSTypeNamingStrategy namingStrategy = new SimpleJacksonTSTypeNamingStrategy(); + private boolean jaxrsRun = false; public Map getCustomTypes() { return customTypes; @@ -61,4 +67,22 @@ public TSTypeNamingStrategy getNamingStrategy() { public void setNamingStrategy(TSTypeNamingStrategy namingStrategy) { this.namingStrategy = namingStrategy; } + + public boolean getJaxrsRun() { + return jaxrsRun; + } + + public void setJaxrsRun(boolean bool) { + jaxrsRun = bool; + } + + public boolean methodHasHTTPAnnotation(Method method) { + if (method.getAnnotation(GET.class) != null || + method.getAnnotation(POST.class) != null || + method.getAnnotation(PUT.class) != null || + method.getAnnotation(DELETE.class) != null) { + return true; + } + return false; + } } diff --git a/java2typescript-jackson/src/main/java/java2typescript/jackson/module/visitors/TSJsonObjectFormatVisitor.java b/java2typescript-jackson/src/main/java/java2typescript/jackson/module/visitors/TSJsonObjectFormatVisitor.java index f149407..04b5ba9 100644 --- a/java2typescript-jackson/src/main/java/java2typescript/jackson/module/visitors/TSJsonObjectFormatVisitor.java +++ b/java2typescript-jackson/src/main/java/java2typescript/jackson/module/visitors/TSJsonObjectFormatVisitor.java @@ -24,6 +24,10 @@ import java.beans.PropertyDescriptor; import java.beans.Transient; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + import java2typescript.jackson.module.grammar.AnyType; import java2typescript.jackson.module.grammar.FunctionType; import java2typescript.jackson.module.grammar.ClassType; @@ -35,7 +39,6 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; @@ -51,6 +54,7 @@ public class TSJsonObjectFormatVisitor extends ABaseTSJsonFormatVisitor implements JsonObjectFormatVisitor { private Class clazz; + private List blackListField = new ArrayList(); public TSJsonObjectFormatVisitor(ABaseTSJsonFormatVisitor parentHolder, String className, Class clazz, Configuration conf) { super(parentHolder, conf); @@ -59,7 +63,9 @@ public TSJsonObjectFormatVisitor(ABaseTSJsonFormatVisitor parentHolder, Strin } private void addField(String name, AbstractType fieldType) { - type.getFields().put(name, fieldType); + if (!blackListField.contains(name)) { + type.getFields().put(name, fieldType); + } } private boolean isAccessorMethod(Method method, BeanInfo beanInfo) { @@ -74,6 +80,24 @@ private boolean isAccessorMethod(Method method, BeanInfo beanInfo) { return false; } + private void blackListUnnecessaryFieldMethods(Method method) { + Pattern getSearcher = Pattern.compile("^get.*"); + Pattern setSearcher = Pattern.compile("^set.*"); + + String methodName = method.getName(); + String ignoredField; + + if (getSearcher.matcher(method.getName()).matches()) { + ignoredField = methodName.replaceFirst("^get",""); + ignoredField = Introspector.decapitalize(ignoredField); + blackListField.add(ignoredField); + } else if (setSearcher.matcher(method.getName()).matches()) { + ignoredField = methodName.replaceFirst("^set",""); + ignoredField = Introspector.decapitalize(ignoredField); + blackListField.add(ignoredField); + } + } + void addPublicMethods() { for (Method method : this.clazz.getDeclaredMethods()) { @@ -83,6 +107,13 @@ void addPublicMethods() { continue; } + //Don't exclude accessors with HTTP Annotations + if (conf.getJaxrsRun() && conf.methodHasHTTPAnnotation(method)) { + addMethod(method); + blackListUnnecessaryFieldMethods(method); + continue; + } + // Exclude accessors try { BeanInfo beanInfo = Introspector.getBeanInfo(clazz); diff --git a/java2typescript-jaxrs/src/main/java/java2typescript/jaxrs/ServiceDescriptorGenerator.java b/java2typescript-jaxrs/src/main/java/java2typescript/jaxrs/ServiceDescriptorGenerator.java index e390d0a..fd0a3a2 100644 --- a/java2typescript-jaxrs/src/main/java/java2typescript/jaxrs/ServiceDescriptorGenerator.java +++ b/java2typescript-jaxrs/src/main/java/java2typescript/jaxrs/ServiceDescriptorGenerator.java @@ -31,6 +31,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; + +import java2typescript.jackson.module.Configuration; import java2typescript.jackson.module.DefinitionGenerator; import java2typescript.jackson.module.grammar.AnyType; import java2typescript.jackson.module.grammar.ClassType; @@ -85,14 +87,21 @@ public class ServiceDescriptorGenerator { private ObjectMapper mapper; + private Configuration conf; + public ServiceDescriptorGenerator(Collection> classes) { this(classes, new ObjectMapper()); } public ServiceDescriptorGenerator(Collection> classes, ObjectMapper mapper) { + this(classes,mapper, null); + } + + public ServiceDescriptorGenerator(Collection> classes, ObjectMapper mapper, Configuration conf) { this.classes = classes; this.mapper = mapper; addDummyMappingForJAXRSClasses(); + this.conf = conf; } private class DummySerializer extends JsonSerializer { @@ -153,7 +162,11 @@ public Module generateTypeScript(String moduleName) throws JsonMappingException // Generates Typescript module out of service classses definition DefinitionGenerator defGen = new DefinitionGenerator(mapper); - Module module = defGen.generateTypeScript(moduleName, classes, null); + if (conf == null) { + conf = new Configuration(); + conf.setJaxrsRun(true); + } + Module module = defGen.generateTypeScript(moduleName, classes, conf); // For each rest service, update methods with parameter names, got from Rest service descriptor for (RestService restService : generateRestServices(classes)) { diff --git a/java2typescript-jaxrs/src/test/java/java2typescript/jaxrs/DescriptorGeneratorTest.java b/java2typescript-jaxrs/src/test/java/java2typescript/jaxrs/DescriptorGeneratorTest.java index 086aceb..0cb6006 100644 --- a/java2typescript-jaxrs/src/test/java/java2typescript/jaxrs/DescriptorGeneratorTest.java +++ b/java2typescript-jaxrs/src/test/java/java2typescript/jaxrs/DescriptorGeneratorTest.java @@ -46,7 +46,7 @@ static class MyObject { } @Path("/") - static private interface ExampleService { + class ExampleService { @Path("/{id}") @POST @@ -54,7 +54,9 @@ public String aPostMethod(// @QueryParam("q1") String queryParam, // @PathParam("id") String id, // @FormParam("formParam") Integer formParam, // - String postPayload); + String postPayload){ + return "test"; + } @Path("/{id}") @GET @@ -62,7 +64,21 @@ public void aGetMethod(// @QueryParam("q1") String queryParam, // @PathParam("id") String id, // @FormParam("formParam") Integer formParam, // - MyObject postPayload); + MyObject postPayload){ + + } + + @Path("/random") + @GET + public int getRandom() { + return 4; + } + + @Path("/multi") + @GET + public int getMultiWordGetter() { + return 3; + } } @@ -92,4 +108,19 @@ public void testTypescriptGenerate() throws JsonGenerationException, JsonMapping Module tsModule = descGen.generateTypeScript("modName"); tsModule.write(out); } + + @Test + public void testTypescriptGenerateWithExample() throws JsonGenerationException, JsonMappingException, IOException { + + ServiceDescriptorGenerator descGen = new ServiceDescriptorGenerator( + Collections.singletonList(ExampleService.class)); + + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("custom-mapping"); + + mapper.registerModule(module); + + Module tsModule = descGen.generateTypeScript("modName"); + tsModule.write(out); + } }