Skip to content

Everything discussed in the Twitch live sessions for MuleSoft beginners.

Notifications You must be signed in to change notification settings

alexandramartinez/mulesoft-from-start

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MuleSoft from Start: A Beginner's Guide

Everything discussed in the Twitch live sessions for MuleSoft beginners.


WE DID IT!

All edited videos have been published and updated in the links below!


💻 Past Sessions

Session Title Description Twitch YouTube
0 Planning the Outline Based on the book MuleSoft for Salesforce Developers, we reviewed the relevant topics and created an appropriate outline for the upcoming sessions. More info here. Full video (55min) Edited video (38min)
1 MuleSoft Overview We went through an overview of the different MuleSoft products and how to get involved with the community. More info here. Full video (1h2min) Edited video (34min)
2 What is an API? We explained the API basics and learned what is MuleSoft's API-led connectivity approach. More info here. Full video (1h1m) Edited video (35min)
3 Design an API Specification We created the requirements for our Blog API and started designing our API Spec. Finish your homework before the next session! More info here. Full video (1h16m) Edited video (42min)
4 Test & Publish the API Spec We tested the API Specification using the mocking service in Design Center and adjusted a few things we had to change. Then, we published the API Spec to Exchange. Finally, we created a new Mule project from the published asset. More info here. Full video (1h10m) Edited video (27min)
5 Develop the API in Anypoint Studio We created a new Mule project with the scaffolded flows from the published API specification and started our API implementation / development. More info here. Full video (1h19m) Edited video (37m)
6 Debug the Mule App in Anypoint Studio We reviewed how to implement the articles logic, created a Postman collection with its local+dev environments, and learned how to debug our Mule application. More info here. Full video (1h) Edited video (39m)
7 Deploy the Mule App to CloudHub (Runtime Manager) We confirmed the API works locally, so we deployed it to CloudHub (located in Runtime Manager) to test it in the dev environment. More info here. - Part 1 Full video (18m) - Part 2 Full video (1h2m) Edited video (14m)
8 Set up CI/CD & API Autodiscovery (API Manager) We connected our Mule app from Runtime Manager to our API in API Manager to apply security policies using API Autodiscovery. We learned how to apply CI/CD pipelines to our local project and how to do them using GitHub Actions. Full video (1h15m) Edited video (27m)
9 Test your Mule app with MUnit testing (manually from Anypoint Studio) We created some MUnit tests for our Mule app's flows and ran them in Anypoint Studio to increase the MUnit coverage. Full video (1h16m) Edited video (58m)

📝 Outline & Links 🔗

✅ Session 1

MuleSoft Overview

Other resources

✅ Session 2

What is an API?

Other resources

✅ Session 3

Design an API Specification
  • Step 1: Write down requirements
  • Step 2: Design the API spec in Design Center
    • Anypoint Platform > Design Center > Create > New API Specification
    • Name: Blog API
    • Guide me through it
    • Create API
  • This is the RAML we generated during the session.
Homework for next session
  • Finish creating the API Specification with the resources we didn't get to create during the session: Writers, Categories, and Comments.
  • The solution will be added to this repo before the next session.
Alex's homework solution

Remember we can all have different API designs depending on what we are trying to achieve with our API. This is the solution that I created for what I believe is the correct design. But please feel free to send me a message if you have a different solution!

Steps:

  1. I modified the data types we created in the last session. Updated requirements can be found here.

    a) Article data type:

    * writerId (number) -> writer (Writer)
    * categoryId (number) -> category (string)
    

    b) Writer data type:

     * removed articles
    

    c) Category data type was removed since it was transformed to just a string

    d) Comment data type:

     * removed articleId
    
  2. I created a new API Specification using RAML 1.0 instead of the visual UI. This will make it easier moving forward for us to compare each other's results.

  3. Inside this new API Spec, I created a types folder with our data types:

    • Article
    • Comment
    • Error
    • Writer
  4. The final resources I created are as folows:

    /articles
    /articles/{id}
    /articles/{id}/comments
    /articles/{id}/comments/{id}
    /writers
    /writers/{id}
    /categories
    
  5. I decided to use a query parameter on the /categories resource to query if a specific category (string) exists or not. A similar approach would be done with the comments. If you don't want to have such a long URI like /articles/1/comments/1, you can also decide to use query parameters instead. This is completely up to your design/preference.

  6. Finally, the whole code I generated can be found here. You can decide to use this design to continue with the rest of the sessions, or continue with your own API spec!

✅ Session 4

Publish an API Specification
  • Step 1: Test your API Spec using the mocking service (adjust spec if needed)
  • Step 2: Publish to Exchange
  • Step 3: Create a new Mule project in Studio, importing the API Spec from Exchange to scaffold the flows

Other resources

✅ Session 5

