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

Reserved word causes Java codegen to fail #305

Closed
hshorter opened this issue Oct 9, 2014 · 34 comments
Closed

Reserved word causes Java codegen to fail #305

hshorter opened this issue Oct 9, 2014 · 34 comments
Milestone

Comments

@hshorter
Copy link

hshorter commented Oct 9, 2014

JSON below causes the Java CodeGen to fail with the following exception because of the use of 'switch':

java.lang.Exception: reserved word "switch" not allowed at com.wordnik.swagger.codegen.BasicJavaGenerator.escapeReservedWord(BasicJavaGenerator.scala:240) at com.wordnik.swagger.codegen.language.CodegenConfig.toVarName(CodegenConfig.scala:116) at com.wordnik.swagger.codegen.BasicJavaGenerator.toVarName(BasicJavaGenerator.scala:112) at com.wordnik.swagger.codegen.Codegen$$anonfun$apiToMap$2.apply(Codegen.scala:166) at com.wordnik.swagger.codegen.Codegen$$anonfun$apiToMap$2.apply(Codegen.scala:115) at com.wordnik.swagger.codegen.Codegen.apiToMap(Codegen.scala:115) at com.wordnik.swagger.codegen.BasicGenerator$$anonfun$prepareApiBundle$2$$anonfun$apply$16.apply(BasicGenerator.scala:345) at com.wordnik.swagger.codegen.BasicGenerator$$anonfun$prepareApiBundle$2$$anonfun$apply$16.apply(BasicGenerator.scala:344) at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:772) at scala.collection.immutable.List.foreach(List.scala:318)

{

    "apis": [
        {
            "description": "",
            "operations": [
                {
                    "consumes": [ ],
                    "items": { },
                    "method": "GET",
                    "nickname": "GET",
                    "parameters": [
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "domain",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "svlan",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        }
                    ],
                    "produces": [
                        "application/json",
                        "application/x-json-smile",
                        "application/xml",
                        "text/xml",
                        "application/x-yaml",
                        "text/x-yaml",
                        "text/csv",
                        "application/*+xml",
                        "application/xml",
                        "text/xml"
                    ],
                    "responseMessages": [ ],
                    "summary": "",
                    "type": "ErpsAuditResult"
                }
            ],
            "path": "/Erps/{domain}/{svlan}/Audit"
        },
        {
            "description": "",
            "operations": [
                {
                    "consumes": [ ],
                    "items": { },
                    "method": "GET",
                    "nickname": "GET",
                    "parameters": [
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "domain",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "svlan",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "address",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "switch",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        }
                    ],
                    "produces": [
                        "application/json",
                        "application/x-json-smile",
                        "application/xml",
                        "text/xml",
                        "application/x-yaml",
                        "text/x-yaml",
                        "text/csv",
                        "application/*+xml",
                        "application/xml",
                        "text/xml"
                    ],
                    "responseMessages": [ ],
                    "summary": "",
                    "type": "ErpsRepairVlanList"
                },
                {
                    "consumes": [
                        "application/json",
                        "application/x-json-smile",
                        "application/xml",
                        "text/xml",
                        "application/x-yaml",
                        "text/x-yaml",
                        "text/csv",
                        "*/*"
                    ],
                    "items": { },
                    "method": "PUT",
                    "nickname": "PUT",
                    "parameters": [
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "domain",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "svlan",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "address",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "description": "",
                            "name": "switch",
                            "paramType": "path",
                            "required": true,
                            "type": "string"
                        },
                        {
                            "allowMultiple": false,
                            "name": "parameter1",
                            "paramType": "body",
                            "required": true,
                            "type": "string"
                        }
                    ],
                    "produces": [ ],
                    "responseMessages": [ ],
                    "summary": "",
                    "type": "void"
                }
            ],
            "path": "/Erps/{domain}/{svlan}/Repair/{address}/{switch}"
        }
    ],
    "apiVersion": "1.0",
    "basePath": "url",
    "consumes": [ ],
    "info": { },
    "models": {
        "ErpsAuditResult": {
            "description": "",
            "id": "ErpsAuditResult",
            "properties": {
                "svlan": {
                    "type": "int",
                    "uniqueItems": false
                },
                "warnings": {
                    "items": {
                        "$ref": "ErpsAuditWarning"
                    },
                    "type": "array",
                    "uniqueItems": false
                },
                "managementDomainName": {
                    "type": "string",
                    "uniqueItems": false
                }
            },
            "required": [ ],
            "subTypes": [ ]
        },
        "ErpsAuditWarning": {
            "description": "",
            "id": "ErpsAuditWarning",
            "properties": {
                "warning": {
                    "type": "string",
                    "uniqueItems": false
                }
            },
            "required": [ ],
            "subTypes": [ ]
        },
        "ErpsRepairVlanList": {
            "description": "",
            "id": "ErpsRepairVlanList",
            "properties": {
                "switchIndex": {
                    "type": "int",
                    "uniqueItems": false
                },
                "svlan": {
                    "type": "int",
                    "uniqueItems": false
                },
                "address": {
                    "type": "string",
                    "uniqueItems": false
                },
                "vlans": {
                    "items": {
                        "type": "int"
                    },
                    "type": "array",
                    "uniqueItems": false
                },
                "managementDomainName": {
                    "type": "string",
                    "uniqueItems": false
                }
            },
            "required": [ ],
            "subTypes": [ ]
        }
    },
    "produces": [ ],
    "resourcePath": "/Erps",
    "swaggerVersion": "1.2"

}
@fehguy
Copy link
Contributor

