Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Java] Basic bean-validation of @NotNull, @Size, @Pattern, @Min, @Max #2549 #3280

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,33 @@ and specify the `classname` when running the generator:

Your subclass will now be loaded and overrides the `PREFIX` value in the superclass.

### Java Bean Validation support

Java Bean Validation annotations are supported:

Annotation | Swagger-API | Description
---------- | ----------- | -----------
@DecimalMax (max for BigDecimal) | maxLength | not yet supported, see #2549
@DecimalMin (min for BigDecimal) | minLength | not yet supported, see #2549
@Max | maximum | The value of the field or property must be an integer value lower than or equal to the number in the value element.
@Min | minimum | The value of the field or property must be an integer value greater than or equal to the number in the value element.
@NotNull | required=true | The value of the field or property must not be null.
@Pattern | pattern | The value of the field or property must match the regular expression defined in the regexp element.
@Size | minLength/maxLength | The size of the field or property is evaluated and must match the specified boundaries.

See http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html for the full list of annotations.

The following annotations currently don't have an equivalent in the Swagger-API spec:
* @AssertFalse
* @AssertTrue
* @Digits
* @Future
* @Null
* @Past

Languages with Bean Validation support: Java, JAX-RS CXF


### Bringing your own models

Sometimes you don't want a model generated. In this case, you can simply specify an import mapping to tell
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
package io.swagger.codegen.plugin;

import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyAdditionalPropertiesKvp;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyImportMappingsKvp;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyInstantiationTypesKvp;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsv;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyTypeMappingsKvp;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

/*
* Copyright 2001-2005 The Apache Software Foundation.
*
Expand All @@ -19,25 +37,9 @@
import io.swagger.codegen.CliOption;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.config.CodegenConfigurator;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static io.swagger.codegen.config.CodegenConfiguratorUtils.*;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;

/**
* Goal which generates client/server code from a swagger json/yaml definition.
Expand Down Expand Up @@ -288,7 +290,8 @@ public void execute() throws MojoExecutionException {
}

if (addCompileSourceRoot) {
project.addCompileSourceRoot(output.toString());
String sourceJavaFolder = output.toString() + "/" + configOptions.get(CodegenConstants.SOURCE_FOLDER);
project.addCompileSourceRoot(sourceJavaFolder);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,33 @@
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Operation;

/**
* TODO #2017:
* - reuse bean-validation-annotations in Java?
* - pom.xml: maybe add cxf-version property
* - api_test.mustache: add switch for using gzip in test cases?
*
*
*
*/
public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaCXFServerCodegen()
{
{
public JavaCXFServerCodegen()
{
super();

supportsInheritance = true;

artifactId = "swagger-cxf-server";

sourceFolder = "gen" + File.separator + "java";
outputFolder = "generated-code/JavaJaxRS-CXF";
apiTestTemplateFiles.clear(); // TODO: add test template


apiTemplateFiles.put("apiServiceImpl.mustache", ".java");

// clear model and api doc template as this codegen
// does not support auto-generated markdown doc at the moment
//TODO: add doc templates
Expand All @@ -34,14 +49,34 @@ public JavaCXFServerCodegen()

embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "cxf";

}
}


@Override
public String getName()
{
return "jaxrs-cxf";
}
@Override
public void processOpts()
{
super.processOpts();

supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen

writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));

writeOptional(outputFolder, new SupportingFile("readme.md", "", "readme.md"));

writeOptional(outputFolder, new SupportingFile("web.mustache",
("src/main/webapp/WEB-INF"), "web.xml"));
writeOptional(outputFolder, new SupportingFile("context.xml.mustache",
("src/main/webapp/WEB-INF"), "context.xml"));
writeOptional(outputFolder, new SupportingFile("jboss-web.xml.mustache",
("src/main/webapp/WEB-INF"), "jboss-web.xml"));

}

@Override
public String getName()
{
return "jaxrs-cxf";
}

