mulesoft-labs / raml-for-jax-rs

This project is all about two way transformation of JAX-RS-annotated Java code to RAML API description and back.
Other
295 stars 181 forks source link

Issue with the generated POJO's #76

Closed rajkumar1979 closed 9 years ago

rajkumar1979 commented 9 years ago

are you following any standard for generating the POJO's from json schema,

My Json schema has a complex object of type

"paymentDetails":{

            "type": "object",
            "description": "Representation for the address associated with the customers payment.",
            "properties": {
                "type": {
                    "type": "string",
                    "description": "The method of payment."
                },
                "attribute": {
                    "type": "array",
                    "description": "Array of name/value pairs that correspond to the attributes required for the method of payment provided.",
                    "items": [
                        {
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string",
                                    "description": "Attribute name for a payment detail element."
                                },
                                "value": {
                                    "type": "string",
                                    "description": "Attribute value for a payment detail element."
                                }
                            },
                            "required": [
                                "name",
                                "value"
                            ]
                        }
                    ]
                },
                "paymentAddress": {
                    "type": "object",
                    "properties": {
                        "addressLine1": {
                            "type": "string",
                            "description": "First address line associated with the payment address"
                        },
                        "addressLine2": {
                            "type": "string",
                            "description": "Optional second address line"
                        },
                        "addressLine3": {
                            "type": "string",
                            "description": "Optional third address line"
                        },
                        "addressLine4": {
                            "type": "string",
                            "description": "Optional fourth address line"
                        },
                        "city": {
                            "type": "string",
                            "description": "Civic location"
                        },
                        "stateOrProvince": {
                            "type": "string",
                            "description": "State or province identifier. In the United States and Canada, this corresponds to a 2 letter code. Optional as not all countries have a sub-national region"
                        },
                        "postalCode": {
                            "type": "string",
                            "description": "Postal code or zip code. "
                        },
                        "country": {
                            "type": "string",
                            "description": "2 character ISO 3166-1 code for country"
                        }
                    },
                    "required": [
                        "addressLine1",
                        "city"
                    ]
                }
            }
        }

When I test the generated POJO's by passing a sample request, it allows an object that does not adhere to this schema.

In the past when we generated objects using JAXB, when we pass an object that does not adhere to an xml schema , jersey considers that as a invalid request, but in this case the request is allowed to pass through.

Example the malformed request that was used is, I had changed the request to use an element called attr which is not there in the schema , but jersey does not validate that.

{ "accountDetails": { "accountID": "123145631722297", "accountClassification": "SmallBusiness", "accountSubClassification": "Regular", "personaID": "123145631723942", "authID": "123145631723942" }, "offerID": "20000000", "paymentDetails": { "type": "CreditCard", "attr": [ { "name": "nameOnCard", "value": "John" }, { "name": "cardNumber", "value": "9919930747642032" }, { "name": "expirationMonth", "value": "11" }, { "name": "expirationYear", "value": "2015" }, { "name": "cvn", "value": "123" } ], "paymentAddress": { "addressLine1": "123 main str", "addressLine2": "APT 122", "addressLine3": "Near Macdonald", "addressLine4": "OPP Gas station", "city": "San Diego", "stateOrProvince": "CA", "postalCode": "92122", "country": "US" } } }

ddossot commented 9 years ago

There are two issues.

First, you are allowing extra properties to be added to your object because you miss the following property:

"additionalProperties": false