fehguy commented Oct 9, 2014

this is by design--it is possible to change the templates to support reserved words. However, that will be addressed in the develop_2.0 branch of swagger-codegen.

@fehguy fehguy modified the milestone: v2.0.18 Dec 24, 2014
@frodrigo
Copy link
Contributor

frodrigo commented Apr 1, 2015

We are at v2.1.2 and the problem is still here. Need change the target ?
I encountered it with void, it's not just a reserved keyword but also a special meaning as return value.

@fehguy
Copy link
Contributor

fehguy commented Apr 2, 2015

Please try 2.1.3-SNAPSHOT. I believe it has been addressed there.

@frodrigo
Copy link
Contributor

frodrigo commented Apr 2, 2015

I try with last code from develop_2.0 branch

@wing328
Copy link
Contributor

wing328 commented Apr 2, 2015

Do you mind showing us what the auto-generated code looks like ?

@frodrigo
Copy link
Contributor

frodrigo commented Apr 2, 2015

No generetad code.

$ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i http://127.0.0.1:3000/api/swagger_doc.json -l java -o dir

[...]
java.lang.RuntimeException: void (reserved word) cannot be used as a model name
at com.wordnik.swagger.codegen.languages.JavaClientCodegen.toModelName(JavaClientCodegen.java:120)
at com.wordnik.swagger.codegen.languages.JavaClientCodegen.getSwaggerType(JavaClientCodegen.java:161)
at com.wordnik.swagger.codegen.DefaultCodegen.fromProperty(DefaultCodegen.java:534)
at com.wordnik.swagger.codegen.DefaultCodegen.fromResponse(DefaultCodegen.java:845)
at com.wordnik.swagger.codegen.DefaultCodegen.fromOperation(DefaultCodegen.java:709)
at com.wordnik.swagger.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:305)
at com.wordnik.swagger.codegen.DefaultGenerator.processPaths(DefaultGenerator.java:277)
at com.wordnik.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:152)
at com.wordnik.swagger.codegen.cmd.Generate.run(Generate.java:77)
at com.wordnik.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:33)

According to swagger spec (1.2) void is a valid return data type.

@wing328
Copy link
Contributor

wing328 commented Apr 2, 2015

Agreed void is valid return type in swagger spec 1.2.

My guess is that there may be an issue converting the spec from 1.2 to 2.0 when generating the client

I would suggest you to try generating the client in Ruby or Python to see if there's a model named "Void". If yes, that means likely the conversion from 1.2 to 2.0 treats "void" as an object, not a data type indicating void return.

