Friday, October 16, 2020

Http Api - Mock / Redirect tool

 Http API - Mock Redirect is a light weight developer tool, I recently developed.  

Purpose of the Tool:

  1. When we may want to route urls to different hosts (say Dev, Test, Stage env). For ex a url of app may be routed to a host, another url of same app can be routed to different host. It can be configured  at http method as well
  2. When we may want to mock the response rather than calling the actual service/host
  3. This tools also provides view of all request/response processed

How does it work:

The tools starts a http server on configured local port, and will listen to any incoming request. Based on the url mapping configuration (will see later in the section) it will decide whether the request has to routed to the external endpoint or mock response to be sent. 


How to make it work:

Installation:

1.  Java/Jre 8 or above is installed

2. Download the api-mock-redirect-1.0.0.jar from github , and save it in a local folder. It is executable jar - double click to open the tool.

2. Email support@lite-bean.com


Url Mapping - Configuration

1. Provide a config name (config can be later loaded, so give some meaningful name)

2. Provide the local port, where tool should listen to any incoming http request. (port > 5000 -  is preferred. As initial set of ports are reserved for other purpose) 

3. Configure the url for which tool needs to redirect or mock. The url should start from context, and should be valid regex string. For ex: 

       a. users/.* - will handle all request starting with users/

       b. user/[0-9]* - will handle all request for users/<userid>

4. Configure http method, default is * - to support all methods, you may also select any method

5. Configure the option - i.e., Redirect/Mock  (by default it is redirect).

6.  Click edit/pencil icon, which will display fields to configure redirect/mock details. 

In the below example, i have configured an url for "api/v1/employee/<empl_id_numeric>"








Redirect - Configuration

1. Select Protool - Both http & https are supported

2. Enter the host name

3. Enter the port - at which the host is serving the request. (for https it may be 443, for http it may be 80 or 8080)

In the below example, I have configured the redirect to "https://dummy.restapiexample.com/"


Url Mapping 2 - Configuration

On click of "+" will create another row in url mapping, where next url can be configured.

Here I have configured my next url for "api/v1/employees"






Lets add another url to demonstrate mock feature, select Mock option 


Mock- Configuration

1. Configure Response 

2. Type in response headers (click + to add more headers)

3. Enter response body




Save & Monitor Urls

After all above configuration, click Save & Start Service button, which will start the service on configured port and listen to any incoming request. Incoming request will be logged in the tool.

Here the service is started at http://localhost:5001





Demo URL1 - Redirect


Url - http://localhost:5001/api/v1/employees 
Expected output - it should redirect to  "https://dummy.restapiexample.com/api/v1/employees" and fetch the result.

Here we have got the response as expected



Demo URL 2 - Redirect - power of regex


Url - http://localhost:5001/api/v1/employee/1
Expected output - it should redirect to  "https://dummy.restapiexample.com/api/v1/employee/1" and fetch the result.

Here we have got the response as expected


Demo URL 3 - Mock


Url - Mock url is configured as /api/* - so we will have v2, so that it wont qualify for first two urls - "http://localhost:5001/api/v2/employees"

Expected output - it should return mock output.

Here we have got the response as expected

Logs:

As shown below, all request / response will be logged in the tool - on click on any row will display req/response details (including all headers)





Other Features:

1. Service Stop &Close: click "Stop &Close" button on the listening page, to stop the service, and close the tab
2.  Load Saved Configuration:  Now the config is saved, it can be loaded anytime again - all the existing configuration can be reused.


Notes:

1. This is not limited to REST. SOAP over http can also be handled 

2. This tool is not limited to GET. All http options are supported and can be configured

3. Some understanding of REGEX is required to configure url

4. Url Mapping and request headers requires the cell is keyed in out 

5. Any click on edit, remove, add will automatically save the current state of config

6. If no matching url configured, tool will return "404 - resource not found"

7. For redirect - Few request headers (Content-length, Accept-encoding & Host)  are excluded. This can be overriden by adding a file "lb/repo/ignoreRedirectHeaders". Ensure all headers needs to be excluded need to be added here.



Hope this tool will be useful one. Do let me know your feedback/comments.




Friday, April 3, 2020

Structural Patterns: Bridge Vs Adapter Vs Decorator

Structural Patterns: Bridge Vs Adapter Vs Decorator

In this article we will look at Bridge, Adapter & Decorator pattern:

Bridge: Used to bridge two compatible interfaces
Adapter: Deals with two incompatible interfaces
Decorator: Enhance the same interface, such a way the existing object is not impacted


Bridge:

This pattern can be used when we want to bridge/combine two interface/subsystem 

For example Car and Registration are two subsystem, and RegisteredCar bridges both.


Adapter:

This pattern can be used to deal with two incompatible interface/subsystem. Adapter makes things work after they are designed.

For ex: Driver drives Car, now if we want to make driver drives auto?
AutoAdapter ensure driver actions (start, stop) are converted to auto operation (on/off)



Decorator:

This pattern enhances an object, without changing its interface

For example, Honda, Maruti can be enhanced to Sport Car without modifying Car/Maruti/Honda
With this SportCar can be built/enhanced over Maruti/Honda or any Car otherwise we might have built separate class says HondaSportCar & MarutiSportCar.




Hope this was useful one, if you have any question/comment, please comment below, i will try to answer my best. Thank you!

Wednesday, February 12, 2020

Stored procedure (SQL server) Notes


Stored procedure is a sql code or set of sql, which is saved in server side, and can be executed  as many times. We can pass run time parameters to stored procedure. Below are the some of the basic things to write a stored procedure:


  • Create stored procedure
  • Logging
  • Variables
  • Iteration
  • Transaction/Exception Handling


Create Stored Procedure:

CREATE PROCEDURE updateLocality @State nvarchar(50), @City nvarchar(30), @PostalCode  nvarchar(10), @Locality nvarchar(50)
AS
update Employee
set locality=@Locality
where state = @State and city=@City and postalCode=@PostalCode;
GO;

Execute Procedure:

EXEC updateLocality @State='TN' @City = "Chennai", @PostalCode = "600053" @Locality = 'Ambattur'; 

The procedure takes four input parameters (State, City, PostalCode, Locality) and update the locality for those matching state, city and postalcode.

Logging:

1.  First, to log the db response for the sql execution:
SET NOCOUNT OFF;
This logs the db response, for ex: no. of rows updated. This is switched off for debugging/demo purpose but it is always a best practice to switch on to avoid unnecessary log


2. Print execution log, something developer log as info
This can be done using PRINT or RAISE ERROR. The drawback with print seem it will be printed only after the script is executed whereas RAISE ERROR can log it during execution itself

Print 'Execution started'; -- self explanatory

RAISERROR('Execution started',0,1) WITH NOWAIT; 
  • The first parameter is the message to display, 
  • second is the error level, it treats anything with an error level from 0-10 as a message and does not affect code execution
  • third is the system state. This ranges from -1 to 255 and anything outside of that results in an exception 
  • WITH NOWAIT allows the immediate message output describing how the script is executing as it happens

Variables:

DECLARE @Message VARCHAR(100) = 'Welcome to Stored Procedure';
--initialize a local variable Message
--VARCHAR is the datatype/string for message. It can be of any supported datatype
Sqlserver does not support array of values, but we can do is
declare @listOfIDs table (id int);
insert @listOfIDs(id) select ID from Employee where state = @State and city=@City and postalCode=@PostalCode;
--This stores all matching employee id into listOfIDs

Iteration: 

Cursor: Helps us iterate over result set

DECLARE @CustomerId INT, @FirstName VARCHAR(30), @LastName VARCHAR(50)
DECLARE @MessageOutput VARCHAR(100)
DECLARE Customer_Cursor CURSOR FOR
    SELECT CustomerId, FirstName, LastName FROM Customers

OPEN Customer_Cursor
FETCH NEXT FROM Customer_Cursor INTO
    @CustomerId, @FirstName, @LastName
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @MessageOutput = @FirstName + ' ' + @LastName
    RAISERROR(@MessageOutput,0,1) WITH NOWAIT
    FETCH NEXT FROM Customer_Cursor INTO
    @CustomerId, @FirstName, @LastName
END
CLOSE Customer_Cursor
DEALLOCATE Customer_Cursor

Transaction/Exception Handling: 

 By default, all sqls with in the procedure is executed independently, incase of any failure in any sql will not rollback the data. Transaction helps us to execute multiple sqls in a single transaction

CREATE PROCEDURE updateLocality @State nvarchar(50), @City nvarchar(30), @PostalCode  nvarchar(10), @Locality nvarchar(50)
AS
SET NOCOUNT OFF;
BEGIN
    BEGIN TRANSACTION;
    SAVE TRANSACTION OldStateSavePoint;
    BEGIN TRY
    RAISERROR('Execution started state: %s, city: %s, postalcode: %s, locality:%s',0,1, @State, @City, @PostalCode, @Locality) WITH NOWAIT;
    -- update employees
    update Employee
set locality=@Locality
where state = @State and city=@City and postalCode=@PostalCode;
RAISERROR('Employee table updated',0,1) WITH NOWAIT;
--some other sqls
RAISERROR('Table2 updated',0,1) WITH NOWAIT;
-- more
    END TRY
    BEGIN CATCH
    RAISERROR('Rollback - state: %s, city: %s, postalcode: %s, locality:%s',0,1, @State, @City, @PostalCode, @Locality) WITH NOWAIT;
    ROLLBACK TRANSACTION OldStateSavePoint;
    END CATCH
   
update Employee
set locality=@Locality
where state = @State and city=@City and postalCode=@PostalCode;
END;
GO
This ensures the transaction is rolledback incase of any failures


References:

https://www.w3schools.com/sql/sql_stored_procedures.asp
https://docs.microsoft.com/en-us/sql/t-sql/statements/create-procedure-transact-sql?view=sql-server-ver15
http://structuredsight.com/2014/11/24/wait-wait-dont-tell-me-on-second-thought/
https://stackoverflow.com/questions/2622230/how-can-i-iterate-over-a-recordset-within-a-stored-procedure
https://dba.stackexchange.com/questions/134129/transaction-in-a-stored-procedure