Add it to your 3 object schemas (ie. paymentDetails, the one under items and paymentAddress.

Second, you use a "required" array instead of a "required" boolean for each property. This has just been added to JsonSchema2Pojo but the RAML->JAX-RS codegen plug-in hasn't been upgraded to 0.4.11 yet.

To fix this issue you can either switch to the draft-3 style of required properties or upgrade JsonSchema2Pojo to 0.4.11 and build and use your own version of the codegen plugin.

@petrochenko-pavel-a Please upgrade JsonSchema2Pojo to 0.4.11 :wink:

rajkumar1979 commented 9 years ago

Thanks for the feedback on additionalProperties.

How do I upgrade JsonSchema2Pojo ? I am just using the maven plugin to generate the Pojos in maven project.

Could you please share the details.

petrochenko-pavel-a commented 9 years ago

Done, snapshot builds are now using 0.4.11

rajkumar1979 commented 9 years ago

I am using version 1.3.3 because I think we had issues on the one checked in the repository which I believe is the snapshot version.

Could you tell me where can I get the most stable build and what's the version?

ddossot commented 9 years ago

@rajkumar1979 Version 1.3.3 is the current stable release. See: http://search.maven.org/#search|ga|1|a%3A%22raml-jaxrs-maven-plugin%22

rajkumar1979 commented 9 years ago

Sorry ,

Its a little confusing.

I am using the version 1.3.3 to generated the raml to jaxrs classes, I thought you fixed 1.3.3 by upgrading to the latest JsonSchematoPojo, I thought you mentioned that you fixed it in the snapshot release,Could you please tell me the snapshot version of the plugin that I can use to generate these artifacts.

petrochenko-pavel-a commented 9 years ago

Generally you need to use 1.3.4-SNAPSHOT. The snapshots are published at sonatype as well as in mulesoft public repos.

Regards, Pavel

On Mon, Apr 27, 2015 at 6:35 AM, rajkumar1979 notifications@github.com wrote:

Sorry ,

Its a little confusing.

I am using the version 1.3.3 to generated the raml to jaxrs classes, I thought you fixed 1.3.3 by upgrading to the latest JsonSchematoPojo, I thought you mentioned that you fixed it in the snapshot release,Could you please tell me the snapshot version of the plugin that I can use to generate these artifacts.

— Reply to this email directly or view it on GitHub https://github.com/mulesoft/raml-for-jax-rs/issues/76#issuecomment-96451932 .

rajkumar1979 commented 9 years ago

After updating the 1.3.4-SNAPSHOT, when I print the response it displays the following json { "subscriptionID": 100, "subscriptionState": null, "offerID": 2220000, "trialStartDate": null, "trialEndDate": null, "subscriptionStartDate": null, "subscriptionEndDate": null, "nextBillDate": null, "effectiveCancellationDate": null, "entitledProduct": [ { "entitledProductID": 1, "productType": null, "entitledProductState": "ACTIVE", "additionalProperties": {} } ], "additionalProperties": {} }

I am not sure why its including an element named additionalProperties as part of every object in the response.

rajkumar1979 commented 9 years ago

I also tried to print the request that is being sent and tried to echo the same as response.

input to my service { "accountDetails": { "accountID": "123145631722297", "accountClassification": "SmallBusiness", "accountSubClassification": "Regular", "personaID": "123145631723942", "authID": "123145631723942" }, "offerID": "20000000", "paymentDetails": { "type": "CreditCard", "attribute": [ { "name": "nameOnCard", "value": "John" }, { "name": "cardNumber", "value": "9919930747642032" }, { "name": "expirationMonth", "value": "11" }, { "name": "expirationYear", "value": "2015" }, { "name": "cvn", "value": "123" } ], "paymentAddress": { "addressLine1": "123 main str", "addressLine2": "APT 122", "addressLine3": "Near Macdonald", "addressLine4": "OPP Gas station", "city": "San Diego", "stateOrProvince": "CA", "postalCode": "92122", "country": "US" } } }

Output

{ "accountDetails": { "accountID": "123145631722297", "accountClassification": "SmallBusiness", "accountSubClassification": "Regular", "personaID": "123145631723942", "authID": "123145631723942", "additionalProperties": {} }, "offerID": "20000000", "paymentDetails": { "type": "CreditCard", "attribute": [ { "name": "nameOnCard", "value": "John", "additionalProperties": {} }, { "name": "cardNumber", "value": "9919930747642032", "additionalProperties": {} }, { "name": "expirationMonth", "value": "11", "additionalProperties": {} }, { "name": "expirationYear", "value": "2015", "additionalProperties": {} }, { "name": "cvn", "value": "123", "additionalProperties": {} } ], "paymentAddress": { "addressLine1": "123 main str", "addressLine2": "APT 122", "addressLine3": "Near Macdonald", "addressLine4": "OPP Gas station", "city": "San Diego", "stateOrProvince": "CA", "postalCode": "92122", "country": "US", "additionalProperties": {} }, "additionalProperties": {} }, "additionalProperties": {} }

It adds additionalProperties as part of every object.

this was not hapenning in 1.3.3

ddossot commented 9 years ago

What JSON provider do you use with JAX-RS? Jackson?

rajkumar1979 commented 9 years ago

I am using jackson.

Also My json schema does not have addiitonal properties, I tried without that and it still puts those aspart of every object

ddossot commented 9 years ago

Very strange, never seen this before. Can you show your latest plugin config and latest JSON schema?

rajkumar1979 commented 9 years ago

I added the plugin

org.raml.plugins raml-jaxrs-maven-plugin 1.3.4-SNAPSHOT ${basedir}/src/main/resources/raml com.intuit.platform.webs.subscription 2.0 false jackson2 true generate generate-sources

I added the plugin repository as well

sonatype-public-repository https://oss.sonatype.org/content/groups/public true true

My raml definition

%RAML 0.8

title: Create Subscription version: v1

baseUri: http://corp.intuit.net

baseUri: http://mocksvc.mulesoft.com/mocks/0cb2e36d-c426-4720-9a0a-a177a3e4ac10

baseUri: http://mocksvc.mulesoft.com/mocks/ca9092b8-c563-43fe-ad7a-2bf20bdc2a27/mocks/0cb2e36d-c426-4720-9a0a-a177a3e4ac10 mediaType: application/json schemas:

rajkumar1979 commented 9 years ago

Schema Definition that I used

{ "$schema": "http://json-schema.org/draft-04/schema", "type": "object", "properties": { "accountDetails": { "type": "object", "properties": {
"accountID": { "type": "string", "description": "This is the standard Intuit company identifier - it is the same as the customerAccountID." }, "accountClassification": { "type": "string", "description": "The Account Classification describes the relationship with Intuit that the account has that is being created. As an example in the Accountant-Client use case, the Classification can be one of SmallBusiness or Accountant. This information is important to determine offers, features, or pricing that may be available to the account." }, "accountSubClassification": { "type": "string", "description": "The Account Sub Classification allows a further categorization of the relationship to Intuit for a given account. As an example in the Accountant-Client use case, the a Sub Classification for SmallBusiness can be Regular or Enterprise. Likewise for Accountant." }, "personaID": { "type": "string", "description": "_Either personaID or authID is required, with personaID the preferred value (if available)." }, "authID": { "type": "string", "description": "_authID is required if personaID is not provided. The value would be used in conjunction with the realmID to derive the personaID and associated PII info." } }, "required": [ "personaID", "accountID" ] }, "offerID": { "type": "string", "description": "Offer ID representing the offer that the customer is getting." }, "paymentDetails": { "type": "object", "description": "Representation for the address associated with the customers payment.", "properties": { "type": { "type": "string", "description": "The method of payment." }, "attribute": { "type": "array", "description": "Array of name/value pairs that correspond to the attributes required for the method of payment provided.", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Attribute name for a payment detail element." }, "value": { "type": "string", "description": "Attribute value for a payment detail element." } }, "required": [ "name", "value" ] }

                },
                "paymentAddress": {
                    "type": "object",
                    "properties": {
                        "addressLine1": {
                            "type": "string",
                            "description": "First address line associated with the payment address"
                        },
                        "addressLine2": {
                            "type": "string",
                            "description": "Optional second address line"
                        },
                        "addressLine3": {
                            "type": "string",
                            "description": "Optional third address line"
                        },
                        "addressLine4": {
                            "type": "string",
                            "description": "Optional fourth address line"
                        },
                        "city": {
                            "type": "string",
                            "description": "Civic location"
                        },
                        "stateOrProvince": {
                            "type": "string",
                            "description": "State or province identifier. In the United States and Canada, this corresponds to a 2 letter code. Optional as not all countries have a sub-national region"
                        },
                        "postalCode": {
                            "type": "string",
                            "description": "Postal code or zip code. "
                        },
                        "country": {
                            "type": "string",
                            "description": "2 character ISO 3166-1 code for country"
                        }
                    },
                    "required": [
                        "addressLine1",
                        "city"
                    ]
                }
            }
        }
    }
   }
petrochenko-pavel-a commented 9 years ago

Hi, I have no bandwidth right now, but promise to dedicate time in nearest days probably Friday or Satarday to dig deep into this.

ddossot commented 9 years ago

@rajkumar1979 Your comments are unreadable. Can you please format them?

Also, I don't see additionalProperties in your JSON Schema.

rajkumar1979 commented 9 years ago

I dont have additionalProperties in my schema, thats why I am surprised as why it gets included in the response.

How can I attach a file to this?

ddossot commented 9 years ago

If you do not have additionalProperties set to false in your schema, you will get the additionalProperties catch-all field.

You can not attach files: edit your previous comments and format them with Markdown (see https://help.github.com/articles/github-flavored-markdown/ for syntax).

rajkumar1979 commented 9 years ago

Hi ,

The Key was additionalProperties, I set it to false and it works now.

Thanks for all the help and assistance.

Thanks

Raj.

gr423 commented 6 years ago

Hi ,

I do face the same issue . The required fields are not marked with required annotation, and hence it is accepting the payload without mandatory fields , which is not expected. Please could help me here.

<plugin>
<groupId>org.raml.jaxrs</groupId>
<artifactId>raml-to-jaxrs-maven-plugin</artifactId>
    <version>3.0.1</version>
    <executions>
    <execution>
    <id>GenerateAdminV2</id>
    <goals>
        <goal>generate</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
                            <ramlFile>${basedir}/src/main/resources/raml/v1/MAS_api.raml</ramlFile>
                            <resourcePackage>com.nagra.opentv.mas.v1.resource</resourcePackage>
<modelPackage>com.some.st.mas.v1.model</modelPackage>
<removeOldOutput>true</removeOldOutput>
    <generateTypesWith>
        <value>jackson2</value>
   </generateTypesWith>
<jsonMapperConfiguration>
    <includeToString>true</includeToString>
</jsonMapperConfiguration>
</configuration>
</execution>
</executions>
</plugin>