TravelZoom- Mule Integration With Everyday API's
Tags: mulesofthackathon, angular, node, css
Published: 2020-11-29 03:31:50

##Overview

This concept is all about how Mule API-Led connectivity can be extensively utilized to create an application network of MuleSoft APIs. TravelZoom can be used by the people in the UK, who use train services as the mode of transportation for going to their workspace, shopping or even on a vacation. The application provides users with the facilities of registering with the system, and once successfully registered the user can search for the trains routed through a specified source and destination location for a given time period. The search for trains can be done using postcodes as well. That's not all, along with this considering the Covid-19 situation, and travel well being of the user this application also includes the features such as- providing Covid-19 updates for the destination location, the weather conditions, links to the local food sources including restaurants and grocery stores, and as a cherry on top any delays in the subscribed train journey will be notified prior to a user-configured time on the day of travel. This additional information gives a heads up to the user to plan his journeys well in advance considering his/her time and safety.
</p>
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ahy28iwy02acszc9c6e2.PNG)
######<figcaption>Figure 1: High Level Design Diagram</figcaption>

##Technical Design Diagrams
###Use Case Diagram
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ony6g72xopfo8slenwew.PNG)
######<figcaption>Figure 2: Use Case Diagram</figcaption>

###Architecture Diagram
  <U>Layered Viewpoint- MyTrains Service</U>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pynkdfzmvysz7qq02pzw.png)
######<figcaption>Figure 3.1: Architecture Diagram- Layered Viewpoint For MyTrains Service</figcaption>
 <U>Layered Viewpoint- Customer Notification Service</U>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0jfsoftrzw648qlkmedc.png)
######<figcaption>Figure 3.2: Architecture Diagram- Layered Viewpoint For Notification Service</figcaption>

###Sequence diagram
<u>Process View- MyTrains Service</u>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/q1nsrzo0xy4h0rjbm8ve.jpg)
######<figcaption>Figure 4.1: Sequence Diagram- Process View For MyTrains Service</figcaption>
<u>Process View- Customer Notification Service</u>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7v1i85rm641cmd89aic6.jpg)
######<figcaption>Figure 4.2: Sequence Diagram- Process View For Customer Delay Notification Service</figcaption>

###ER Diagram for TravelZoom Database

![ER Diagram](https://dev-to-uploads.s3.amazonaws.com/i/30vi0wdtcd6get92agib.JPG)

##User Experience (UI)
The front-end application is created using Angular 11, Bootstrap, ng2-charts for displaying covid and css3. 
Users can search on the basis of Source, Destination and Travel date. In the Source, location can be either a Location name or a postal code. Same is applies for the Destination. For the travel date, we have to specify the date of travel.

Then two tabs in UI Travel and NearBy shows the weather, Covid cases in different regions and train services from the source to destination are displayed.

Below are the screenshots of UI exhibiting the explained features, which has been enclosed using RED rectangular boxes.
      
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9vljcsr34mxl0a8gbnjy.JPG)
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5ai4xlmbo7deh1fl5vm7.JPG)

---
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/96m4rhhn7ahbn6eyyu2g.JPG)
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uprp6n58mgxxd43wehee.JPG)
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1qdxl1n4qfs5iax997t6.JPG)
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/p9dfd9uujyw02shk3vvp.JPG)
---

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/v0ezaoqvh98pge6cej63.JPG)

**Note**: The UI has been integrated with the following endpoints from experience API:
- /myTravel/locations/stations
- /myTravel/locations/stations/trains
- /myTravel/locations/forecast
- /myTravel/locations/attractionspots
- /myTravel/locations/covid
- /myTravel/locations/covid/areaname

Rest of the endpoints are fully functional and can be tested using any API testing tool. The UI integration with the remaining APIs is moved to future extension scope.

##MuleSoft Implementation
The MuleSoft implementation for the TravelZoom is designed following the API-Led connectivity approach, having the APIs created in the Experience Layer, Process Layer and System Layer based on their functionality and integration with external systems.
###Experience Layer
The NodeJs front-end application integrates with the myTravel Experience API, which exposes REST endpoints for managing User(s) in the system, the Subscriptions for train services to multiple locations during a specific time period. Endpoints for retrieving location data, covid case count, and weather forecast.  Below are the resources exposed by the Exp API to the external world:

* /register:

    + POST- endpoint for creating a new user initially creating a user account in Okta for single sign-on, followed by saving the user details into the application database.
* /login:

    + POST- endpoint for a registered user to login into the application by providing Username and Password.
* /forgotPassword:

    + POST- accepts customer email as payload for initiating a password reset, for which the link would be sent to the provided email address.
* /myTravel/users/{userId}:

   + GET- Get user details by user Id.
* /myTravel/users/{userId}/subscriptions:

   + GET- Get all Subscriptions for a specific user.
* /myTravel/users/{userId}/subscriptions:

   + POST- Create subscription for trains routed between given two locations in given time window.
* /myTravel/users/{userId}/subscriptions/{subscriptionId}:

   + GET- Retrieve subscription details for a particular train service for the selected user.
* /myTravel/users/{userId}/subscriptions/{subscriptionId}:

   + DELETE- Unscubscribe to a service that a user has subscribed to.
* /myTravel/locations/stations:

    + GET- Returns a list of all stations and codes. 
* /myTravel/locations/stations/trains:

    + GET- Fetches train services between source and destination location on a particular date. 
* /myTravel/locations/forecast:

    + GET- Provides weather forecast for the selected date and location.
* /myTravel/locations/attractionspots:

    + GET- Retrieves restaurants, tourist and cinema spots near a location.
* /myTravel/locations/covid:

    + GET- Get all COVID-19 case details for entire UK.
* /myTravel/locations/covid/areaname:

    + GET- Get COVID details for UK by Area name

####RAML Specification For Experience API
Below is the RAML specification for the experience API that provides a detailed representation of the methods, request and response structures with examples for each REST endpoint. 
```
#%RAML 1.0
title: myTravel Experience API
version: v1

mediaType:
  - application/json

protocols:
  - HTTP

traits: 
  responseMessage: !include /resources/traits/error-trait.raml

uses:
  myTrains: /exchange_modules/cd5bf5d6-a7c5-40f7-a8db-9f1046bbc2fd/mytrains-datatype-library/1.0.10/mytrains-datatype-library.raml
  locations: /exchange_modules/cd5bf5d6-a7c5-40f7-a8db-9f1046bbc2fd/locations-data-type-library/1.0.4/locations-data-type-library.raml


types:
  user: myTrains.user
  subscription: myTrains.subscription
  token: myTrains.token
  station: myTrains.station
  forecast: locations.forecast
  attractionSpots: locations.attractionspots
  covidbyregion: locations.covidbyregion
  covidbyarea: locations.covidbyarea
  stationLocation: locations.stationLocation
  trainService: myTrains.trainService
  alertData: myTrains.alert

/myTravel:
  displayName: myTravel
  
  /register:
    displayName: Register User
    description: Used to register and update user
    post:
      is: [ { responseMessage: { messageReference : Error registering user. } } ]
      displayName: Register
      description: Register new user.
      body:
        application/json:
          displayName: Registered User Details
          description: User details to store in database.
          type: user
          example: !include /resources/examples/register-input-example.raml
      responses:
        201:
          description: Success
          body:
            application/json:
              example:
                message: User registered successfully.
  /login:
    displayName: Login
    post:
        description: This method is used to create token for login details
        body:
          application/json:
            type: object
            example:
                    strict: true
                    value:
                      email: train.alerts@alert.com
                      password : "testpass"
        responses:
          "500":
            body:
              type:
                type: any
          "201":
            body:
              type: token
              examples:
                output: !include /resources/examples/token-example.raml
          "400":
            body:
              type:
                type: any
  
  /forgotPassword:
    displayName: Forgot Password
    description: Forgot Password operation
    post:
      is: [ { responseMessage: { messageReference : Error resetting password. Try again later. } } ]
      displayName: Forgot Password
      description: Forgot Password
      body:
        application/json:
          displayName: Username
          description: Username of the customer.
          type: string
          examples:
            output: "jane.doe@example.com"
      responses:
        201:
          description: Success
          body:
            application/json:
              example: "https://dev-462737.okta.com/signin/reset-password/XE6wE17zmphl3KqAPFxO"
  
  /users:
    displayName: Users
    /{userId}:
      displayName: User ID
      description: Used for logged in user operations
      get:
        is: [ { responseMessage: { messageReference : User ID retrieval unsuccessful. } } ]
        displayName: Get User
        description: Retrieves user details
        responses:
          200:
            description: Success
            body:
              application/json:
                type: user
                examples:
                  output: !include /resources/examples/userDetailsExample.raml
    
      /subscriptions:
        displayName: Subscriptions
        description: Subscription to train services between two locations in particular time window.
        get:
          is: [ { responseMessage: { messageReference : Error retrieving all subscriptions. } } ]
          displayName: Get All Subscriptions
          description: Get details of all subscriptions for given user
          responses:
            200:
              description: Success
              body:
                application/json:
                  type: subscription[]
                  examples:
                    output: !include /resources/examples/all-subscriptions-example.raml
        
        post:
          is: [ { responseMessage: { messageReference : Error creating subscription. } } ]
          displayName: Create Subscription
          description: Create subscription for trains between given two locations in given time window
          body:
            application/json:
              displayName: Subscription details
              description: Details of location, time window and advance notification time for subscription.
              type: subscription
              examples:
                input: !include /resources/examples/create-subscription-input-example.raml
          responses:
            201:
              description: Success
              body:
                application/json:
                  example:
                    message: Successfully created subscription.

        /{subscriptionId}:
          displayName: Subscription ID
          get:
            is: [ { responseMessage: { messageReference : Error retrieving subscription details. } } ]
            displayName: Get Subscription Details
            description: Get details of subscription with given ID
            responses:
              200:
                description: Success
                body:
                  application/json:
                    type: subscription
                    examples:
                      output: !include /resources/examples/subscription-details-example.raml
          
          delete:
            is: [ { responseMessage: { messageReference : Error deleting subscription. } } ]
            displayName: Unsubscribe
            description: Unsubscribe to a subscription
            responses:
              200:
                description: Success
                body:
                  application/json:
                    example:
                      message: Successfully deleted subscription.

              202:
                description: Accepted
                body:
                  application/json:
                    example:
                      message: Subscription queued to be deleted.

              204:
                description: Success. No content to display.

  /locations:
    displayName: Locations

    /stations:
      displayName: Stations
      get:
        displayName: Get all Stations
        description: Returns list of all stations and codes
        responses:
          200:
            description: Success
            body:
              type: station[]
              examples:
                output: !include /resources/examples/station-list-example.raml

      /nearby:
        displayName: Near By Station
        get:
          is: [{ responseMessage: { messageReference : Error retrieving stations nearby. } }]
          displayName: Get nearby stations
          description: Fetches the nearby stations with station codes and post code
          queryParameters:
            address:
              displayName: address
              description: Post code or Location Name
              example: "DE21"
              type: string
          responses:
            200:
              description: Success
              body:
                type: stationLocation[]
                examples:
                  output: !include /resources/examples/nearby-stations-example.raml
      
      /trains:
        displayName: Trains
        get:
          is: [{ responseMessage: { messageReference : Error retrieving trains services. } }]
          displayName: Get trains
          description: Fetches train services between source and destination location on a particular date
          queryParameters:
            origin:
              displayName: Origin Station
              description: Origin Station
              example: "London St Pancras International"
              type: string
            originType:
              displayName: Origin Type
              description: Origin Type
              example: "P"
              type: string
            destination:
              displayName: Destination Station
              description: Destination Station
              example: "Looe"
              type: string
            destType:
              displayName: Destination Type
              description: Destination Type
              example: "L"
              type: string
            travelDate:
              displayName: Travel Date
              description: Travel Date
              example: 2020-11-27
              type: date-only
          responses:
            200:
              description: Success
              body:
                type: trainService[]
                examples:
                  output: !include /resources/examples/json/train-service-response.json
    
    /forecast:
      displayName: Forecast
      get:
        is: [{ responseMessage: { messageReference : Error fetching weather forecast. } }]
        displayName: Get Forecast
        description: Gives forecast for following five days
        queryParameters:
          city: 
            displayName: City Name 
            description: City Name
            example: "New York"
            type: string
          date:
            displayName: Date
            description: "5 days forecast is provided including current day (dateformat- 'yyyy-MM-dd')"
            example: "2020-11-23"
            type: string
          countryCode:
            displayName: Country Code
            description: Country code as query parameters like us, uk…. e.t.c.
            example: "us"
            type: string
            required: false
          units: 
            displayName: units
            description: Units like metric, imperial and standard as default
            type: string
            required: false
        responses:
          200:
            description: Success
            body:
              type: forecast
              examples:
                output: !include /resources/examples/json/forecast-response-example.json
    
    /attractionspots:
      displayName: Attraction Spots
      get:
        is: [ { responseMessage: { messageReference : Error fetching attraction spots. } } ]
        displayName: Get attraction spots
        description: Retrieves restaurants, tourist and cinema spots near a location
        queryParameters:
          city:
            description: name of the place/city
            type: string
            required: true 
            example:
              new york
        responses:
          200:
            body:
              application/json:
                type: attractionSpots
                examples:
                  output: !include /resources/examples/json/attraction-spots-response-example.json
    
    /covid:
      displayName: COVID Update
      get:
        is: [ { responseMessage: { messageReference : Error fetching COVID updates. } } ]
        displayName: Get Update
        description: Get all COVID details for UK
        responses:
          200:
            body:
              application/json:
                example:
                  output: !include /resources/examples/covid-by-region-example.raml
      
      /areaname:
        displayName: COVID Update By Area
        get:
          is: [ { responseMessage: { messageReference : Error fetching COVID updates. } } ]
          displayName: Get Update by Area
          description: Get COVID details for UK by Area
          responses:
            200:
              body:
                type: object[]
                examples:
                  output: !include /resources/examples/json/covid-by-area-example.json
```
###Process Layer
The njc-mytravel-experience-api invokes the following 2 process APIs:
1. <u>mytrains-process-api</u>: Supports CRUD operations on users or service subscriptions. 
2. <u>notification-process-api</u>: Checks and notify the users about the delays in train service, retrieving train and station details, location details, weather forecast and Covid case count based on location and date.

