Tuesday, 22 June 2021

Usage of Kafka Clients: Write a kafka producer that write messages to a kafka topic

Lets say we have created a kafka topic using a command line :

kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic twitter-topic --create 

--partitions 3      



Verify the Kafka topic details - by listing in the console:


kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --topic twitter-topic --describe         


Topic: twitter-topic PartitionCount: 3 ReplicationFactor: 1 Configs: segment.bytes=1073741824

Topic: twitter-topic Partition: 0 Leader: 0 Replicas: 0 Isr: 0

Topic: twitter-topic Partition: 1 Leader: 0 Replicas: 0 Isr: 0

Topic: twitter-topic Partition: 2 Leader: 0 Replicas: 0 Isr: 0  



Now you have a kafka topic - Write a Kafka Producer using Kafka clients dependency:



Dependencies (if in gradle):


dependencies {
implementation group: 'org.apache.kafka', name: 'kafka-clients', version: '2.8.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

Write a Kafka producer in a normal java class inside main method:
----------------------------------------------------------------------
package com.basic.producer;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;

public class ProducerWithoutKeyDemo {
public static void main(String[] args) {
//Add REQUIRED properties - set up kafka config
Properties properties = new Properties();
//If you don't set the following properties
        //possible exception: org.apache.kafka.common.config.ConfigException
        //If don't not set: exception: No resolvable bootstrap urls given in bootstrap.servers
properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
//If don't not set: exception:
        //Missing required configuration "key.serializer" which has no default value.
properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
                                                                            StringSerializer.class.getName());
//If don't not set: exception:
        //Missing required configuration "value.serializer" which has no default value.
properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
                                                                            StringSerializer.class.getName());
        //create a kafka producer
KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
        //send data to kafka topic
        String message = "Hey man";
ProducerRecord<String, String> producerRecord
                    = new ProducerRecord<>("twitter-topic", message);
//send needs a ProducerRecord type - defined without a key.
//without key means - the messages can go to any partition in twitter-topic
producer.send(producerRecord);

//Very important note:
//If you don't flush - message will not go to topic
producer.flush();
//Instead of the above- you flush & close in one step by using .close() method
producer.close();
}
}
----------------------------------------------------------------------
You can test the producer by executing a console consumer on terminal:

kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic twitter-topic 

Leetcode Solved: Convert a Roman number to Integer

PRODLEM STATEMENT:

For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.


Roman numerals are usually written largest to smallest from left to right.
However, the numeral for four is not IIII. 
Instead, the number four is written as IV. 
Because the one is before the five we subtract it making four. 
The same principle applies to the number nine, which is written as IX. 
There are six instances where subtraction is used:

I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer.


Example 1:

Input: s = "III"
Output: 3
Example 2:

Input: s = "IV"
Output: 4
Example 3:

Input: s = "IX"
Output: 9
Example 4:

Input: s = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.
Example 5:

Input: s = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.


Constraints:

1 <= s.length <= 15
s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
It is guaranteed that s is a valid roman numeral in the range [1, 3999].
----------------------------------------------------------------------
package com.algos;

import java.util.HashMap;
import java.util.Map;

public class RomanToInteger {

public static void main(String[] args) {
System.out.println(romanToInt("MDCCCLIX")); //XL L X V IV III = 112
}

public static int romanToInt(String s) {
char[] chars = s.toCharArray();
int iCount = 0;
int total = 0;
Map<String, Integer> charMap = new HashMap<>();
charMap.put("I", Integer.valueOf(1));
charMap.put("V", Integer.valueOf(5));
charMap.put("X", Integer.valueOf(10));
charMap.put("L", Integer.valueOf(50));
charMap.put("C", Integer.valueOf(100));
charMap.put("D", Integer.valueOf(500));
charMap.put("M", Integer.valueOf(1000));
char prev = '\0'; // (char) 0
for (int c = chars.length - 1; c >= 0; c--) {
if ('I' == chars[c]) {
iCount++;
if (iCount > 3) {
c--;
break;
} else {
if (prev == 'V' || prev == 'X') {
iCount = 0; //need to verify
total = total - 1;
} else {
total = total + charMap.get("I");
}
prev = chars[c];
if (iCount == 3) {
iCount = 0;
}
continue;
}
} else if ('V' == chars[c]) {
prev = chars[c];
total = total + charMap.get("V");
} else if ('X' == chars[c]) {
if(prev == 'L' || prev == 'C') {
total = total - 10;
} else {
total = total + charMap.get("X");
}
prev = chars[c];
} else if ('L' == chars[c]) {
prev = chars[c];
total = total + charMap.get("L");
} else if ('C' == chars[c]) {
if(prev == 'D' || prev == 'M') {
total = total - 100;
} else {
total = total + charMap.get("C");
}
prev = chars[c];
} else if ('D' == chars[c]) {
prev = chars[c];
total = total + charMap.get("D");
} else if ('M' == chars[c]) {
prev = chars[c];
total = total + charMap.get("M");
}
}
return total;
}
}