@frodrigo
Copy link
Contributor

frodrigo commented Apr 2, 2015

Ruby is not the right place to look at, since there is no return type nor return.

In Python void is treated as type, but not no void entity are created.
responseObject = self.apiClient.deserialize(response, 'void')
return responseObject

In C#, same ugly thing:
return (void) ApiInvoker.deserialize(response, typeof(void));

@wing328
Copy link
Contributor

wing328 commented Apr 3, 2015

CSharp petstore sample (using swagger spec 2.0) does not have the "void"
issue you found:

https://github.com/swagger-api/swagger-codegen/blob/master/samples/client/petstore/csharp/src/Com/Wordnik/Petstore/Api/PetApi.cs#L137

so my guess is that the issue has to do with conversion from swagger spec
1.2 to 2.0.

On Fri, Apr 3, 2015 at 12:14 AM, Frédéric Rodrigo notifications@github.com
wrote:

Ruby is not the right place to look at, since there is no return type nor
return.

In Python void is treated as type, but not no void entity are created.
responseObject = self.apiClient.deserialize(response, 'void')
return responseObject

In C#, same ugly thing:
return (void) ApiInvoker.deserialize(response, typeof(void));


Reply to this email directly or view it on GitHub
#305 (comment)
.

@xhh
Copy link
Contributor

xhh commented Apr 3, 2015

Regarding the issue of treating "void" as model name, the following is what I guess where the problem is:

https://github.com/swagger-api/swagger-parser/blob/master/modules/swagger-compat-spec-parser/src/main/java/io/swagger/parser/SwaggerCompatConverter.java#L365

// default response type
Property responseProperty = propertyFromTypedObject(operation);
if(responseProperty != null) {
  Response response = new Response()
    .description("success")
    .schema(responseProperty); // <===== here
  if(output.getResponses() == null)
    output.defaultResponse(response);
  else
    output.response(200, response);
}

https://github.com/swagger-api/swagger-parser/blob/master/modules/swagger-compat-spec-parser/src/main/java/io/swagger/parser/SwaggerCompatConverter.java#L322

if(obj.getRef() != null)
  output = new RefProperty(obj.getRef());
else if(type != null) // <===== type is "void" here
  output = new RefProperty(type);
else
  output = new RefProperty("void");

@xhh
Copy link
Contributor

xhh commented Apr 3, 2015

I've made it work via this PR: swagger-api/swagger-parser#34, please have a look.

@frodrigo
Copy link
Contributor

frodrigo commented Apr 3, 2015

I have updated, rebuild all, (the dependency is now 1.0.5-SNAPSHOT), but the problem is still the same:
java.lang.RuntimeException: void (reserved word) cannot be used as a model name

@xhh
Copy link
Contributor

xhh commented Apr 4, 2015

the 1.0.5-SNAPSHOT version of swagger-parser does has the issue, it needs to publish a new version for swagger-parser and use that new version in swagger-codegen project

@fehguy
Copy link
Contributor

fehguy commented Apr 4, 2015

Hi, I've just pushed an updated 1.0.5-SNAPSHOT. Please try again, and apologies for the delay.

@frodrigo
Copy link
Contributor

frodrigo commented Apr 4, 2015

It's now OK for me. Thank you.

@wing328
Copy link
Contributor

wing328 commented Apr 23, 2015

@frodrigo do you mind closing this issue given that it's resolved ?

@webron
Copy link
Contributor

webron commented Apr 24, 2015

Looks like @frodrigo confirmed already. Closing.

@webron webron closed this as completed Apr 24, 2015
@frodrigo
Copy link
Contributor

The reserved keyword "void" is now OK. But the others still cause exceptions as reported when this issue was opened.

@webron
Copy link
Contributor

webron commented Apr 26, 2015

Without a list it would be difficult to do much about it.

@frodrigo
Copy link
Contributor

@wing328
Copy link
Contributor

wing328 commented Apr 27, 2015

@frodrigo If I understand it correctly, you would like to use Java reserved keyword (e.g. return) as the model name. Do you mind telling us a bit more about the use case? Can the model be renamed as something else (e.g. ReturnObject) ?