Develop the API in Anypoint Studio
  • Step 1: Scaffold the flows in Studio from the API Specification we had published to Exchange (we did this at the end of session 4)
  • Step 2: Move the Global Elements from maxines-blog-api.xml to a new global.xml file
  • Step 3: Create the local.properties and dev.properties to keep separate properties per environment (you can also use .yaml)
  • Step 4: Add a Global Property env with the value local
  • Step 5: Add a Configuration Properties for the file ${env}.properties
  • Step 6: Create the default.properties file and its Configuration to keep the common values
  • Step 7: Start the API implementation using Object Store (you can also connect to a database or an external service if you want)
  • This is the project we generated during the session
  • To see all the changes to the Mule project in this session, refer to this commit: fa444df

Other resources

Homework for next session
  • Create new Mule Configuration Files to keep each resources' logic separate from the main maxines-blog-api.xml file
  • Add subflows inside these new config files instead of flows
  • Reference these new subflows from the main flows from the APIKit router
  • Finish creating the logic for the articles resource (happy path)
  • Improve the code to avoid duplicating the same code (like we do with the Retrieve connector named GET articles) -- this helps to avoid human mistake
Alex's homework solution

Remember we can all have different solutions. You don't have to do exactly what I do. This is just to guide you or give you a better idea of what other solutions you can implement.

You can see the full list of changes I did for this homework in this Pull Request

Since this solution is a bit bigger, I'll break this down in stages.

Stage 1: Updating the RAML

Steps:

  1. I decided to add a POST and a DELETE to the /categories resource. To do this, I went back to Design Center and implemented those two methods in the RAML.

    /categories:
        
        post:
            body:
            type: string[]
            example:
                ["Programming"]
            responses:
            201:
                body: 
                type: string[]
                example:
                    ["MuleSoft", "DataWeave", "Programming"]
            409:
                body: Error
        delete:
            body:
            type: string[]
            example:
                ["DataWeave"]
            responses:
            204:
            404:
                body: Error
            409:
                body: Error
  2. I also updated the version in the RAML (should be at the top).

    version: 1.0.2
  3. After that, I published these changes to the Exchange asset just by clicking the Publish button at the top-right.

  4. Once the changes are in Exchange, I went back to Anypoint Studio and selected Maxine's Blog API > Update version.

  5. You can click on the check for updates button at the top-right of the new window to reflect the latest version. Make sure you are signed in to your Anypoint Platform account, otherwise you might have issues updating.

  6. A workaround to this, if you experience a lot of issues with updating via the UI, is to go to your pom.xml and manually update the version in the dependencies. For example, this is how it looks like in my project:

    <dependency>
        <groupId>25cebd62-2548-4351-8196-5a262e78e663</groupId>
        <artifactId>maxines-blog-api</artifactId>
        <version>1.0.2</version>
        <classifier>raml</classifier>
        <type>zip</type>
    </dependency>
  7. The UI should ask you if you want to add the new flows. You can say yes to do the scaffolding for those flows. The rest of your flows should remain untouched.

  8. By this point, Studio correctly generated the two new flows for me:

    • delete:\categories:application\json:maxines-blog-api-config
    • post:\categories:application\json:maxines-blog-api-config

Stage 2: Creating new Mule Configuration Files per resource

Steps:

  1. I created the following files:

    • resources-articles.xml
    • resources-categories.xml
    • resources-comments.xml
    • resources-writers.xml
  2. Inside these files, I created a sub-flow per HTTP Method. For example, the resources-articles file has the following sub-flows (note that these have some naming conventions that I decided to follow, like <config-file-name>:<flow-name>, but you can name them however you prefer):

    • resources-articles:read-all-articles
    • resources-articles:read-one-article
    • resources-articles:create-one-article
    • resources-articles:update-one-article
    • resources-articles:delete-one-article
  3. Then, I added flow-refs to all the flows in maxines-blog-api.xml so the logic can live inside the new config files I created.

  4. Now I can directly modify the logic from the Mule Configuration Files instead of having to navigate through the huge main file.

NOTE: If you leave any of the flows or subflows empty, the application will not run. Make sure you add at least one logger (for example) to be able to run the app to test.

Stage 3: Creating the logic for the articles resource

Steps:

  1. Created four sub-flows to be reused by the rest of the flows.

  2. Improved the logic to read all articles to reference the new resources-articles:retrieve-all-articles-in-vars.articles sub-flow.

  3. Created the logic to read one article by filtering the list of articles using DataWeave (Transform Message).

    Code:

    %dw 2.0
    output application/json
    ---
    (vars.articles default [] filter ($.id ~= vars.articleId))[0]
  4. Updated the logic to create one article.

  5. Created the logic to update one article and used DataWeave to update the data.

    Code:

    %dw 2.0
    output application/json
    ---
    vars.articles default [] map (
        if ($.id ~= vars.articleId)
            payload
        else $
    )
  6. Created the logic to delete one article by filtering out the article by the articleId using DataWeave.

    Code:

    %dw 2.0
    output application/json
    ---
    vars.articles default [] filter ($.id != vars.articleId)

    Note that for this last one we had to make sure the articleId variable was indeed a Number and not a String. The URI Parameters or the Query Parameters are usually of type String. You need to use further DataWeave code to transform it to a Number when applicable. In this case, we used the following code when we create the variable:

    attributes.uriParams.'articleId' as Number

✅ Session 6

Debug the Mule App in Anypoint Studio
Homework for next session

