Description
Hey all, I love your work.
I've upgraded from 2.3.1 and have found that my custom mustache files are no longer found when running swagger-codegen. I have dug in a bit and have found that the templateDir variable is overwritten after being properly set from my gradle task. What's worse, is that I successfully was able to override a method on JavaClientCodegen to set templateDir properly again, and when it came time for processing the template the template was not found for some mysterious reason.
Swagger-codegen version
3.0.0-rc0
Relevant code
I ended up cloning the repositories and building locally to be able to run with the latest code since I was having the issue on 3.0.0-rc0 and found This issue over on the swagger-codegen-generators GitHub project that made it seem possible it was already resolved on the SNAPSHOT.
Gradle buildSrc:
apply plugin: 'java'
repositories {
mavenLocal()
jcenter()
}
dependencies {
compile group: 'io.swagger', name: 'swagger-codegen-cli', version: '3.0.0-SNAPSHOT'
// compile group: 'io.swagger', name: 'swagger-codegen-generators', version: '1.0.0-SNAPSHOT'
// I tried both of the above
}
build.gradle:
import io.swagger.codegen.config.CodegenConfigurator
import io.swagger.codegen.DefaultGenerator
apply plugin: 'java'
apply plugin: 'maven'
buildscript {
repositories {
mavenLocal()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath('io.swagger:swagger-codegen:3.0.0-SNAPSHOT')
}
}
def swaggerInput = "src/main/resources/swaggerdoc.json"
def swaggerOutputDir = file('build/swagger')
task ('swagger') {
inputs.file(swaggerInput)
outputs.dir(swaggerOutputDir)
doLast {
def config = new CodegenConfigurator()
config.setInputSpec(swaggerInput)
config.setOutputDir(swaggerOutputDir.path)
config.setLang('com.job.qa.automation.lib.codegen.MyJavaCodegen')
config.setTemplateDir('src/main/resources/templates')
config.setAdditionalProperties([
'invokerPackage' : 'com.job.api.util',
'modelPackage' : 'com.job.api.dto',
'apiPackage' : 'com.job.api.controllers',
'dateLibrary' : 'java8',
])
new DefaultGenerator().opts(config.toClientOptInput()).generate()
}
}
MyJavaCodegen. I should note that I've already successfully used a custom codegen class such as this, but stripped it down to just focus on this template problem:
package com.job.qa.automation.lib.codegen;
import io.swagger.codegen.languages.java.JavaClientCodegen;
public class MyJavaCodegen extends JavaClientCodegen {
public MyJavaCodegen() {
super();
}
@Override
public void processOpts() {
super.processOpts();
templateDir = "src/main/resources/templates";
modelTemplateFiles.remove("model.mustache");
modelTemplateFiles.put("myDto.mustache", ".java");
}
}
Relevant JavaClientCodegen code. The templateVersion code was added not too far back, but even before it was added we still had the situation where the templateDir set in the super.processOpts() call is always overwritten just after when also setting embeddedTemplateDir:
@Override
public void processOpts() {
super.processOpts();
String templateVersion = getTemplateVersion();
if (StringUtils.isNotBlank(templateVersion)) {
embeddedTemplateDir = templateDir = String.format("%s/Java", templateVersion);
} else {
embeddedTemplateDir = templateDir = String.format("%s/Java", DEFAULT_TEMPLATE_VERSION);
}
But again, this is only half of the problem, even with MyJavaCodegen salvaging the templateDir value, we run into a problem again.
Caused by: java.io.FileNotFoundException: /src/main/resources/templates/myDto.mustache
at com.github.jknack.handlebars.io.URLTemplateLoader.sourceAt(URLTemplateLoader.java:70)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:357)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:343)
at io.swagger.codegen.DefaultGenerator.getHandlebars(DefaultGenerator.java:1019)
at io.swagger.codegen.DefaultGenerator.processTemplateToFile(DefaultGenerator.java:742)
at io.swagger.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:394)
... 82 more
Okay, it looks like we should change
templateDir = "src/main/resources/templates";
to
templateDir = new File("src/main/resources/templates").getAbsolutePath();
This yields:
Caused by: java.io.FileNotFoundException: //Users/admin/checkout/project/src/main/resources/templates/myDto.mustache
at com.github.jknack.handlebars.io.URLTemplateLoader.sourceAt(URLTemplateLoader.java:70)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:357)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:343)
at io.swagger.codegen.DefaultGenerator.getHandlebars(DefaultGenerator.java:1019)
at io.swagger.codegen.DefaultGenerator.processTemplateToFile(DefaultGenerator.java:742)
at io.swagger.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:394)
... 82 more
That path starts //Users... interesting. I debugged the program and set a breakpoint to change the path to not include the double forward slash, but it still failed with the same exception.
What happens if I don't try to use my custom mustache files, but still try to set the templateDir? Well, if I leave the modelTemplateFiles HashMap alone in MyJavaCodegen I get the following exception:
Caused by: java.io.FileNotFoundException: /src/main/resources/templates/v2/Java/model.mustache
at com.github.jknack.handlebars.io.URLTemplateLoader.sourceAt(URLTemplateLoader.java:70)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:357)
at com.github.jknack.handlebars.Handlebars.compile(Handlebars.java:343)
at io.swagger.codegen.DefaultGenerator.getHandlebars(DefaultGenerator.java:1019)
at io.swagger.codegen.DefaultGenerator.processTemplateToFile(DefaultGenerator.java:742)
at io.swagger.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:394)
I wasn't able to make any sense of the the problem within sourceAt(URLTemplateLoader.java:70).
Its source is the following:
@Override
public TemplateSource sourceAt(final String uri) throws IOException {
notEmpty(uri, "The uri is required.");
String location = resolve(normalize(uri));
URL resource = getResource(location);
if (resource == null) {
throw new FileNotFoundException(location);
}
return new URLTemplateSource(location, resource);
}
And we are failing at getResource(location which is the following:
@Override
protected URL getResource(final String location) {
return getClass().getResource(location);
}
I tried other location strings for files elsewhere on my filesystem, and in the top level of my resources directory, such as simply "swaggerdoc.json", but everything failed the same way, returning null.
Steps to reproduce
./gradlew swagger after the setup I've described above.
Related issues/PRs
Similar issue that happened July 2017
#4627
Suggest a fix/enhancement
Part of the solution is likely to remove the setting of templateDir from JavaClientCodegen#processOpts. If there is for some reason a need for templateDir to either not be null or to be a valid directory, we can take care of that in the getter in DefaultCodegenConfig, just like embeddedTemplateDir is as follows:
public String embeddedTemplateDir() {
if (embeddedTemplateDir != null) {
return embeddedTemplateDir;
} else {
return templateDir;
}
}
templateDir could be as follows:
public String templateDir() {
if (templateDir != null) {
return templateDir;
} else {
return embeddedTemplateDir;
}
}
Or this can be taken care of in JavaClientCodegen#processOpts by making the beginning of the method the following:
@Override
public void processOpts() {
super.processOpts();
String templateVersion = getTemplateVersion();
if (StringUtils.isNotBlank(templateVersion)) {
embeddedTemplateDir = String.format("%s/Java", templateVersion);
} else {
embeddedTemplateDir = String.format("%s/Java", DEFAULT_TEMPLATE_VERSION);
}
if (templateDir == null || !new File(templateDir).exists()) {
templateDir = embeddedTemplateDir;
}
Description
Hey all, I love your work.
I've upgraded from 2.3.1 and have found that my custom mustache files are no longer found when running swagger-codegen. I have dug in a bit and have found that the
templateDirvariable is overwritten after being properly set from my gradle task. What's worse, is that I successfully was able to override a method onJavaClientCodegento settemplateDirproperly again, and when it came time for processing the template the template was not found for some mysterious reason.Swagger-codegen version
3.0.0-rc0
Relevant code
I ended up cloning the repositories and building locally to be able to run with the latest code since I was having the issue on 3.0.0-rc0 and found This issue over on the swagger-codegen-generators GitHub project that made it seem possible it was already resolved on the SNAPSHOT.
Gradle buildSrc:
build.gradle:
MyJavaCodegen. I should note that I've already successfully used a custom codegen class such as this, but stripped it down to just focus on this template problem:
Relevant JavaClientCodegen code. The
templateVersioncode was added not too far back, but even before it was added we still had the situation where thetemplateDirset in thesuper.processOpts()call is always overwritten just after when also settingembeddedTemplateDir:But again, this is only half of the problem, even with MyJavaCodegen salvaging the
templateDirvalue, we run into a problem again.Okay, it looks like we should change
to
This yields:
That path starts
//Users... interesting. I debugged the program and set a breakpoint to change the path to not include the double forward slash, but it still failed with the same exception.What happens if I don't try to use my custom mustache files, but still try to set the
templateDir? Well, if I leave themodelTemplateFilesHashMap alone inMyJavaCodegenI get the following exception:I wasn't able to make any sense of the the problem within
sourceAt(URLTemplateLoader.java:70).Its source is the following:
And we are failing at
getResource(locationwhich is the following:I tried other
locationstrings for files elsewhere on my filesystem, and in the top level of myresourcesdirectory, such as simply"swaggerdoc.json", but everything failed the same way, returningnull.Steps to reproduce
./gradlew swaggerafter the setup I've described above.Related issues/PRs
Similar issue that happened July 2017
#4627
Suggest a fix/enhancement
Part of the solution is likely to remove the setting of
templateDirfromJavaClientCodegen#processOpts. If there is for some reason a need fortemplateDirto either not be null or to be a valid directory, we can take care of that in the getter inDefaultCodegenConfig, just likeembeddedTemplateDiris as follows:templateDircould be as follows:Or this can be taken care of in
JavaClientCodegen#processOptsby making the beginning of the method the following: