jboss-fuse / fuse-apicurito-generator

Fuse Apicurito Generator
5 stars 14 forks source link

issue9 - adding IDs to generated fuse project from apicurito generator #10

Closed bfitzpat closed 6 years ago

bfitzpat commented 6 years ago

Signed-off-by: Brian Fitzpatrick bfitzpat@redhat.com

bfitzpat commented 6 years ago

This PR adds a new test, tweaks the camel file template slightly, and creates UUID-generated for anything generated with the Rest DSL from apicurito.

bfitzpat commented 6 years ago

Here's an example generated with the new code: `<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

<camelContext id="context1" xmlns="http://camel.apache.org/schema/spring">

    <onException>
        <exception>java.lang.Exception</exception>
        <handled><constant>true</constant></handled>
        <setHeader headerName="Exchange.HTTP_RESPONSE_CODE">
            <constant>500</constant>
        </setHeader>
        <setBody>
            <simple>${exception.message}</simple>
        </setBody>
    </onException>

    <restConfiguration component="servlet" apiContextPath="/openapi.json"/>

    <rest id="rest1" path="/" enableCORS="true">
        <get id="openapi.json" produces="application/json" uri="openapi.json">
            <description>Gets the openapi document for this service</description>
            <route id="rest1-route1">
                <setHeader id="setHeader-route1" headerName="Exchange.CONTENT_TYPE">
                    <constant>application/vnd.oai.openapi+json</constant>
                </setHeader>
                <setBody id="setBody-route1">
                    <simple>resource:classpath:openapi.json</simple>
                </setBody>
            </route>
        </get>
    </rest>

    <rest id="rest2" path="/v2" bindingMode="json" enableCORS="true">
        <put consumes="application/json,application/xml" id="updatePet" produces="application/xml,application/json" uri="/pet">
            <param description="Pet object that needs to be added to the store" name="body" required="true" type="body"/>
            <to uri="direct:updatePet"/>
        </put>
        <post consumes="application/json,application/xml" id="addPet" produces="application/xml,application/json" uri="/pet">
            <param description="Pet object that needs to be added to the store" name="body" required="true" type="body"/>
            <to uri="direct:addPet"/>
        </post>
        <get id="findPetsByStatus" produces="application/xml,application/json" uri="/pet/findByStatus">
            <description>Multiple status values can be provided with comma separated strings</description>
            <param arrayType="string" collectionFormat="multi" dataType="array" description="Status values that need to be considered for filter" name="status" required="true" type="query"/>
            <to uri="direct:findPetsByStatus"/>
        </get>
        <get id="findPetsByTags" produces="application/xml,application/json" uri="/pet/findByTags">
            <description>Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.</description>
            <param arrayType="string" collectionFormat="multi" dataType="array" description="Tags to filter by" name="tags" required="true" type="query"/>
            <to uri="direct:findPetsByTags"/>
        </get>
        <get id="getPetById" produces="application/xml,application/json" uri="/pet/{petId}">
            <description>Returns a single pet</description>
            <param dataType="integer" description="ID of pet to return" name="petId" required="true" type="path"/>
            <to uri="direct:getPetById"/>
        </get>
        <post consumes="application/x-www-form-urlencoded" id="updatePetWithForm" produces="application/xml,application/json" uri="/pet/{petId}">
            <param dataType="integer" description="ID of pet that needs to be updated" name="petId" required="true" type="path"/>
            <param dataType="string" description="Updated name of the pet" name="name" required="false" type="formData"/>
            <param dataType="string" description="Updated status of the pet" name="status" required="false" type="formData"/>
            <to uri="direct:updatePetWithForm"/>
        </post>
        <delete id="deletePet" produces="application/xml,application/json" uri="/pet/{petId}">
            <param dataType="string" name="api_key" required="false" type="header"/>
            <param dataType="integer" description="Pet id to delete" name="petId" required="true" type="path"/>
            <to uri="direct:deletePet"/>
        </delete>
        <post consumes="multipart/form-data" id="uploadFile" produces="application/json" uri="/pet/{petId}/uploadImage">
            <param dataType="integer" description="ID of pet to update" name="petId" required="true" type="path"/>
            <param dataType="string" description="Additional data to pass to server" name="additionalMetadata" required="false" type="formData"/>
            <param dataType="file" description="file to upload" name="file" required="false" type="formData"/>
            <to uri="direct:uploadFile"/>
        </post>
        <get id="getInventory" produces="application/json" uri="/store/inventory">
            <description>Returns a map of status codes to quantities</description>
            <to uri="direct:getInventory"/>
        </get>
        <post id="placeOrder" produces="application/xml,application/json" uri="/store/order">
            <param description="order placed for purchasing the pet" name="body" required="true" type="body"/>
            <to uri="direct:placeOrder"/>
        </post>
        <get id="getOrderById" produces="application/xml,application/json" uri="/store/order/{orderId}">
            <description>For valid response try integer IDs with value &gt;= 1 and &lt;= 10. Other values will generated exceptions</description>
            <param dataType="integer" description="ID of pet that needs to be fetched" name="orderId" required="true" type="path"/>
            <to uri="direct:getOrderById"/>
        </get>
        <delete id="deleteOrder" produces="application/xml,application/json" uri="/store/order/{orderId}">
            <description>For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors</description>
            <param dataType="integer" description="ID of the order that needs to be deleted" name="orderId" required="true" type="path"/>
            <to uri="direct:deleteOrder"/>
        </delete>
        <post id="createUser" produces="application/xml,application/json" uri="/user">
            <description>This can only be done by the logged in user.</description>
            <param description="Created user object" name="body" required="true" type="body"/>
            <to uri="direct:createUser"/>
        </post>
        <post id="createUsersWithArrayInput" produces="application/xml,application/json" uri="/user/createWithArray">
            <param description="List of user object" name="body" required="true" type="body"/>
            <to uri="direct:createUsersWithArrayInput"/>
        </post>
        <post id="createUsersWithListInput" produces="application/xml,application/json" uri="/user/createWithList">
            <param description="List of user object" name="body" required="true" type="body"/>
            <to uri="direct:createUsersWithListInput"/>
        </post>
        <get id="loginUser" produces="application/xml,application/json" uri="/user/login">
            <param dataType="string" description="The user name for login" name="username" required="true" type="query"/>
            <param dataType="string" description="The password for login in clear text" name="password" required="true" type="query"/>
            <to uri="direct:loginUser"/>
        </get>
        <get id="logoutUser" produces="application/xml,application/json" uri="/user/logout">
            <to uri="direct:logoutUser"/>
        </get>
        <get id="getUserByName" produces="application/xml,application/json" uri="/user/{username}">
            <param dataType="string" description="The name that needs to be fetched. Use user1 for testing. " name="username" required="true" type="path"/>
            <to uri="direct:getUserByName"/>
        </get>
        <put id="updateUser" produces="application/xml,application/json" uri="/user/{username}">
            <description>This can only be done by the logged in user.</description>
            <param dataType="string" description="name that need to be updated" name="username" required="true" type="path"/>
            <param description="Updated user object" name="body" required="true" type="body"/>
            <to uri="direct:updateUser"/>
        </put>
        <delete id="deleteUser" produces="application/xml,application/json" uri="/user/{username}">
            <description>This can only be done by the logged in user.</description>
            <param dataType="string" description="The name that needs to be deleted" name="username" required="true" type="path"/>
            <to uri="direct:deleteUser"/>
        </delete>
    </rest>

    <route id="route-708124ac-493b-4348-ada1-587206524f88">
        <from id="from-95527728-7d5c-4817-978d-1a713110c801" uri="direct:updatePet"/>
        <to id="to-ce85e2d4-c63d-473a-b80e-7b6823f47ae4" uri="direct:501"/>
    </route>
    <route id="route-410d191b-ca55-4359-9cd6-5c39423c04ac">
        <from id="from-056371ce-53a8-4d0a-8ce6-183435e66295" uri="direct:addPet"/>
        <to id="to-ef5053bc-6561-4fe2-81eb-9f37f36d0508" uri="direct:501"/>
    </route>
    <route id="route-6767fca0-3001-4dd3-a3c5-d1f97455f598">
        <from id="from-9311d86e-41f8-448b-a0a1-0a8c26c88dfc" uri="direct:findPetsByStatus"/>
        <to id="to-c9885700-525f-4bc2-bbf9-090b488e9082" uri="direct:501"/>
    </route>
    <route id="route-4dbd70d3-dba8-493f-aa0d-abb4669c4617">
        <from id="from-a6ab52e6-1a54-415b-a92f-5311eebb1bc6" uri="direct:findPetsByTags"/>
        <to id="to-2f0de224-4198-46ce-9798-acab6b1e2c35" uri="direct:501"/>
    </route>
    <route id="route-fad9b91d-6ba8-47b0-a5ec-5928170fc643">
        <from id="from-cc77a20d-b27c-4eb2-a8a1-58d7a5e4d90d" uri="direct:getPetById"/>
        <to id="to-4fee7bb5-d869-478a-a124-accea0ef64a3" uri="direct:501"/>
    </route>
    <route id="route-8d93f9ad-4f15-42ed-94b4-2e866c68995f">
        <from id="from-a2030b37-3526-4780-ae4c-0c53fc581a1c" uri="direct:updatePetWithForm"/>
        <to id="to-8bcd4272-ca3f-4531-931b-01d86f1ba923" uri="direct:501"/>
    </route>
    <route id="route-ba0c64f6-387b-4cd2-a6a0-0bfa4802dbf8">
        <from id="from-4326767f-4d62-4d67-8443-b153379c69d6" uri="direct:deletePet"/>
        <to id="to-9a99fe90-2602-4307-b152-08854cb6b7cb" uri="direct:501"/>
    </route>
    <route id="route-f70f4c73-12c9-4aaa-ab47-1eb56c5917d9">
        <from id="from-3c94fdd1-85ac-403b-8cc3-fcf647fad120" uri="direct:uploadFile"/>
        <to id="to-8c153ab4-5c86-4873-8226-42300e44042e" uri="direct:501"/>
    </route>
    <route id="route-5885f938-e098-463b-9a7e-4e565851e961">
        <from id="from-885c2dfc-9877-4921-b651-abe3bf318d3b" uri="direct:getInventory"/>
        <to id="to-75faa1c3-797c-4f8b-945f-876e0b0a9234" uri="direct:501"/>
    </route>
    <route id="route-7ee63aab-33ad-462e-9db2-1df33441e4c9">
        <from id="from-836ad9f5-6536-4970-b63c-8a357321964e" uri="direct:placeOrder"/>
        <to id="to-d4d1a357-71f1-433b-bf87-54b7143b9be5" uri="direct:501"/>
    </route>
    <route id="route-837a9517-cf43-407b-975f-1aa847e70561">
        <from id="from-72bcc9f1-a108-458b-851b-92fbf87e730e" uri="direct:getOrderById"/>
        <to id="to-6bb79b85-2e77-4fba-b8a2-44a323bd46f9" uri="direct:501"/>
    </route>
    <route id="route-5e450b79-7dc5-4c41-8c54-8484a2a403b3">
        <from id="from-fa407215-5779-4679-8a64-c1c6bbd489fc" uri="direct:deleteOrder"/>
        <to id="to-c6ec0af8-76e8-433a-ba52-b55f1667153c" uri="direct:501"/>
    </route>
    <route id="route-0fcf29c1-481e-483e-897c-e64a90f75253">
        <from id="from-ac2ba174-0802-4ec3-8f61-3d4ea3bbe97c" uri="direct:createUser"/>
        <to id="to-c19d6c16-eb89-47be-8c0b-f8f02d6e2e01" uri="direct:501"/>
    </route>
    <route id="route-bdeffebf-aae9-4530-ad9e-c4d6d0c747b3">
        <from id="from-8263aa64-b90d-4718-865e-09679a2de340" uri="direct:createUsersWithArrayInput"/>
        <to id="to-5b7e0ae1-c2e9-4f3f-bbaa-3e2081c410e1" uri="direct:501"/>
    </route>
    <route id="route-dd279923-76a3-4a8e-8aca-d1588e701f19">
        <from id="from-66fce8ba-60c1-4d55-88dd-2359a56f8390" uri="direct:createUsersWithListInput"/>
        <to id="to-0d76d3bd-68d6-4983-8b7d-32ed850dccf1" uri="direct:501"/>
    </route>
    <route id="route-4e20544c-1532-48b4-b443-ba6bf0e997fc">
        <from id="from-edfe1558-17e3-436b-9d75-ea8dd3a60d79" uri="direct:loginUser"/>
        <to id="to-ed4357aa-01d0-467a-a579-b2950d85e5bc" uri="direct:501"/>
    </route>
    <route id="route-9cff8aa8-a1f0-49eb-ba3d-106307885161">
        <from id="from-7de5c66d-577c-4045-b992-eb8c48ba9cac" uri="direct:logoutUser"/>
        <to id="to-923170d2-483b-49b9-a317-b96d0726cf4b" uri="direct:501"/>
    </route>
    <route id="route-1e0f49e3-283b-4d46-ab62-60c0208074c3">
        <from id="from-120f29c9-7238-41f8-a40b-4cde485bc3fa" uri="direct:getUserByName"/>
        <to id="to-2ea1eb34-ee80-4e73-80e2-48af5a85cd2a" uri="direct:501"/>
    </route>
    <route id="route-85e5e345-3602-4667-89b1-08e1b608677f">
        <from id="from-08a414f5-19ce-4153-aab7-5ccf529736c5" uri="direct:updateUser"/>
        <to id="to-4992f04a-1326-4ee7-b00b-69db9e19df73" uri="direct:501"/>
    </route>
    <route id="route-949daae3-35ed-4399-a071-b3c8db88e3cd">
        <from id="from-b0ef7451-588b-4a89-a6ed-bb428e5b1df0" uri="direct:deleteUser"/>
        <to id="to-abbdca3d-1d54-465b-9824-01ee00eaa5a7" uri="direct:501"/>
    </route>

    <route id="route2">
        <from id="from-route2" uri="direct:501"/>
        <log id="log-route2" message="API operation not yet implemented: ${headers.CamelHttpMethod} ${headers.CamelHttpPath}"/>
        <setHeader id="setHeader-route2" headerName="Exchange.HTTP_RESPONSE_CODE">
            <constant>501</constant>
        </setHeader>
        <setBody id="setBody-route2">
            <simple>API operation not implemented: ${headers.CamelHttpMethod} ${headers.CamelHttpPath}</simple>
        </setBody>
    </route>

</camelContext>

`

apupier commented 6 years ago

I'm not sure what the ID is used for, specifically

In modeling world, there are usually a design id to model elements. It is a good practice to have design ids to be able to link correctly to the source. With Camel, there is no specific design id, the id used is both design and runtime (which can also have its -discussed- advantages, such as validating at design time unicity of these ids, being able to reference elements from a context to another) Concretely, these ids are used by Fuse Tooling for debugging purpose and also for the internal Camel design model.

zregvart commented 6 years ago

@bfitzpat you could also use the underlying Mustache templating framework, it supports simple Function<String, String> helpers, like:

Mustache mustache = new DefaultMustacheFactory().compile(new StringReader("Hi I'm an {{uuid}}"), "example");

Function<String, String> uuid = (s) -> UUID.randomUUID().toString();

mustache.execute(new OutputStreamWriter(System.out),
    Collections.singletonList(Collections.singletonMap("uuid", uuid))).flush();

Would yield:

Hi I'm an 131497df-fe6c-4818-9954-0a0bc3be182d

You need to add that Function<String, String> to variables here:

https://github.com/jboss-fuse/fuse-apicurito-generator/blob/7ba5a8b134f59bce314e4bb917b949060811e503/src/main/java/com/redhat/fuse/apicurio/jaxrs/GenerateFuseProjectResource.java#L123-L127

bfitzpat commented 6 years ago

@zregvart That's awesome. I shall change the code immediately. I wanted to use Mustache but couldn't find a good example of how to do a dynamic replace when I was using my Google-fu yesterday!

@EricWittmann The IDs are needed for a number of things. They are mostly used for debugging purposes so we can get a handle to individual elements in the config when we go into a debug session in Eclipse - so the tooling requires them. When we import the generated project with no Ids, we get a ton of warnings as you saw. Those warnings are mostly resolved the first time the user opens the tooling with the config, but we want to reduce the warnings and errors as far as possible from the start.

bfitzpat commented 6 years ago

@zregvart That's MUCH cleaner -- thanks for the great suggestion!

bfitzpat commented 6 years ago

@EricWittmann or @apupier can you take another look for approval?