For more information on the endpoints for the process APIs please refer the RAML specification in Git: https://github.com/smeghakumar/RAML.git
    

###System Layer
The System APIs share a bounded context with the external systems the communicate with and hence we one System API per external system entity.

The mytrains-process-api invokes the following system APIs:
1. <u>mytrains-system-api</u>: This API communicates with the MySQL database to perform:
  * An INSERT, UPDATE and DELETE operations on the user and user subscriptions, 
  * INSERT alert details, 
  * INSERT and SELECT operation on railway station details
2. <u>okta-system-api</u>: Okta API is used for enabling single sign-on for the travelzoom users. The core operations of this API include:
  * Creates a user in Okta
  * Authenticate and Authorize Users
  * Forgot password option for a password reset
  * Deactivate user
3. <u>nre-system-api</u>: The system API checks for delays in train services for the immediate 60 minute time frame and notifies the users by sending Emails. This is done by comparing the actual arrival train time and estimated arrival time from the train details retrieved from the external NationalRail API. The two operations can be summarized as:
  * Fetch all station codes and station names
  * Get services for provided origin, destination and date
4. <u>train-details-system-api</u>: Retrieves train details such as- arrival and departure time, source and destination locations, train number, and total duration for the journey.

The notification-process-api invokes the following system APIs:
5. <u>delay-notification-system-api</u>: It connects with the MySQL database tables for retrieving the Subscriptions details whose train time falls between the 60-minute window from that moment. 
6. <u>location-system-api</u>: Provides the information about the currently available or open set of nearby stations, leisure-spots and set of postal codes based on the postal code or station names passed as the query parameter.
7. <u>covid-system-api</u>: Retrieves the COVID-19 case details for the provided city.
8. <u>weather-system-api</u>: Returns weather forecast for the date and location provided as the query parameters.

     

##Project Setup Prerequisites and Instructions
<u>UI</u>
* Install NodeJs from https://nodejs.org/en/.
* Google Chrome is recommended for better UI experience or any browser with a resolution 2560 x 1600.
* Install  Git on to your machine (if not already installed), following the instructions on https://github.com/git-guides/install-git.
* Open Command prompt and change directory to the folder where you want to clone the project into your machine, followed by executing the git command:
`git clone https://github.com/smeghakumar/travelzoom.git`.</center>

![Clone repository](https://dev-to-uploads.s3.amazonaws.com/i/132dj9dr3xtw4igyjvxh.JPG)
* Change your directory to the project folder and execute the command: `npm install`.

![npm install](https://dev-to-uploads.s3.amazonaws.com/i/qd0je6z93vpf7lsxvo75.JPG)
* Execute the command: `npm start`. This will start the NodeJs front-end application.

![npm start](https://dev-to-uploads.s3.amazonaws.com/i/vy0a1palvhwzfj9hj6fo.JPG)
![npm start successful indicator screen](https://dev-to-uploads.s3.amazonaws.com/i/bq1r4v6f03ah9d7ybfsx.JPG)
* Launch the web browser and enter the locally running application URL http://localhost:4200/.

![Website for TravelZoom](https://dev-to-uploads.s3.amazonaws.com/i/ac61uz3mba7bfv8t3pk2.JPG)
<u>MuleSoft</u>
* MuleSoft Anypoint Platform account for publishing assets and deploying Mule applications.


**Note**: All the calling points to the external systems have been mocked with the help of a Mule mocking API which replicates the request and response structure similar to the actual service. The URLs for the actual external services are commented in the configuration YAML file. This is because most of them are free only for a month and then requires a subscription for extended usage.

To test from UI please use the below-listed combination of origin-destination location name combinations or equivalent combinations replacing with the provides postal codes:
#####Location Names
| Origin Location        | Destination Location   |
| -------------          |:-------------:         |
| Leeds                  | London Waterloo        | 
| Woking                 | Leeds                  | 
| Leeds                  | Basingstoke            | 
|Basingstoke             | Leeds                  |  
|London Waterloo         | London St Pancras (Int)|
|London Waterloo         | Leeds                  |
|London St Pancras (Int) |Woking                  |
|Basingstoke             |Woking                  |
|London St Pancras (Int) |Leeds			  |
|London St Pancras (Int) |London Waterloo         |

#####Postal codes
| Location      |Postcode |Location   |Postcode |  
| ------------- |:-------:|:-------:  |:-------:|
|London WaterLoo| SE1 8SW |Basingstoke|RG21 7EB |
|London WaterLoo| SE1 8SW |Basingstoke|RG21 7LW |
|London WaterLoo| SE1 7RJ |Basingstoke|RG21 7JT |
|London WaterLoo| SE1 7RY |Basingstoke|RG21 7DW |
|London St Pancras (Intl)| N1C 4|Basingstoke|RG22 5NZ|
|London St Pancras (Intl)| N1C 4QP|Leeds|LS1 6AL|
|London St Pancras (Intl)| NW1 2QS|Leeds|LS2 8DZ |
|London St Pancras (Intl)| N1C 4AP|Leeds|LS2 7HY |
|London St Pancras (Intl)| N1 9NW|Leeds|LS1 1PJ |
|Woking| GU21 4LL|Leeds|LS2 7AU |
|Woking| GU22 7AE|Woking|GU22 7AA |
|Woking|GU21 6XR|





<u>MySQL Database</u>
* Execute the Database scripts for table creation available at https://github.com/smeghakumar/Database-Scripts.git




##Conclusion
*"If you don't know where you are going. How can you expect to get there?"* <Center>~ Basil S. Walsh</Center> 
Start your journey from the destination before you start from your home. Get all the details of the destination using the TravelZoom and plan the travel accordingly. The collection of API’s brings the information’s to your mobile screen whenever and where ever you wanted.

##Future Scope
Future additions in the project pipeline are as follows:
* Integrating with IoT devices and creating an internet-based Smart Home automation system.
* Log externalization to Splunk/ELK
* Advanced error handling, and Incident notification layer for the whole system.
* Integrating more of Everyday APIs.

*“You'll never reach perfection because there's always room for improvement. Yet get along the way to perfection, you'll learn to get better.”* <Center>~ Hlovate</Center>
Hope the above quote well explains my thoughts on future extension and enhancements to the project.
##References
####Git Repository Links
* UI Application: https://github.com/smeghakumar/travelzoom.git
* MuleSoft Implementations: https://github.com/smeghakumar/MuleSoft-APIs.git
* RAML Specifications: https://github.com/smeghakumar/RAML.git
* Database Scripts: https://github.com/smeghakumar/Database-Scripts.git