Friday, 18 June 2021

How to check whether a given number is Armstrong Number or not?

What is an Armstrong Number?

An Armstrong Number is a number, where the sum of cubes of each digit of that 
number is equal to the given number.
Example: 371 = 33 + 73 + 13
----------------------------------------------------------------------------------------------------------------------
package com.algos;

import java.util.Scanner;

public class ArmstrongNumber {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(checkArmstrongNumber(n));
}

private static boolean checkArmstrongNumber(int n) {
int movingCubeTot = 0;
int temp = n;
while(temp > 0) {
int currDig = temp % 10;
temp = temp/10;
movingCubeTot = movingCubeTot + (currDig * currDig * currDig);
}
return n == movingCubeTot;
}
}

Thursday, 17 June 2021

Git Commands: used by a developer on daily basis

How to initialize a project or any folder to use the git?

Typically, developers use the git for better continuous integration (collaborative work among multiple team members). But, in general, any person who is novice to the computer knowledge can take the benefit of the git version control system. For example, a novel writer, can use the git.

git init

<in a project folder> will initialize the git & git for then, tracks your changes.


How to check the current status of git? 

git status

This command helps the user of the git to know what is the current status of the version control: like what files are changed, among those files which are being in untracked & in staging (ready to commit state).


How to check the logs of git?

git log 

git log --oneline

The above commands help you to show the recent commits to current project. Note: Every commit will have a SHA id(an alphanumeric id) & author info. Generally, we use to know what's the recent changes that have been added to a file / project. 


How to check the branch info?

Branching model in git is a model, where individual work piece assigned to a developer is developed on a different branch, sometimes called as feature branch. Generally, we name the branches with the work related terms. For example, if I am working on purchase order related work, I will create a new branch with a suitable name something like purchase-order branch or sometimes we create branches with JIRA story numbers (for example, on DCP project - branch : DCP-1234)

To the know what are the branches existing: we can use 

git branch

this command will show all the branches. Some branches will be both remote & local branches. This means, during the initial development of a piece of work, the branch may still exist as a local branch for that developer. Until this branch is been pushed, it will have only a local branch. Once a branch is pushed & it will be available in remote.

How to see the local & remote branches using terminal?

To see all the local & remote branches:

git branch -a 

To see the local branches:

git branch

To see the remote branches:

git branch -r


Git Commands used to work with other people's repositories

https://help.github.com/articles/fetching-a-remote/

git clone

git fetch

git merge

git pull

When you are working with other people's repositories:

you may use these commands

These commands are useful working with remote repositories.

git clone :
---------------
to grab a complete copy of a another user's repository - use git clone

$git clone https://www.github.com/USERNAME/REPOSITORY.git


git fetch:
--------------
Use git fetch to fetch the new work done by the other people.

Fetching from a repository grabs all the new remote-tracking (refs/remote/origin/foo referred to as a origin/foo) branches and tags without merging those changes into  your branches.

 git merge:
-----------------

merge combines your local changes with changes made by others.

Typically , you would merge a remote-tracking branch with your local branch

git pull:
--------------
It is a shortcut for both git fetch and git merge in same command

because pull performs a merge on the retrieved changes, you should ensure your local work is commited before running the pull command.

If you run into a merge conflict if you cannot resolve, or if you decide to quit the merge, use git merge --abort to take the branch where it was before you pulled.







Thursday, 10 June 2021

How to print the date in specific format in java?

You can format the dates in java using SimpleDateFormat class from java.text pacakge.

Create an object of SimpleDateFormat - provide the pattern to constructor.
Note: Pattern will have date specific literals.

String pattern = "yy-MM-dd";

SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);

For example: 

package com.algos;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormat {
public static void main(String[] args) {
String pattern = "dd-MM-yy";
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
System.out.println(dateFormat.format(new Date()));
}
}

How to reverse the words in a sentence in java ?

Two ways:

> using new StringBuilder().append method
> using apache commons dependence - StringUtils.reverseDelimited(sentence, ' ')
Example:
package com.algos;

public class ReverseSentence {
public static void main(String[] args) {
String sentence = "I am in love with her";
System.out.println("Reverse of a sentence: "
                        + reverseSentence(sentence));
System.out.println(sentence.length() == reverseSentence(sentence).length());
        //2nd way
//By using apache-commons:commons-lang3 dependency
//StringUtils.reverseDelimited(str)
}

private static String reverseSentence(String sentence) {
if (sentence == null) return null;
String[] words = sentence.split(" ");
StringBuilder output = new StringBuilder();
for (int i = words.length - 1; i >= 0; i--) {
output.append(words[i]);
output.append(" ");
}
return output.toString().trim();
}
}

How to reverse the String in java ?

You can use some mutable string related classes like StringBuilder / StringBuffer classes for reversing the string.

> You can use reverse() method of StringBuilder : 
new StringBuilder().reverse for doing this.
> You can also use apache commons dependence - 
& use StringUtils.reverse(String str)
Example:
package com.algos;

public class ReverseString {
public static void main(String[] args) {
String str = "Hello World";
System.out.println("1st Way : Reverse of given string : "
                + reverseStr(str));
        System.out.println("2nd Way : Reverse of given string : " 
                + reverseStr2(str));
//Using 3rd way
//By using apache-commons:commons-lang3
//StringUtils.reverse(str)
}

private static String reverseStr2(String str) {
if (str == null) {
return null;
}
StringBuilder builder = new StringBuilder(str).reverse();
return builder.toString();
}

private static String reverseStr(String str) {
if (str == null) {
return null;
}
char[] in = str.toCharArray();
StringBuilder builder = new StringBuilder();
for (int i = in.length - 1; i >= 0; i--) {
builder.append(in[i]);
}
return builder.toString();
}
}

How to find the missing number from a given array (when only one number is missing from a sequence of non-zero numbers)?

Assumptions :

The array may have only one number missing in the sequence of numbers
with out zero in it.
Example:
int[] arr= {1, 3};
The missing number is 2 (where numbers are from 1 to 3)
Algorithm:
> Calculate the array size, using array size - calculate the sum of n numbers 
(n: array size + 1)
> Traverse the array elements using a for loop - calculate the moving sum
> then after that, diff of number of n numbers - moving sum of elements will 
give the missing number
Example:
package com.algos;

public class OnlyMissingNumberInArray {

public static void main(String[] args) {
int[] arr= {1, 3};
//The missing number from 1 to 3 is 2
System.out.println("The missing number "+ findMissingNumber(arr));
}

private static int findMissingNumber(int[] arr) {
//Calculate sum of numbers from 1 to 3 using n(n+1)/2
int n = arr.length + 1;
int sumOf = n * (n + 1)/2;
int sum = 0;
for(int i : arr) {
sum = sum + i; //moving sum
}
return sumOf - sum; //missing number 2
}
}

Thursday, 3 June 2021

Gradle Build : Project API Inbuilt properties

 One can use these properties given by gradle project api, within build.gradle file.

------------------------------Start of the File--------------------------

build.gradle

//project api properties
logger.info("Name of the project: ${project.name}")
logger.info(
"absolute path of the project: ${project.path}")
logger.info(
"description for the project: ${project.description}")
logger.info(
"directory containing the build script: ${project.projectDir}")
logger.info(
"build directory: ${project.buildDir}")
logger.info(
"${project.group}")
logger.info(
"${project.version}")

//The above properties - print same as below
//project api properties without project. prefix - implied by default
logger.info("Name of the project: ${name}")
logger.info("absolute path of the project: ${path}")
logger.info("description for the project: ${description}")
logger.info("directory containing the build script: ${projectDir}")
logger.info("build directory: ${buildDir}")
logger.info("${group}")
logger.info("${version}")
------------------------------End of the File--------------------------
Execution:
gradle -i build

-i for enabling logging for info level.
Output:
Name of the project: gradle-demo
absolute path of the project: :
description for the project: null
directory containing the build script: /Users/dinesh/IdeaProjects/gradle-demo
build directory: /Users/dinesh/IdeaProjects/gradle-demo/build

unspecified
Name of the project: gradle-demo
absolute path of the project: :
description for the project: null
directory containing the build script: /Users/dinesh/IdeaProjects/gradle-demo
build directory: /Users/dinesh/IdeaProjects/gradle-demo/build

unspecified

Gradle Logging Options: How to use logger in gradle build files?

 By default, there are no logs printed, because logging is disabled by default.

OptionOutputs Log Levels

no logging options

LIFECYCLE and higher

-q or --quiet

QUIET and higher

-w or --warn

WARN and higher

-i or --info

INFO and higher

-d or --debug

DEBUG and higher (that is, all log messages)


Note: reference official docs

Tuesday, 18 May 2021

What is Feign Web Service Client ?

Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it.

The following dependency is expected to add Feign in the project:

Dependency:

group id: org.springframework.cloud

artefact id: spring-cloud-starter-openfeign

Annotations:

@EnableFeignClients    - to enable the Feign Client

Sample Feign Client:

@FeignClient(name = "products", url="${productsUrl}")

public interface ProductClient {

        @RequestMapping(method=RequestMethod.GET,  value ="/products")

        List<Product> getProducts();

        @RequestMapping(method= RequestMethod.POST,  

        value ="/products/{productId}", consumes = "application/json")

        Product update(@PathVariable("productId") Long productId);

}


string value "products" within @FeignClient annotation is the arbitrary client which might be used in Ribbon (load balancing) support.

Note:

> you can also specify url attribute (absolute value or just a hostname).

> you can use qualifier attribute for giving an alias value for the bean name, if not given the name of bean in the application context is the fully qualified name of the interface.

---------------------------

Note: Each feign client is part of an ensemble of components that work together to contact a remote server, and the ensemble has a name that is given in name attribute of @FeignClient annotation.

Spring Cloud creates a new ensemble as an ApplicationContext on demand for each named client using FeignClientsConfiguration. This contains other things feign.Decorder, a feign.Encoder, and a feign.Contract.

You can control the feign client by declaring additional configuration using configuration attribute.


@FeignClient(name = "products", configuration= FooConfiguration.class)

public interface ProductClient {

    //..

}

Note: FooConfiguration does not need to be annotated with @Configuration. However, if it, then take care to exclude it from any @ComponentScan that would otherwise include this configuration as it become the default source for feign.Decoder, feign.Encoder, feign.Contract.

OTHER EXTRA INFO:

Spring Cloud Netflix provides the following beans by default:

> Decoder feignDecoder: ResponseEntityDecoder (which wraps a SpringDecorder)

> Encoder feignEncoder: SpringEncoder

> Logger feignLogger: Slf4jLogger

> Contract feignContract: SpringMvcContract

> Feign.Builder feignBuilder HystrixFeign.Builder

> Client feignClient: if Ribbon is enabled it is a LoadBalancerFeignClient, otherwise the feign client is used.

Not only by using a separate Configuration class, you can configure the @FeignClient using application props.

Example: 

feign:

    client: 

        config:

            <feignName>:

                connectTimeout: 5000

                readTimeout:    5000

                loggerLevel: full

                errorDecoder: com.example.SimpleErrorDecoder

                retryer: com.example.SampleRetryer

                requestInterceptors:

                        - com.example.SampleRequestInterceptor

                        - com.sample.ExampleRequestInterceptor

                decode404: false

                encoder: com.example.SampleEncoder

                decoder: com.example.SampleDecoder

                contract: com.example.SampleContract


The above props will apply to only named feign client. To apply to all feign clients, you can declare the props using default feign name:

Example:

  feign:

    client:

        config:

            default:

                connectTimeout:    5000

                readTimeout:    5000

                loggerLevel: basic

Now, this config props applies to all feign clients.

Note: If you create both Configuration class and Feign Config props in application yaml, configuration props will win.

You can change this behaviour by changing the prop:

   feign.client.default-to-properties to false.

Feign Logging:

A logger is created for each Feign Client created. 

By default the name of the logger is the full class name of the interface used to create the Feign client.

you can configure the log level per client 

e.g, 

logging.level.com.sample.ProductClient: DEBUG

com.sample.ProductClient - full class name

Logging Levels available are:

    NONE - No logging (default)

    BASIC - logs only 

        > request method    > URL    > response status > execution time

    HEADERS    - logs basic info along with req and response headers

    FULL - log the headers, body and metadata for both requests and responses.

Sunday, 11 April 2021

How to create aliases for git commands used frequently?

We can create aliases, shorter versions for git commands, using git config command.

git config --global alias.<shorter_name> <command>

If the command is having multiple words, then you single quotes

git config --global alias.<shorter_name>     '<command>    <attribute1> <attr2> .... '

Examples:

For checkout command use:

git config --global alias.co checkout

For commit command use:

git config --global alias.ct commit

For branch command use:

git config --global alias.br branch

For status command use:

git config --global alias.st status

For pull complete command (multiple words) use:

git config --global alias.plm 'pull origin master'


Note: you can check all the aliases & other config options using

git config --global --list

Output:

alias.co=checkout

alias.br=branch

alias.ct=commit

alias.st=status

alias.plm=pull origin master