aiShare Your Requirements
Shiv Kumar Oodles

Shiv Kumar (Manager-Solutions Architect)

Experience: 12+ yrs

Shiv is an experienced Java Developer with a strong background in multiple technologies. He specializes in defining system architectures to ensure reliable and resilient solutions. He possesses a comprehensive understanding of the latest technologies and has hands-on experience in Core Java, Spring Boot, Hibernate, Apache Kafka messaging queue, Redis, as well as relational databases like MySQL and PostgreSQL, and non-relational databases like MongoDB. He excels in API implementations, Microservices, Web Services development, testing, and deployments. Shiv actively contributes to code enhancements and consistently delivers valuable contributions to various client projects, including Fabtrack, Pando, Pandojo, Digikam, WhatsApp Integration, Croniz, Punchin Application, Script TV, Bhaasha, and more. He demonstrates strong analytical skills and a creative mindset. In addition, he has a passion for reading books and exploring new technologies and innovations.

Shiv Kumar Oodles
Shiv Kumar
(Solutions Architect)

Shiv is an experienced Java Developer with a strong background in multiple technologies. He specializes in defining system architectures to ensure reliable and resilient solutions. He possesses a comprehensive understanding of the latest technologies and has hands-on experience in Core Java, Spring Boot, Hibernate, Apache Kafka messaging queue, Redis, as well as relational databases like MySQL and PostgreSQL, and non-relational databases like MongoDB. He excels in API implementations, Microservices, Web Services development, testing, and deployments. Shiv actively contributes to code enhancements and consistently delivers valuable contributions to various client projects, including Fabtrack, Pando, Pandojo, Digikam, WhatsApp Integration, Croniz, Punchin Application, Script TV, Bhaasha, and more. He demonstrates strong analytical skills and a creative mindset. In addition, he has a passion for reading books and exploring new technologies and innovations.

LanguageLanguages

DotEnglish

Conversational

DotHindi

Fluent

SkillsSkills

DotOBS Studio

80%

DotDASH

60%

DotEncoding

60%

DotPhoton

60%

DotZoom

80%

DotDRM

60%

DotTechnical Project Management

80%

DotJava

80%

DotAnt Media

60%

DotKaltura

40%

DotTranscoding

60%

DotPostgres

80%

DotAmazon Prime Video Direct

60%

DotMySQL

80%

DotFFmpeg

80%

DotRedis

80%

DotKafka

80%

DotSpring Boot

80%

DotHLS

80%

DotNetflix Open Connect

60%

DotAWS

80%
ExpWork Experience / Trainings / Internship

Aug 2013-Present

Solution Architect

Gurgaon


Oodles Technologies

Gurgaon

Aug 2013-Present

Aug 2013-Present

Solution Architect

Gurgaon


Oodles Technologies

Gurgaon

Aug 2013-Present

EducationEducation

2008-2012

Dot

PTU

B. Tech-CSE

Top Blog Posts
Implementation of Microservice Architecture in Java and Nodejs In my last blog, I have discussedthe main basic components of the microservice architecture. In this blog, we will discuss about some implementation techniques of the microservice architecture using Java and node-js technologies. I have worked on one project which converts currency from one format to other. Below diagram will describe the structure of the application. Zuul Gateway has an inbuilt Ribbon load balancer. Zuul Gateway is the entry point for all the clients and it connects with Eureka Server to get the location of deployed microservice instances. All the node-js microservices below registered themselves with Eureka Server using Client Side Discovery pattern. Architecture Diagram of Microservice Implementation : In this application we are using different microservices which are listed below with description: 1. User Microservice : User microservice is written in node.js and is used to create users and to fetch user's information. It is also used as metadata service because we can create exchange data from this microservice also. 2. Forex Microservice : Forex microservice is also written in node.js and is used to set the value of one currency against another currency. We can also get the value of one currency against another one. 3. Currency Conversion Microservice : Currency conversion microservice is also written in node.js and is used to convert the value of one currency into another currency value. To convert the value it will first fetch the value of one currency against another one from Forex microservice and then do the manipulation to show the converted value. In this case, one microservice(Currency Microservice) calls another microservice(Forex microservice) and it is done by using Feign Client. Feign Client: If you want to call any method of another application in our application then you have to do either rest or soap request. Currently, rest is used mostly due to its flexible nature. To do rest call to other application you have to use rest-template in which we have programmatically build proper URL of the target with all the URL parameters and then pass it to a method of rest-template to fetch the data. To do this developer has to take care of everything rather than focus on the business logic of the application. To overcome this issue, Netflix provides an abstraction over the REST API calls in which developers don’t have to bother about the internal working of REST APIs. The developer has to only define interface against the rest API and then the original request will be constructed by Spring itself. It hides the internal working of REST APIs and developers have now more time to focus on business logic. Request encoding and response decoding are also provided by Netflix Feign Client. We have to only provide the serviceId of the microservice and then Feign on the fly provide the implementation of the defined interface by using the declarative principle to call another microservice. Feign ask the Eureka discovery about the actual location of requested microservice on the basis of provided service-id and call the actual instance with the desired URL. @FeignClient annotation is used on the interface which takes service-id as a parameter. How to implement Feign Client in Java: 1. You have to first add Feign dependency in your project pom.xml like <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> <version>1.4.2.RELEASE</version> </dependency> 2. Add @EnableFeignClients in the main class of the project which let the project know that Feign will be used and enable the project to scan the Feign related annotations. 3. Then you have to define an interface annotated with @FeignClient which take service-id of another microservice as the parameter for which call is made. In this interface, Methods are defined with a type of request with annotation @RequestMapping. Example : @FeignClient(name="forex-service") public interface ForexClient { @RequestMapping(method = RequestMethod.GET, value = "/currency-exchange/from/{from}/to/{to}") public ResponseEntity convertCurrency( @PathVariable(value = "from") String from, @PathVariable(value = "to") String to ); } In above code snippet Feign will provide the implementation of the interface on runtime but for this Feign has to know beforehand about microservice which he has to call. That is why service-id is provided with @FeignClient annotation. Feign connect with Eureka server to get the actual host location of that microservice using service-id and then call the actual instance with URL provided in @RequestMapping annotation. 4. Atlast we have to autowire the interface defined above into required controller or service to inject the implementation of the Interface at runtime and call the interface method. Example: @RestController public class CurrencyConversionController { @Autowired ForexClient forexClient; @GetMapping("/currency-converter/from/{from}/to/{to}/quantity/{quantity}") public CurrencyConversionBean convertCurrency( @PathVariable String from, @PathVariable String to, @PathVariable BigDecimal quantity) { try { ResponseEntity responseEntity = forexClient.convertCurrency(from,to); }catch (Exception ex){ ex.printStackTrace(); } ......... } } How to implement Feign Client in Nodejs : Below are the steps to implement Feign Client in nodejs : We will use the feignjs module and its client feign-request to implement the Feign in node-js. 1. To install both use the below commands : npm install feignjs npm install feignjs-client There are multiple feign clients : feignjs-request - Request module for nodejs feignjs-jquery - JQuery module for nodejs feignjs-node - Node module for nodejs - use http of nodejs feignjs-xhr - XHR module for nodejs which use plain xhr. But we will use feignjs-request because it is more suitable for our case. We will discuss other clients in upcoming blogs. 1. To install it use the command below : npm install feignjs-request 2. Import feign in your required file using below syntax : import feign = require('feignjs'); import FeignRequest = require('feignjs-request'); 3. Define Apis in a declarative manner for microservices which we call using Feign using below syntax : var apiDescription = { saveValue : { method : 'POST', uri : '/createExchange' }, getAllValue : { method : 'get', uri : '/getAllExchangeValues' }; These are the apis of the the other microservices which we have to call to fetch data using Feign. 4. Instantiate feign client using the below syntax : var client = feign.builder() .client(new FeignRequest()).target(apiDescription, 'url'); url - URL of the another microservice to which call will be made. 5. Make an actual call to required microservice : Client declared above has now methods with their endpoints to make calls. Syntax for invoking the methods is given below : Syntax : client.method( [path-parameters], [body/query/post-parameter-object], [callback-function] ); Example: client.saveValue({ 'conversionMultiple':req.body.conversionMultiple, 'currencyFrom':req.body.currencyFrom, 'currencyTo':req.body.currencyTo}, {Xtoken:token} ).then(function(result, error){ if(error){ res.send(JSON.stringify(error)); }else{ res.json(result); } }); In method call, we have passed the path-parameters and one body object required for the call. Result will be rendered as json into response object and in case of error, an error message will be sent as string format. In this way, we can implement Feign both in java and nodejs. We will discuss how to register microservices with Eureka in nodejs and other stuff also. Thanks Shiv Kumar
How to secure Redis database In previous blog I have explained how to set up a key value database Redis. After installing redis we can access redis database using command redis-cli, because redis security is not implemented yet. If you run following command on redis cli : 127.0.0.1:6379> auth admin (error) ERR Client sent AUTH, but no password is set - It gives this error message means no security password is set yet. We can secure our Redis database in many ways as described below : 1. Bind it to some private ip instead of localhost : 1.1 Open redis.conf 1.2 Go to configuration # bind 127.0.0.1 and uncomment it. 1.3 Change local ip to some private ip. 1.4 Save the changes and restart redis server. 2. Configure a secure password : 2.1 Open redis.conf 2.2 Go to configuration # requirepass foobared and uncomment it. 2.3 Change password to some secure password. 2.4 Save the changes and restart redis server. Now each time you access redis database and run command you have to provide password, otherwise it will give error (error) NOAUTH Authentication required. 2.5 Run command auth password . It gives OK. Now you can access redis database using command redis-cli -h hostname -p portnumber -a securepassword 3. Rename dangerous commands : There is a set of some commands which are very dangerous to execute , so they should be executed by some authorised user. To secure redis in this perspective you can completelly kill or rename those command using following syntax : Go to redis.conf and do following : Completely kill command : rename-command FLUSHDB "" -- renamed to empty string means no operation will be performd when this command is executed. Rename to some other name : rename-command FLUSHDB FLUSHDB_MANUAL -- command is renamed to FLUSHDB_MANUAL If you run now FLUSHDB on redis console it will give following error: (error) ERR unknown command 'FLUSHDB' 4. Another way to secure redis is setting permission and ownership to the redis folder using following command : sudo chmod 700 redis folder Thanks Shiv Kumar
Ways to show conditional error messages in jquery validate plugin Sometimes we are required to show validation messages depending upon some conditions and check. Jquery Validate plugin provides different ways as described below to do the same. Way 1 : Using "depends". It is not a rule but the property which toggles the rules on or off. "depends" is used only in rules section not in messages section. { eventName: { required: { depends: function(ele) { return $('#eventCheckBox').is(':checked'); } }, minlength: 3 }, ... }, messages: { eventName: { required: "Event name is required", minlength: "Event name should be atleast 3 characters long." }, .... }, Way 2 : Using Inline check inside the rule section : { eventName: { required: $('#eventCheckBox').is(':checked')? true : false, minlength: 3 } }, ... messages: { username: { required: "Event name is required", minlength: "Event name should be atleast 3 characters long." } ... }, Way 3 : conditional checks in addMethod: jQuery.validator.addMethod("isValidMemberType", function(value, element) { var order = $(element).attr('data-order'); if(value == 'PEOPLE_AND_COMPANIES') return true; else if(value == 'PEOPLE_ONLY' && $('#company'+order).val() != 0) return false; else if(value == 'COMPANIES_ONLY' && $('#user'+order).val() != 0) return false; else return true; }, function(value,element){ if($(element).val() == 'PEOPLE_ONLY') return $L("people.only.setting.error"); else if($(element).val() == 'COMPANIES_ONLY') return $L("company.only.setting.error"); }); Thanks
Difference between BeanFactory and ApplicationContext BeanFactory is also called basic IOC and ApplicationContext is called Advanced IOC. Although BeanFactory and ApplicationContext both are used to get the beans from IOC container by using method getBean(String beanName). But they have some significant differences in their implementation which are described as below : 1. BeanFactory uses lazy initialization approach whereas ApplicationContext uses eager initialization approach. i.e BeanFactory creates a singleton bean only when it is requested from it but ApplicationContext creates all singleton beans at the time of its own initialization. 2. ApplicationContext creates and manages resources objects on its own whereas BeanFactory used to be explicitly provided a resource object using the syntax : ClassPathResource resource = new ClassPathResource("beans.xml"); XmlBeanFactory factory = new XmlBeanFactory(resource); // Here resource object is provided explicitly 3. ApplicationContext supports internationalization but BeanFactory do not. 4. Annotation based dependency Injection is not supported by BeanFactory whereas ApplicationContext supports using annotation @PreDestroy, @Autowired. Thanks
Difference between get and load method of hibernate session get() and load() both methods have same syntax and is used to load an entity using its id.But they are internally different in their mechanism. public Object load(Class entityClass, Serializable id); public Object get(Class entityClass, Serializable id); Differences : 1. get() method provides the implementation of eager loading(load state and relations initially) whereas load() method provides the implementation of lazy loading(load state and relations when actaully needed). 2. When requested object is not found in the database get() method returns nullPointerException whereas load method throws objectNotFoundException. 3. get() method can be used in attached(session is active) as well as detached(session is closed) mode whereas load method can only be used in attached mode. In case of load() , if session is closed and then we try to access state of any object , LazyInitializationException is thrown. I have following Emp table with 3 records. Emp Table id name job salary 1 Rahul Developer 20000 2 Gaurav Tester 19000 3 Gagan Designer 20000 get() method Example : public static void main(String arr[]){ Session session = MyFactory.getSession(); Emp emp = (Emp) session.get(Emp.class, 1); //Emp emp = (Emp) session.get(Emp.class,5); It will throw nullPointerException beacuse id 5 is not available in db. session.close(); System.out.println("Session closed, Entity state is :"); // State will be printed here becuase object is loaded eagerly with its own state and relations. System.out.println(emp.getName()+" "+emp.getJob()+" "+emp.getSalary()); } load() method Example : public static void main(String arr[]){ Session session = MyFactory.getSession(); Emp emp = (Emp) session.load(Emp.class, 1); //Emp emp = (Emp) session.load(Emp.class,5); It will throw objectNotFoundException beacuse id 5 is not available in db. session.close(); System.out.println("Session closed, Entity state is :"); // LazyInitialization error will be thrown as object is loaded in lazy mode. System.out.println(emp.getName()+" "+emp.getJob()+" "+emp.getSalary()); } THANKS
Know about Generic Validator In grails, validation is checked with either using command objects or using domain level validators, but both of them have pre-defined validation to check. If we have to check some different kind of validation then we have to prepare regex for them or create some custom validator to validate. But Generic Validator class of org.apache.commons.validator provides some static methods to check different kind of validations which we have to customise in command objects and in domains. Some of the methods of class are described here : isBlankOrNull(String value) : Checks if the field isn't null and length of the field is greater than zero not including whitespace. isInt(String value) : Checks if value can be converted to a int primitive type or not. matchRegexp(String value, String regexp) : Checks if the value matches the given regular expression or not. isInRange(int value, int min, int max) : Checks if a value is within a given range or not. Other benefit of using these methods is your code will look neat and clean. THANKS
How to partially search a word in solr I have faced an issue while implementing searching using solr. I have to search for partial word and its working fine for single word or multiple words but creates an issue in a specific scenario : When I seached for "shiv" ---- working fine "shiv kumar" --- working fine "shiv kum" --- working fine "shiv k" -- failed here The issue is not with my code but with tokenizer(StandardTokenizerFactory) solr configuration in schema.xml. In schema.xml, StandardTokenizerFactory has a filter EdgeNGramFilterFactory configured in different way like : <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="30" side="front" luceneMatchVersion="4.3"/> It means it will create n-gram for the input starting from front edge and grouping element in pair of two and more and upto 30. minGramSize plays an importatnt role here and specifies the minimum numbers of characters for grouping. You can understand this by example : The above configuration will give the following output for the word "higher" : higher ---> "hi", "hig", "high", highe", "higher" By putting minGramSize ="1" solved my problem as it gives the following output: higher ---> "h", "hi", "hig", "high", highe", "higher" In earlier configuration there was grouping of 2 that is why "shiv k" case was failing because no combination was there for single "k". Setting minGramSize to 1, search for single "k" also works and solved the issue. Hope this will surely help you. Thanks
How to get most relevant result using solr boosting Recently I have faced an issue while implementing suggestion dropdown in our app using solr. We had to show the very most relevant result to the user according to the role of user and other conditions. Solrj API is already integrated in the app and it helped me to solve the issue with the help of boosting feature of solr to get the most nearby result. Solr provides two types of boosting mechanism : 1. Index Time Boosting mechanism : It is done when we have to index data into solr.It can be applied to whole document or on a specific field also. 2. Query/Search Time Boosting mechanism : It is done while searching from solr. It can be applied on different fields according to result requirement. I prefered second mechanism as it was solving my problem without affecting other modules. Boosts are applied on different fileds using caret symbol(^) along with weightage value on the searched text or on a specific query part like: (eventName:"Grails Conf" AND location:Delhi)^2.0 OR eventName:"Grails Conference"^10 In the above query : eventName:"Grails Conference"^10 --- boosting is applied on the searched text only and weightage is 10. (eventName:"Grails Conf" AND location:Delhi)^2 ---boosting is applied on a query part and weightage is 2. Higher the weightage , higher is the priority of execution. According to my requirement I have to apply the boosting on query parts like : solrQuery = "(type:(com.threebaysover.events.Event) AND event_privacy:Public AND (event_status:Published OR event_status:Cancelled) AND (start_date:[* TO NOW] OR end_date:[* TO NOW]) AND ((connection:(${user.uniqueKey()}))^10 OR (followers:(${user.uniqueKey()}))^5 OR (company:(${currentCompanies}))^4 OR (event_partner_company:(${currentCompanies}))^2 OR (venue_company:(${currentCompanies}))^1))" In above query , priority of execution is connection > followers > company > event_partner_company > venue_company according to weightage defined. All time we have not to search for those results which fulfill the desired criteria.Sometimes our requirement is to search for those elements which are out of the desired criteria or we can say odd results. For such types of situation, there are two types of boosting provided. 1. Positive Boost : It always fetches those reults which fulfill the given condition in query. Solr and Lucene Library both provide support for positive boosts. 2. Negative Boost : It fetches those result which are negative. For example you have to search for people who are not attending an event. Solr doesn't support negative bbost while lucene do. It is implemented using query like : (eventName:"Grails Conf" AND location:Delhi)^2.0 OR -eventName:"Grails Conference"^10 Above query will fetch those results in which eventName is not "Grails Conference". Hope this will help you also. Thanks
GORM fetching mechanisms and issues Gorm provides two type of fetching mechanism using Hibernate under the hood : 1. Eager Fetching (Instant Loading) 2. Lazy Fecthing (Lazy/Late Loading) Lazy fetching is default. 1. Eager Fetching : Using this fetching mechanism the required instance along with their associated properties immediately loads into the memory but with separate db select query for associations(Internally). static mapping={ propertyName lazy : false } Another alternative to lazy : false static mapping={ propertyName fetch : 'join' // It will also load the associated objects in single query by left outer join. } Pros : It avoids extra database query to fetch other associated properties and we can directly get them from the instance immediately. Cons : It downgrade the performance of the application as the whole data is not required immediately in all the cases. 2. Lazy Fetching : Using this fetching mechanism, the associated data is fetched on the demand with the help of new separate query on database. static mapping={ propertyName lazy : true // default } Pros : No overloaded data every time, as the required things are fetched on demand. Cons : There are several issues with Lazy fetching. 1. Separate query is required to fetch the associated data. 2. It creates issue when object is deattached from session and throws LazyInitializationException. I have faced the same issue while working with a module. The required object lost from the hibernate session and no other property was available then. Ways to solve the problem : 1. Make the fetching mode "eager" but it is costly. 2. Again attach the object to the session using either of the following approach : I. merge() - Again attached the object to the session but persist the current changes to the database. User user = User.get(1) .... .... object deattched from session .... .... user = user.merge() II. attach() - Attach the object to the session again but regardless of the changes in the database. User user = User.get(1) .... .... object deattched from session .... .... user = user.attach() Using the above mentioned appraoch I am able to attach the instance to the session and it solved my problem. Hope this will also help you. Thanks
How to show timezones in GMT format in java We all required date and time along with timezones in our project at various stages like sign up,event management, time management and etc.Java provides class java.util.TimeZone to play with time zones.It provides various methods to do so. In my project, the requirement was to show the time zones in GMT format along with city name. TimeZone class provides method getAvailableIDs() which gives a string array in the following format: Pacific/Midway Pacific/Niue America/Adak Etc/GMT+10 and so on... But what I required wasall the times zones in GMT format along with city name only like : (GMT-11:00) Midway (GMT-11:00) Niue (GMT-10:00) Adak (GMT-10:00) Atka After some work around with the available list provided by getAvailableIDs(), finally I got the list in desired manner with the below code snippet : I created a custom taglib to show all the time zones in gsp : def timeZones = { attrs,body -> def allTimeZones = TimeZone.getAvailableIDs(); List timeZoneList = [] allTimeZones?.each{ def timeZone = TimeZone.getTimeZone(it) // fetch timezone object from string name long hours = TimeUnit.MILLISECONDS.toHours(timeZone?.getRawOffset()); // find hours from offset value to display // find minutes from offset value to display long minutes = TimeUnit.MILLISECONDS.toMinutes(timeZone?.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours); minutes = Math.abs(minutes); String result = ""; if (hours > 0) { result = String.format("(GMT+%d:%02d) %s", hours, minutes, timeZone?.getID()); } else if (hours < 0){ result = String.format("(GMT%d:%02d) %s", hours, minutes, timeZone?.getID()); }else{ result = "(GMT)"+' '+ timeZone?.getID(); } timeZoneList.add(result) } out << body(timeZoneList:timeZoneList) } def timeZoneDisplayName = { attrs-> def zoneName = attrs?.timeZoneName.trim() def zoneParts = zoneName.split(' ') def locationName = '' if(zoneParts[1]?.indexOf('/') == -1) locationName = zoneParts[1] else locationName = zoneParts[1].substring(zoneParts[1].lastIndexOf("/") + 1) def displayName = zoneParts[0]+' '+locationName.replace('_', ' ') out << displayName } In gsp use taglib like : <select multiple="multiple" name="timeZone" id="addTimeZone"> <event:timeZones> <g:each in="${timeZoneList}"> <option value="${it.toString().trim()}"><event:timeZoneDisplayName timeZoneName="${it}"/></option> </g:each> </event:timeZones> </select> This workaround provides me the desired data. Applying small changes you can also get the time zones in your required format if format is different from this one. THANKS