@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
import java.io.File;
import java.util.*;

/**
* TODO #2549:
* - add switch for bean-validation-annotations?
*
*
*
*/
public class JavaClientCodegen extends AbstractJavaCodegen {
@SuppressWarnings("hiding")
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
Expand Down Expand Up @@ -164,7 +171,7 @@ public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
operation.returnType = "Void";
}
if (usesRetrofit2Library() && StringUtils.isNotEmpty(operation.path) && operation.path.startsWith("/"))
operation.path = operation.path.substring(1);
operation.path = operation.path.substring(1);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.util.Objects;
{{#imports}}
import {{import}};
{{/imports}}
import javax.validation.constraints.*;

{{#serializableModel}}import java.io.Serializable;{{/serializableModel}}
{{#models}}
Expand Down
33 changes: 30 additions & 3 deletions modules/swagger-codegen/src/main/resources/Java/pojo.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,37 @@ public class {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} {{#seriali
{{/maximum}}
* @return {{name}}
**/
{{#vendorExtensions.extraAnnotation}}
{{vendorExtensions.extraAnnotation}}
{{/vendorExtensions.extraAnnotation}}
{{#required}}
@NotNull
{{/required}}
{{#pattern}}
@Pattern(regexp="{{pattern}}")
{{/pattern}}
{{#minLength}}
{{#maxLength}}
@Size(min={{minLength}},max={{maxLength}})
{{/maxLength}}
{{/minLength}}
{{#minLength}}
{{^maxLength}}
@Size(min={{minLength}})
{{/maxLength}}
{{/minLength}}
{{^minLength}}
{{#maxLength}}
@Size(max={{maxLength}})
{{/maxLength}}
{{/minLength}}
{{#minimum}}
//@Min({{minimum}})
{{/minimum}}
{{#maximum}}
//@Max({{maximum}})
{{/maximum}}
@ApiModelProperty({{#example}}example = "{{example}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}")
{{#vendorExtensions.extraAnnotation}}
{{vendorExtensions.extraAnnotation}}
{{/vendorExtensions.extraAnnotation}}
public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}
Expand Down
8 changes: 8 additions & 0 deletions modules/swagger-codegen/src/main/resources/Java/pom.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@
<artifactId>migbase64</artifactId>
<version>2.2</version>
</dependency>

<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>

<!-- test dependencies -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@ import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.multipart.*;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Path("/")
@Api(value = "/", description = "{{description}}")
public interface {{classname}} {
{{#operations}}
{{#operation}}
@{{httpMethod}}
{{#subresourceOperation}}@Path("{{path}}"){{/subresourceOperation}}
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
{{#hasProduces}}@Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}});
{{#summary}}
@ApiOperation(value = "{{summary}}")
{{/summary}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}});
{{/operation}}
}
{{/operations}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package {{package}}.impl;

import {{package}}.*;
{{#imports}}import {{import}};
{{/imports}}

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import org.apache.cxf.jaxrs.model.wadl.Description;
import org.apache.cxf.jaxrs.model.wadl.DocTarget;

import org.apache.cxf.jaxrs.ext.multipart.*;

import io.swagger.annotations.Api;

@Path("/")
{{#description}}
@Api(value = "/", description = "{{description}}")
{{/description}}
public class {{classname}}ServiceImpl implements {{classname}} {
{{#operations}}
{{#operation}}
@{{httpMethod}}
{{#subresourceOperation}}@Path("{{path}}"){{/subresourceOperation}}
{{#hasConsumes}}@Consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
{{#hasProduces}}@Produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
{{! add description for CXF WADL (must be added to implementation class }}
{{#summary}}
@Description(value = "{{summary}}", target = DocTarget.METHOD)
{{/summary}}
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}} {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}) {
// TODO: Implement...

{{#returnType}}return null;{{/returnType}}
}

{{/operation}}
}
{{/operations}}

Loading