Finish creating the rest of the requests in Postman from our API specification.

Alex's homework solution
  • Created the rest of the requests in Postman.
  • You can see the full list of changes I did for this homework in Pull Request #3.

Note
I worked on some improvements to the code's implementation before session 7. These changes were not included as session 6's homework and that's why I did not add them as part of that pull request. You can see all the improvements I did on commit 60a9813.

✅ Session 7

Deploy the Mule App to CloudHub
  • Since my past Anypoint Platform account had already expired, I had to create a new API Specification in the new account and publish to Exchange
    • For this to be updated in the Mule app, I had to modify the pom.xml and the global.xml files to reflect the new asset
    • See the changes we did to the repo in this session: Pull Request #4
  • We learned how to deploy the Mule app to CloudHub manually from Anypoint Studio
  • We learned the UI of Runtime Manager

✅ Session 8

Set up CI/CD & API Autodiscovery
  • See the changes we did to the repo in this session: Pull Request #5
  • Step 1: Retrieve your Anypoint Platform credentials:
    • Access Management > Business Groups > select your business group > Environments > Sandbox (or your environment)
    • Here you can retrieve your Client ID and Client Secret, which we'll refer to as:
      • ap.client.id & ap.client.secret from the Maven command
      • anypoint.platform.client_id & anypoint.platform.client_secret from the Mule app's properties
  • Step 2: Retrieve your Connected App's credentials:
    • Access Management > Connected Apps > Create app > App acts on it's own behalf
    • Scopes:
      • Design Center Developer
      • View Environment
      • View Organization
      • Profile
      • Cloudhub Organization Admin
      • Create Applications
      • Delete Applications
      • Download Applications
      • Read Applications
      • Read Servers
    • Retrieve Client ID and Client Secret, which we'll refer to as:
      • CONNECTED_APP_CLIENT_ID & CONNECTED_APP_CLIENT_SECRET from GitHub Actions secrets
      • connectedapp.client.id & connectedapp.client.secret from the Maven command
  • Step 3: Modify your pom.xml:
<plugin>
    <groupId>org.mule.tools.maven</groupId>
    <artifactId>mule-maven-plugin</artifactId>
    <version>${mule.maven.plugin.version}</version>
    <extensions>true</extensions>
    <!-- Deployment config start -->
    <configuration>
        <cloudHubDeployment>
            <uri>https://anypoint.mulesoft.com</uri>
            <muleVersion>4.4.0</muleVersion>
            <applicationName>maxines-blog</applicationName>
            <environment>Sandbox</environment>
            <workerType>MICRO</workerType>
            <region>us-east-2</region>
            <workers>1</workers>
            <objectStoreV2>true</objectStoreV2>
            <connectedAppClientId>${connectedapp.client.id}</connectedAppClientId>
            <connectedAppClientSecret>${connectedapp.client.secret}</connectedAppClientSecret>
            <connectedAppGrantType>client_credentials</connectedAppGrantType>
            <properties>
                <env>dev</env>
                <anypoint.platform.client_id>${ap.client.id}</anypoint.platform.client_id>
                <anypoint.platform.client_secret>${ap.client.secret}</anypoint.platform.client_secret>
            </properties>
        </cloudHubDeployment>
    </configuration>
    <!-- Deployment config end -->
</plugin>
  • Step 4: If you want to set it up with GitHub Actions, you can follow this quick reference
    • Make sure you add the actual credentials to the GitHub secrets in Settings > Secrets and variables > Actions > New repository secret
      • CONNECTED_APP_CLIENT_ID
      • CONNECTED_APP_CLIENT_SECRET
      • ANYPOINT_PLATFORM_CLIENT_ID
      • ANYPOINT_PLATFORM_CLIENT_SECRET
    • And make sure you modify the maven command to include all 4 credentials. Like so:
mvn deploy -DskipMunitTests -DmuleDeploy \
-Dmule.artifact=$artifactName \
-Dconnectedapp.client.id="${{ secrets.CONNECTED_APP_CLIENT_ID }}" \
-Dconnectedapp.client.secret="${{ secrets.CONNECTED_APP_CLIENT_SECRET }}" \
-Dap.client.id="${{ secrets.ANYPOINT_PLATFORM_CLIENT_ID }}" \
-Dap.client.secret="${{ secrets.ANYPOINT_PLATFORM_CLIENT_SECRET }}"
  • Step 5: If you want to test this locally (as we did on the session), you just have to run the Maven command in your Terminal with your actual credentials. Like so:
mvn deploy -DskipMunitTests -DmuleDeploy \
 -Dconnectedapp.client.id="ae0bd2e7fd154c3adf1cc934543a07e" \
 -Dconnectedapp.client.secret="2Da6676dad64640B265D9Cc35830478" \
 -Dap.client.id="5e09b8bf52394797b5035978b74aee1" \
 -Dap.client.secret="D4dD12915E3D29d9aB436AA0849c519"
Links & Resources

Resources

✅ Session 9

Test your Mule app with MUnit

About

Everything discussed in the Twitch live sessions for MuleSoft beginners.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published