Currently, in Java codegen, we check whether the model name is a reserved keyword and throw an exception if found. If we skip the check, Java codegen can generate the code but it won't compile since Java would complain about using "return" as the class name.

@frodrigo
Copy link
Contributor

It's not my issue initially. Have personally no more problem since void is OK. Just point you, you may not close this issue just because "void" is now OK.

@MarcinKwiatkowski1988
Copy link

Can you please add also a fix for the return type "Byte" --> java.lang.RuntimeException: byte (reserved word) cannot be used as a model name

@wing328
Copy link
Contributor

wing328 commented Jun 22, 2015

@MarcinKwiatkowski1988 Do you mind sharing the spec with us ?

A model named "Byte" won't compile in Java

@MarcinKwiatkowski1988
Copy link

{"apiVersion":"1.0.0","swaggerVersion":"1.2","basePath":"/pluto/api-docs","resourcePath":"/retrieveperson","apis":[{"path":"/retrieve/{id}","operations":[{"method":"GET","summary":"The API allows to retrieve a person's data","notes":"More notes about this method (rest2 two)","type":"Person","nickname":"retrievePerson","produces":["application/json","application/xml"],"authorizations":{},"parameters":[{"name":"id","description":"ID of Person to fetch","required":true,"type":"string","paramType":"path"}]}]}],"models":{"Person":{"id":"Person","description":"Person resource representation","properties":{"byteField":{"type":"array","description":"ByteField","items":{"type":"byte"}},"name":{"type":"string","description":"Name"},"surname":{"type":"string","description":"Surname"},"phoneNumbers":{"type":"array","description":"List of phone numbers","items":{"$ref":"PhoneNumber"}},"numbers":{"type":"array","items":{"$ref":"PhoneNumber"}}}},"PhoneNumber":{"id":"PhoneNumber","description":"PhoneNumber resource representation","properties":{"prefix":{"type":"string","description":"Country prefix"},"number":{"type":"string","description":"Phone number"}}}}}

@wing328
Copy link
Contributor

wing328 commented Jun 22, 2015

@MarcinKwiatkowski1988 may I know how you obtain the swagger spec file ?

"type":"byte" is not valid according to https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md#431-primitives

@MarcinKwiatkowski1988
Copy link

I obtained it using swagger's annotations - for the Byte part, using this piece of code:

@apimodel(value = "Person", description = "Person resource representation")
public class Person {
@ApiModelProperty(value = "ByteField", dataType = "java.lang.Byte[]")
private Byte[] byteField;
//...

The whole projects works very well, I just need the codegen to works with reserved word "Byte" to create the client for java

@wing328
Copy link
Contributor

wing328 commented Jun 23, 2015

In your case you want to use Byte[] (array of byte) for a property but I'm afraid that's not supported by the spec at the moment. Please refer to OAI/OpenAPI-Specification#50 for more information

@MarcinKwiatkowski1988
Copy link

So I just need to wait till it will be supported, or I have to figure out how to change my project to not use Byte[] ?

@wing328
Copy link
Contributor

wing328 commented Jun 23, 2015

For byte[], is that actually a file ?

@MarcinKwiatkowski1988
Copy link

I have a java file (Person.java) that has a property of this type: Byte[]; what I'm supposed to do to make it work with codegen, to have a working client generated by swagger-codegen, instead of having the error of "reserved word"?

@wing328
Copy link
Contributor

wing328 commented Jun 23, 2015

What about skipping that property for the time being ? and you manually add it back after the code is generated (and clearly this is not the best solution)

@MarcinKwiatkowski1988
Copy link

That's not an option, since the real project has multiple files with that kind of property; the spec I showed was from a small-simple sample.

@wing328
Copy link
Contributor

wing328 commented Jun 23, 2015

What about a temporary workaround to comment out the line that's throwing the exception so that you will still get the code generated (then you can remove the custom model "Byte" to avoid compile error)

A permanent solution is to wait for the OAI/OpenAPI-Specification#50 to be resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants