Sunday, May 9, 2021

Ktor Kotlin Backend Development with MySql Database Demo Project - Mobile Development

Kotlin-Ktor-MySql-Webservice Development

GitHub Full Source Code:
https://github.com/Abhinaw/nearbyapi_abhi/tree/master

I was getting demand for Ktor Kotlin Backend Development with Sample MySql Database Code So in this blog I will give you all full access to the source code on my Github URL.

SQL file is also committed to the parent folder and you can easily import and configure the project.

Why Ktor?

Use what you need. Ktor allows you to transparently configure only the functionality your project requires. No magic involved!

Extensible

Extend what you need. With a configurable pipeline, you can create the extensions you need and place them anywhere you want.

Multiplatform

Run it where you need it. Built from the ground up with Kotlin Multiplatform technology, you can deploy Ktor applications anywhere.

Asynchronous

Scales as you need it. Using Kotlin coroutines, Ktor is truly asynchronous and highly scalable. Use the power of non-blocking development without the callback nightmare.

Java Threads Vs Kotlin Coroutines 

I myself as a programmer/developer I tested it by writing code that's what I do. I read somewhere that Courotines is much better than Java threads I did not believe it initially but to test it I did one thing like I have an 8GB RAM Multi-core Windows operating system. 

To test it, I wrote a simple Java and Kotlin Program where what i did is like created 100 threads from Fork/Join Pool of threads and the same concept with Kotlin Coroutines and the result was amazing to me. 

In the case of Java, my system got crashed and it consumes my all resources when I checked my task manager it was consuming 100% of my system but in the case of Coroutines with the same program, it only consumed my 80% resource and that is an amazing part to me and even the program did not crash. this makes me a little uncomfortable worked on Java for more than 10 years till now and maybe it proves how powerful Kotlin is. As a developer/programmer I believe it because I checked it by doing my hands dirty with it.

Thoughts for Food for Android Developers:

I strongly believe that it will take time to improve like Spring Eco-System but I find it very useful in terms of Mobile Application Development because in every mobile app we need middle-tier for data transaction and there it saves like earlier for that Mobile Developer can not cater that requirement but now they can easily cater the same because they can write the required code for Middle-Tier certainly Android Developers.

And there is one more advantage that I can see is like you can create a single project structure to care both the platforms I mean Front-End and Middle-Tier, Yes there can be an architectural difference but indeed very help full when it comes to CI/CD.

Ktor is a framework to easily build connected applications – web applications, HTTP services, mobile and browser applications. Modern connected applications need to be asynchronous to provide the best experience to users, and Kotlin coroutines provide awesome facilities to do it in an easy and straightforward way.

While not yet entirely there, the goal of Ktor is to provide an end-to-end multiplatform application framework for connected applications. Currently, JVM client and server scenarios are supported, as well as JavaScript, iOS, and Android clients, and we are working on bringing server facilities to native environments, and client facilities to other native targets.

When you create a project in IntelliJ IDE:

Name: Specify a project name.

Location: Specify a directory for your project.

Build System: Choose the desired build system. This can be Gradle with Kotlin or Groovy DSL or Maven.

Website: Specify a domain used to generate a package name.

Artifact: This field shows a generated artifact name.

Ktor Version: Choose the required Ktor version.

Engine: Select an engine used to run a server.

Configuration in: Choose whether to specify server parameters in code or in a HOCON file.

On the next page, you can choose a set of features- building blocks that provide common functionality of a Ktor application, for example, authentication, serialization, and content-encoding, compression, cookie support, and so on.

application.conf:

ktor {

    deployment {

        port = 8080

    }

    application {

        modules = [ com.jetbrains.handson.chat.server.ApplicationKt.module ]

    }

}

Application.Kt:

package com.abhinearby

import com.fasterxml.jackson.databind.SerializationFeature

import io.ktor.application.*

import io.ktor.features.*

import io.ktor.gson.*

import io.ktor.http.*

import io.ktor.http.cio.websocket.*

import io.ktor.jackson.*

import io.ktor.request.*

import io.ktor.response.*

import io.ktor.routing.*

import io.ktor.websocket.*

import org.slf4j.event.Level

import java.util.*

import kotlin.collections.LinkedHashSet

fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

@Suppress("unused") // Referenced in application.conf

@kotlin.jvm.JvmOverloads

fun Application.module(testing: Boolean = false) {

    install(WebSockets)

    install(CallLogging) {

        level = Level.INFO

        filter { call -> call.request.path().startsWith("/") }

    }

    install(ContentNegotiation) {

        gson {

            setPrettyPrinting()

        }

        jackson {

            enable(SerializationFeature.INDENT_OUTPUT)

        }

    }

 routing {

        /* For only Testing*/

        get("/json/jackson") {

            call.respond(mapOf("hello" to "world"))

        }

        /********************Near By App Start*********************/

        val repository: RegistrationRepository = MySqlRegistrationToDoRepository()

        post("/registration")

        {

            val todoDraft = call.receive<RegistrationDraft>()

            val todo = repository.addToRegistrationTable(todoDraft)

            call.respond(todo)

        }

        get("/getallregistrationdata")

        {

            call.respond(repository.getAllRegisteredTableData())

        }

        put("/registration/{id}")

        {

            val todoDraft = call.receive<RegistrationDraft>()

            val todoId = call.parameters["id"]?.toIntOrNull()

            if (todoId == null) {

                call.respond(HttpStatusCode.BadRequest, "id  parameter has to be a number!")

                return@put

            }

            val update = repository.updateToRegistrationTable(todoId, todoDraft)

            if (update) {

                call.respond(HttpStatusCode.OK)

            } else {

                call.respond(HttpStatusCode.NotFound, "registered user with the id $todoId not found")

            }

        }

        /**************Login********************/

        val loginRepo: LoginRepository = MySqlLoginToDoRepository()

        post("/login")

        {

            val todoDraft = call.receive<LoginDraft>()

            val todo = loginRepo.validateToLoginTable(todoDraft)

            call.respond(todo)

        }

        get("/getlogindata")

        {

            val repository: LoginRepository = MySqlLoginToDoRepository()

            call.respond(repository.getAllLoginTableData())

        }

        ///////////////////////////Websocket Chat System////////////////////////////

        val connections = Collections.synchronizedSet<Connection?>(LinkedHashSet())

        webSocket("/chat") {

            println("Adding user!")

            val thisConnection = Connection(this)

            connections += thisConnection

            try {

                send("You are connected! There are ${connections.count()} users here.")

                for (frame in incoming) {

                    frame as? Frame.Text ?: continue

                    val receivedText = frame.readText()

                    val textWithUsername = "[${thisConnection.name}]: $receivedText"

                    connections.forEach {

                        it.session.send(textWithUsername)

                    }

                }

            } catch (e: Exception) {

                println(e.localizedMessage)

            } finally {

                println("Removing $thisConnection!")

                connections -= thisConnection

            }

        }

        /////////////////////////////////////Chat////////////////////////////

    }

}

DatanbaseManager.Kt:


package com.abhinearby.database

import org.ktorm.database.Database

import org.ktorm.dsl.eq

import org.ktorm.dsl.insertAndGenerateKey

import org.ktorm.dsl.update

import org.ktorm.entity.sequenceOf

import org.ktorm.entity.toList

import java.sql.Connection

class DatabaseManager {

private val hostname = "127.0.0.1"

    private val databaseName = "nearby_abhi"

    private val username = "root"

    private val password = ""

    private val ktormDatabase: Database

    init {

        val jdbcUrl = "jdbc:mysql://$hostname:3306/$databaseName?user=$username&password=$password&useSSL=false"

        ktormDatabase = Database.connect(jdbcUrl)

    }

    /************Registration for the App*************/

    fun addRegistrationDataToDB(draft: RegistrationDraft): Registration {

        val insertedId = ktormDatabase.insertAndGenerateKey(DBRegistrationTable)

        {

            set(DBRegistrationTable.firstname, draft.firstname)

            set(DBRegistrationTable.lastname, draft.lastname)

            set(DBRegistrationTable.phoneno, draft.phoneno)

            set(DBRegistrationTable.address, draft.address)

            set(DBRegistrationTable.photo, draft.photo)

            set(DBRegistrationTable.username, draft.username)

            set(DBRegistrationTable.password, draft.password)

        } as Int

        val registration = Registration(

            insertedId,

            draft.firstname,

            draft.lastname,

            draft.phoneno,

            draft.address,

            draft.photo,

            draft.username,

            draft.password

        )

        insertRow(registration)

        return registration

    }

    private fun insertRow(registration: Registration) {

        val id = registration.id

        val username = registration.username

        val password = registration.password

        val fid = registration.id

        val sql =

            "INSERT INTO `login`(`id`, `username`, `password`, `fid`) VALUES ('$id','$username','$password','$fid')"

        ktormDatabase.useConnection { connection: Connection ->

            with(connection) {

                createStatement().execute(sql)

            }

            println("inserted!!")

        }

    }

    fun updateRegistrationDataToDB(id: Int, draft: RegistrationDraft): Boolean {

        val updatedRows = ktormDatabase.update(DBRegistrationTable)

        {

            set(DBRegistrationTable.firstname, draft.firstname)

            set(DBRegistrationTable.lastname, draft.lastname)

            set(DBRegistrationTable.phoneno, draft.phoneno)

            set(DBRegistrationTable.address, draft.address)

            set(DBRegistrationTable.photo, draft.photo)

            set(DBRegistrationTable.username, draft.username)

            set(DBRegistrationTable.password, draft.password)

            where {

                it.id eq id

            }

        }

        return updatedRows > 0

    }

    fun getAllRegisteredTableData(): List<DBNearByRegistrationEntity> {

        return ktormDatabase.sequenceOf(DBRegistrationTable).toList()

    }

    /**************************Registration End*************************************/

    /************************Login **************************/

    fun validateLogin(draft: LoginDraft): LoginDraft {

        val table = "login"

        val sql = "SELECT * FROM $table"

        ktormDatabase.useConnection { connection: Connection ->

            val rs = connection.createStatement().executeQuery(sql)

            while (rs.next()) {

                println(

                    "id: ${rs.getInt("id")}\t" +

                            "username: $${rs.getString("username")}\t" +

                            "password: ${rs.getString("password")}\t" +

                            "fid: $${rs.getDouble("fid")}"

                )

                val userName = rs.getString("username")

                val pass = rs.getString("password")

                if (draft.username.equals(userName)

                    && draft.password.equals(pass)

                ) {

                    break

                }

            }

        }

        return draft!!

    }

    fun getAllLoginTableData(): List<DBNearByLoginEntity> {

        return ktormDatabase.sequenceOf(DBLoginTable).toList()

    }

}

Entity.kt:

import org.ktorm.entity.Entity

import org.ktorm.schema.Table

import org.ktorm.schema.int

import org.ktorm.schema.varchar

object DBRegistrationTable : Table<DBNearByRegistrationEntity>("dbregistrationtable") {

    val id = int("id").primaryKey().bindTo { it.id }

    val firstname = varchar("firstname").bindTo { it.firstname }

    val lastname = varchar("lastname").bindTo { it.lastname }

    var phoneno = varchar("phoneno").bindTo { it.phoneno }

    var address = varchar("address").bindTo { it.address }

    var photo = varchar("photo").bindTo { it.photo }

    var username = varchar("username").bindTo { it.username }

    var password = varchar("password").bindTo { it.password }

}

interface DBNearByRegistrationEntity : Entity<DBNearByRegistrationEntity> {

    companion object : Entity.Factory<DBNearByRegistrationEntity>()

    val id: Int

    val firstname: String

    val lastname: String

    val phoneno: String

    val address: String

    val photo: String

    val username : String

    val password : String

}

RegistrationRepository.kt:

import com.abhinearby.entities.registration.Registration

import com.abhinearby.entities.registration.RegistrationDraft

interface RegistrationRepository {

    fun addToRegistrationTable(draft: RegistrationDraft): Registration

    fun updateToRegistrationTable(id: Int, draft: RegistrationDraft): Boolean

    fun getAllRegisteredTableData() : List<Registration>

}

PostMan Webservcie Request-Response Example:

1)http://localhost:8081/getallregistrationdata

[
    {
        "id"29,
        "firstname""abhi",
        "lastname""tripathi",
        "phoneno""8130752107",
        "address""siddha happyville",
        "photo""",
        "username""abhi",
        "password""abhi"
    },
    {
        "id"30,
        "firstname""abhinawtripathi34@gmail.com",
        "lastname""tripathi",
        "phoneno""8130752107",
        "address""cyfydufffi",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"31,
        "firstname""abhinawtripathi34@gmail.com",
        "lastname""tripathi",
        "phoneno""8130752107",
        "address""cyfydufffi",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"32,
        "firstname""buvu",
        "lastname""cyxx",
        "phoneno""753577789",
        "address""vyuvvjvj",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"33,
        "firstname""g7g7",
        "lastname""cyyc",
        "phoneno""8765677999",
        "address""gyuj",
        "photo""",
        "username""tests107@mailsac.com",
        "password""test"
    },
    {
        "id"34,
        "firstname""g7g7",
        "lastname""cyyc",
        "phoneno""8765677999",
        "address""gyuj",
        "photo""",
        "username""tests107@mailsac.com",
        "password""test"
    },
    {
        "id"35,
        "firstname""g7g7",
        "lastname""cyyc",
        "phoneno""8765677999",
        "address""gyuj",
        "photo""",
        "username""tests107@mailsac.com",
        "password""test"
    },
    {
        "id"36,
        "firstname""g7g7",
        "lastname""cyyc",
        "phoneno""8765677999",
        "address""gyuj",
        "photo""",
        "username""tests107@mailsac.com",
        "password""test"
    },
    {
        "id"37,
        "firstname""test",
        "lastname""test",
        "phoneno""875678887",
        "address""hhjbjhhj",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"38,
        "firstname""test",
        "lastname""test",
        "phoneno""875678887",
        "address""hhjbjhhj",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"39,
        "firstname""test",
        "lastname""test",
        "phoneno""875678887",
        "address""hhjbjhhj",
        "photo""",
        "username""test",
        "password""test"
    },
    {
        "id"40,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"41,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"42,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"43,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"44,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"45,
        "firstname""",
        "lastname""",
        "phoneno""",
        "address""",
        "photo""",
        "username""",
        "password"""
    },
    {
        "id"46,
        "firstname""abhi",
        "lastname""sbhi",
        "phoneno""6858845",
        "address""ifdjdffuff kgufpfug bufstzcufuc kvfuk. kuddhjcfucucyddcpjvucyf",
        "photo""",
        "username""abhi",
        "password""abhi"
    }
]

2)http://localhost:8081/registration/29 (PUT Servcie)

request:

{
        "id"29,
        "firstname""abhinaw",
        "lastname""tri",
        "phoneno""8130752107",
        "address""howrah",
        "photo""/abc.png",
        "username""abhinaw",
        "password""abhinaw"
    }
Response:200OK
Time:251 ms
Size:62 B Save Response





























3)http://localhost:8081/registration (POST Service)









Websocket Communication System:

///////////////////////////Chat////////////////////////////
val connections = Collections.synchronizedSet<Connection?>(LinkedHashSet())
webSocket("/chat") {
println("Adding user!")
val thisConnection = Connection(this)
connections += thisConnection
try {
send("You are connected! There are ${connections.count()} users here.")
for (frame in incoming) {
frame as? Frame.Text ?: continue
val receivedText = frame.readText()
val textWithUsername = "[${thisConnection.name}]: $receivedText"
connections.forEach {
it.session.send(textWithUsername)
}
}
} catch (e: Exception) {
println(e.localizedMessage)
} finally {
println("Removing $thisConnection!")
connections -= thisConnection
}
}
/////////////////////////////////////Chat////////////////////////////

Very easy to communicate and very simple code for example.

Output Window:





Saturday, May 8, 2021

Swagger Implementation to Web-services API Spring Boot Project - Java


Spring Boot Web API Swagger Addition to Demo Project:

Note : For full access of code. kindly follow the below link. you can see the working code.

GitHub:

https://github.com/Abhinaw/RestAPiDemoWithDb/tree/master/src/main/java/com/abhi/restapidemodb

application.properties:
For example

server.port=8080
logging.level.org.springframework=info
server.servlet.context-path=/demo
spring.datasource.url=jdbc:mysql://localhost:3306/DB
spring.datasource.username=root
spring.datasource.password=
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update

Add Swagger Dependencies to POM.XML

<dependency>

    <groupId>io.springfox</groupId>

    <artifactId>springfox-swagger2</artifactId>

    <version>2.9.2</version>

</dependency>

<dependency>

    <groupId>io.springfox</groupId>

    <artifactId>springfox-core</artifactId>

    <version>2.9.2</version>

</dependency>

<dependency>

    <groupId>io.springfox</groupId>

    <artifactId>springfox-swagger-ui</artifactId>

    <version>2.9.2</version>

</dependency>

Create @Configuration File

The next step will be to create a configuration file. This configuration file aims to configure the base package and selectors of your project and make the configured Docket bean available in your application. Once you create this configuration file, there is a lot that will be done by the framework behind the scenes.

Below is an example of a very simple configuration file:

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import springfox.documentation.builders.PathSelectors;

import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.spi.DocumentationType;

import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration

@EnableSwagger2

public class SwaggerConfig {

   @Bean

   public Docket apiDocket() {

       Docket docket =  new Docket(DocumentationType.SWAGGER_2)

                .select()

                .apis(RequestHandlerSelectors.basePackage("com.appsdeveloperblog.app.ws"))

                .paths(PathSelectors.any())

                .build();

       return docket;

    } 

}

There are a couple of very important details to note in the above code snippet:

APIs() – here you specify classes that need to be included in Swagger. I provided the base package of my project and thus delegate the job of finding the needed classes to the framework. The base package will be scanned by the framework and needed classes will be included based on the annotations they have,

paths() – here we specify the methods(which are annotated with @Path annotation) from the Controller classes which should be included. Since I want all methods to be included in my documentation created with Swagger, I provide the PathSelectors.any()

Swagger and Spring Security

If your RESTful Web Service application is using Spring Security, you will need to do a little configuration in your Java class, which extends the WebSecurityConfigurerAdapter and annotated with @EnableWebSecurity annotation.

Open the Java class in your Spring Boot project which extends the WebSecurityConfigurerAdapter and which is annotated with @EnableWebSecurity annotation.

Generate Swagger API Documentation JSON

If we run our application now we can get the generated by Swagger JSON documentation of our REST API by opening the following URL in the browser window. I assume you are running your Spring Boot application locally, if so the try this URL:

http://localhost:8080/<CONTEXT PATH HERE>/v2/API-docs








Please note: 

In the URL above you will need to make sure that you provide a correct port number and the Context Path if you have provided one in your application. properties file. If you do not have the context path configured in your application. properties file, then do not provide any context path in the URL above.

For example, if your application properties file has the following entry:

server. servlet.context-path=/demo

server.port=8080

eg: 

http://localhost:8888/demo/v2/api-docs

Swagger UI

API Docs:
localhost:8080/demo/v2/api-docs

For Example:

{"swagger":"2.0","info":{"description":"Api Documentation","version":"1.0","title":"Api Documentation","termsOfService":"urn:tos","contact":{},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0"}},"host":"localhost:8080","basePath":"/demo","tags":[{"name":"user-controller","description":"User Controller"}],"paths":{"/users":{"get":{"tags":["user-controller"],"summary":"list","operationId":"listUsingGET","produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/User"}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"deprecated":false}},"/users/register":{"post":{"tags":["user-controller"],"summary":"add","operationId":"addUsingPOST","consumes":["application/json"],"produces":["*/*"],"parameters":[{"in":"body","name":"user","description":"user","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"200":{"description":"OK"},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"deprecated":false}},"/users/{id}":{"get":{"tags":["user-controller"],"summary":"get","operationId":"getUsingGET","produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/User"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"deprecated":false},"put":{"tags":["user-controller"],"summary":"update","operationId":"updateUsingPUT","consumes":["application/json"],"produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true,"type":"integer","format":"int32"},{"in":"body","name":"user","description":"user","required":true,"schema":{"$ref":"#/definitions/User"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}},"201":{"description":"Created"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not Found"}},"deprecated":false},"delete":{"tags":["user-controller"],"summary":"delete","operationId":"deleteUsingDELETE","produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK"},"204":{"description":"No Content"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"deprecated":false}}},"definitions":{"User":{"type":"object","properties":{"active":{"type":"integer","format":"int32"},"address":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"id":{"type":"integer","format":"int32"},"lastName":{"type":"string"},"password":{"type":"string"},"phone":{"type":"string"},"photo":{"type":"string"}},"title":"User"}}}




 

Saturday, May 1, 2021

Kotlin - Square Root Naïve Vs Efficient Solution Example

 It was Interview Question for Senior Developer where it was asked like 

Square root

Given an integer, we need to find the floor of its square root.

for example :

I/P = x=4

output = 2

input = x=14

output = 3

input x = 25

output = 5

I will give you 2 solutions for this problem one naive solution and another efficient solution. Let me know if anyone knows another way because to solve this type of problem we need to think of a Binary Search for an efficient solution that reduces the time complexity of the solution.

Naive Solution :

The idea is very simple we check every element one by one if it is square root then we return it.

 eg: lets dry run:

  x=9

 i = 1

 i=2

 i=3

 i=4

 result = (i-1) = 3

 So we come out of the loop when i*i greater than x which means your i-1 is the square root.

 Time Complexity is Theta of square Root of x.

 The solution in Kotlin is very very easy than core-java:

The Efficient Solution can be taken think of  Binar Search 

 So the idea we do x/2 ,x/2... if x/2 more than x then we cut the half.

  lets do the dr run:

 x =10

 low =1

 high=10

 1st Iteration:

  mid =5

 mSq=25

 high =4

  2nd Iteration:

 mid =2

 mSq=4

 low =3 , ans =2

 So Binary Search is a searching algorithm for searching an element in a sorted list or array. Binary Search is efficient than the Linear Search algorithm and performs the search operation in logarithmic time complexity for sorted arrays or lists. Binary Search performs the search operation by repeatedly dividing the search interval in half. The idea is to begin with an interval covering the whole array. If the value of the search key is less than the item in the middle of the interval, narrow the interval to the lower half. Otherwise narrow it to the upper half. Repeatedly check until the value is found or the interval is empty.

Full Code with both Naive vs Efficient Solution:

Runner. kt:

fun main() {
println(sqRootFloor(119))
println(sqareRootFloor(119))
}

/************Naive Solution*****/
fun sqRootFloor(x: Int): Int
{
var i = 1
while (i * i <= x) i++
return i - 1
}

/*************Efficient Solution************/
fun sqareRootFloor(x: Int): Int {
var low = 1
var high = x
var ans = -1
while (low <= high) {
val mid = (low + high) / 2
val mSq = mid * mid
when {
mSq == x -> return mid
mSq > x -> high = mid - 1
else -> {
low = mid + 1
ans = mid
}
}
}
return ans
}

 Input for 4 is 2 you can simply copy-paste and test it out.

Let me know if anyone can come with a more efficient solution for this.


 

Securing Spring Applications against Common Security Threats

 Description:

1)Spring Security protects your application from many common security threats right out of the box. You don't have to re-invent the wheel for the same but the problem is usually developer tends to ignore it but spring security framework provides protection against those threats right out the of the box it just matters how you tend to implement it.

 2)In fact the increased adoption of such frameworks has resulted in significant declines in occurrences of many of the threats.

 3)In Spring Framework: Securing Spring Applications against Common Security Threat like Man of the Middle Attack, Cross-site scripting, and many more. you should learn how to configure Spring Security with Spring Boot to get security up and running from the very get-go of your project. So here I am basically telling you how to deal with these common threats without much effort and you just need to configure your spring app correctly you just need the skills and knowledge of Spring Security needed to effectively secure your application against common security threats.

 I am mentioning a few of the security risks and threats to any spring boot-based application effectively. These are very common threats but very effective So before disabling anything in spring, make sure you are confident and are aware of the risks to your users before going ahead.

1)HTTP Headers: The First Line of Defense
2)The Cache-Control Header
3)MIME Type Sniffing and Browser XSS Protection
4)Understanding Spring Security Cross-Site Request Forgery
5)Default Clickjacking Protection
6)Additional Optional Security Headers
7)Spring Securities HTTP Firewall

The main takeaway from this is just don't try to reinvent the wheel.
Increased adoption of frameworks like Spring Security has resulted in many of the common security threats like cross‑site scripting, cross‑site request forgery, dropping out of the OWASP top 10 as you're getting a lot of protection right out of the box, often threats you don't even know about. 
Spring Security is very configurable, and it's easy to unintentionally disable some of the default security protection. Hence, before disabling anything, make sure you are confident and are aware of the risks to your users before going ahead.

This will give you the foundational knowledge required to customize the framework in the spring boot app.
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.mvcMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.logout();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("abhinaw").password("{noop}password").roles("USER");
auth.inMemoryAuthentication().withUser("tripathi").password("{noop}password").roles("ADMIN");
}

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/webjars/**");
}

}

@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(redirectConnector());
return tomcat;
}

private Connector redirectConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(8080);
connector.setRedirectPort(8443);
return connector;
}

@Controller
public class LoginController {

@GetMapping("/login")
public String login() {
return "login";
}

}

public class AuthenticationUtil {

public static String getUsername() {
UserDetails user = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return user.getUsername();
}
}

Below is my YAML file:

server:
port: 8443
ssl:
key-store-password: ENC(8e+G1W2rkvi1EglUn6uTheBzZ4IY2hhl)
key-store: classpath:keystore.p12
key-store-type: PKCS12
key-alias: tomcat

logging:
level:
root: INFO
com.memorynotfound: INFO
org.springframework.web: INFO
org.springframework.security: INFO

jasypt:
encryptor:
password: password
iv-generator-classname: org.jasypt.iv.NoIvGenerator
algorithm: PBEWithMD5AndTripleDES

For detailed implementation you can check out my GitHub code for better understanding:

Git Hub URL: https://github.com/Abhinaw/SpringSecirityAgainstCommonThreats

Just visit and check out the code and you will understand correctly. 



Monday, March 29, 2021

Part-3 Ktor Kotlin MySQL Integration tutorial - Best Practices Code

 Here you will learn how to integrate MYSQL with Ktor using Kotlin Need to create Database Screen-shots attached for reference.

Below is my Github URL:
https://github.com/Abhinaw/MySqlKtorTutorial




Get All Todos response coming from database:

http://localhost:8081/todos

[ { "id": 2, "title": "Test todo #2", "done": true }, { "id": 3, "title": "Record Video #6", "done": true }, { "id": 4, "title": "Todo Test #4", "done": true } ]

Part-2 Middle-Tier Implementation with #Ktor #kotlindeveloper

Working demo with best practices with proper handling GET, POST, PUT, DELETE operation. You can request JSON and get a response as JSON.

Below is the Github URL:

https://github.com/Abhinaw/KtorEnhancedTutorialRequestResponseDemo

Here you can see live request and response that you are making through the postman . you can perform add,delete,update in the code below is the working example that i performed:

GET:

http://localhost:8081/todos [ { "id": 2, "title": "Record Video", "done": true }, { "id": 3, "title": "Record Video #4", "done": true }, { "id": 4, "title": "Record Video", "done": true }, { "id": 5, "title": "Record Video", "done": true }, { "id": 6, "title": "Record Video", "done": true }, { "id": 7, "title": "Record Video", "done": true }, { "id": 8, "title": "Record Video", "done": true } ]

POST: http://localhost:8081/todos request: { "title": "Record Video", "done": true } response: { "id": 8, "title": "Record Video", "done": true }

PUT: http://localhost:8081/todos/3

request: { "title": "Record Video #4", "done": true }

response: 200OK

DELETE:

http://localhost:8081/todos/1

request: { "title": "Record Video", "done": true } response: 200OK



Part-1 Building Middle-Tier in Kotlin Using Ktor #kotlin #Ktor

 Very Simple Working Code Example. Below is my GitHub URL

https://github.com/Abhinaw/Kotlin_Ktor_Demo_App

Many web applications and services are built using the Spring Framework. While Spring is incredibly powerful and Kotlin is useful nobody can accuse it of being lightweight because of the benefits it has such as support of immutable data and null detection, as well as having less of the bloat of Java. Bring these two together, a lightweight HTTP framework and a nice programming language and you get Ktor. It is heavily based on Kotlin coroutines and so supports a high degree of asynchrony. I have tried to write as much as possible easy code for all so that everyone can understand it.