Saturday, March 12, 2022

Spring Web MVC

Front Controller : 

the concept of the Front Controller in the typical Spring Model View Controller architecture

At a very high level, here are the main responsibilities we're looking at:

  • Intercepts incoming requests
  • Converts the payload of the request to the internal structure of the data
  • Sends the data to Model for further processing
  • Gets processed data from the Model and advances that data to the View for rendering


  • DispatcherServlet plays the role of the Front Controller in the architecture.
  • The diagram is applicable both to typical MVC controllers as well as RESTful controllers
  • MVC applications are not service-oriented hence there is a View Resolver that renders final views based on data received from a Controller
  • RESTful applications are designed to be service-oriented and return raw data (JSON/XML typically). Since these applications do not do any view rendering, there are no View Resolvers – the Controller is generally expected to send data directly via the HTTP response

MVC Controller : 

@Controller
@RequestMapping(value="Test")
public class TestController{
.....
}

Rest Controller :

Maven Dependencies :  spring-web,  spring-webmvc,  jackson-databind

@Controller
public class TestController{
   @GetMapping(value = "/student/{studentId}")
    public @ResponseBody Student getTestData(@PathVariable Integer studentId) {
        Student student = new Student();
        student.setName("Peter");
        student.setId(studentId);

        return student;
    } 
}
@ResponseBody annotation on the method – which instructs Spring to bypass the view resolver and essentially write out the output directly to the body of the HTTP response.

Spring Boot - @RestController

@RestController
public class RestAnnotatedController {
    @GetMapping(value = "/annotated/student/{studentId}")
    public Student getData(@PathVariable Integer studentId) {
        Student student = new Student();
        student.setName("Peter");
        student.setId(studentId);

        return student;
    }
}
@RestController annotation from Spring Boot is basically a quick shortcut that saves us from always having to define @ResponseBody. Help by pass view rendering stage and directly writing response to HTTP response body

@RequestMapping
the annotation is used to map web requests to Spring Controller methods

Example 1 : Request Mapping with by path and HTTP method

@RequestMapping(value = "/ex/foos", method = POST)
@ResponseBody
public String postFoos() {
    return "Post some Foos";
}


Example 2 : Request Mapping and HTTP header

@RequestMapping(
  value = "/ex/foos", 
  headers = { "key1=val1", "key2=val2" }, method = GET)
@ResponseBody
public String getFoosWithHeaders() {
    return "Get some Foos with Header";
}


Example 3 : Mapping media types produced and consumed by controller

@RequestMapping(value="/method6",
produces={"application/json","application/xml"},
consumes="text/html")
@ResponseBody
public String method6(){
return "method6";
}
Above method can consume message only with Content-Type as text/html and is able to produce messages of type application/json and application/xml.


Example 4 : Request Mapping with Path Variable

@RequestMapping(value = "/ex/foos/{fooid}/bar/{barid}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariables
  (@PathVariable long fooid, @PathVariable long barid) {
    return "Get a specific Bar with id=" + barid + 
      " from a Foo with id=" + fooid;
}

Example 5 : Request Mapping with Request Parameters

@RequestMapping(value = "/ex/bars", method = GET)
@ResponseBody
public String getBarBySimplePathWithRequestParam( @RequestParam("id") long id) {
    return "Get a specific Bar with id=" + id;
}

http://localhost:8080/spring-rest/ex/bars?id=100

Example 6 :  Request Mapping with Fallback

@RequestMapping(
  value = "*", 
  method = { RequestMethod.GET, RequestMethod.POST ... })
@ResponseBody
public String allFallback() {
    return "Fallback for All Requests";
}

@RequestMapping New Shortcut Annotations

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping



Reference 1 :  Baeldung
Reference 2 :  Journal Dev


Saturday, February 19, 2022

Object Oriented Programming

 Advantages of OOP :

  • Reusability
  • OOPs is very helpful in solving very complex level of problems.
  • Highly complex programs can be created, handled, and maintained easily using object-oriented programming.
  • OOPs, promote code reuse, thereby reducing redundancy.
  • OOPs also helps to hide the unnecessary details with the help of Data Abstraction.
  • OOPs, are based on a bottom-up approach, unlike the Structural programming paradigm, which uses a top-down approach.
  • Polymorphism offers a lot of flexibility in OOPs.

Properties of OOP :

  • Encapsulation
  • Data abstraction
  • Polymorphism 
  • Inheritance 

Encapsulation vs Data Abstraction

Encapsulation is the packing of "data" and "functions operating on that data" into a single component and restricting the access to some of the object's components. Encapsulation means that the internal representation of an object is generally hidden from view outside of the object's definition.

Abstraction is a mechanism which represent the essential features without including implementation details.

Encapsulation:-- Information hiding.
Abstraction:-- Implementation hiding.


Polymorphism 

Polymorphism is composed of two words - “poly” which means “many”, and “morph” which means “shapes”. Therefore Polymorphism refers to something that has many shapes.

Types of Polymorphism 




Compile time polymorphism : method overloading

Runtime polymorphism : method overriding 


Reference :

Thursday, May 28, 2020

Java Multithreading


Why we need Threads?

  1.  Responsiveness - can be achieved with Concurrency (Multitasking)
  2.  Performance      - can be achieved with Parallelism



Context Switching
  •  Context switching is expensive 
  •  Context switching between threads is a lot cheaper than context switching between processes
  •  Too many threads - OS spending more time in management than real productive work
  •  Thread consuming less resources than processes.

Thread scheduling 
  • There are different possible of ways to schedule
    • First Come First Serve - problem with that if long threads come first other thread will be unresponsiveness, it is called starvation  
    • Short Job First - this time longest job will wait
    • Epochs -  OS divides CPU time to moderately sized pieces called Epochs.  OS allocates different time for each thread in each Epoch. It is done according to Dynamic Priority calculations. 
Thread creation & it's methods
  • Two way of creating threads
    • Implement Runnable interface provide in construction of Thread object
    • Extend Thread object
  • Number of threads should be equal to number of cores in machines
  • Use thread.setUncaughtExceptionHandler  to catch unchecked exceptions during run-time.
    You can either clean up resources or log the issue for trouble shooting purposes
  • Stopping thread from another thread has two ways
    • Thread.interrupt() - you can interrupt the thread in two scenarios
      1. If the thread is executing a method that throws an InterruptedException
      2. If the thread code is handing the interrupt signal explicitly
    • Daemon threads - background threads that do not prevent the application from exiting if the main thread terminates. Other reason , code in a worked thread is not under our control, and we do not want it to block our application from terminating
  • By default, at least if one thread is running application will not stop even main thread stopped. So we need to stop all threads gracefully
  • Thread.join() 
    • calling the join() method has a synchronization effect. join() creates a happens-before relationship
    • Happens-before :  This means that when a thread t1 calls t2.join(), then all changes done by t2 are visible in t1 on return. However, if we do not invoke join() or use other synchronization mechanisms, we do not have any guarantee that changes in the other thread will be visible to the current thread even if the other thread has completed.
    • When we invoke the join() method on a thread, the calling thread goes into a waiting state. It remains in a waiting state until the referenced thread terminates.
    • Timed join() is dependent on the OS for timing. So, we cannot assume that join() will wait exactly as long as specified.
  • In order to avoid creation/destroy of threads there is thread pooling mechanisms.

Data Sharing between Threads
  • Thread local variables are stored in stack . Like local variable and local object references
  • Shared information stored in Heap. Like Objects, class members and static variables
  • Critical section guarded with synchronized keyword. Two ways of doing this
    • synchronized on method level - Monitor

    • synchronized inside method with explicit object - lock


    • Re-entrant - thread in synchronized method/section can access to other synchronized method/section  



Atomic Operations
  • Object reference assignment - including getter, setter for exmaple
  • Primitive type assignments except long and double. Because long and double 64 bit long 
  • We can define long and double volatile.  With volatile they are guaranteed in single HW operation
  • Knowledge of atomic operations is key to us create high performance applications 

Concurrency problems
  • Race condition : two threads working on same shared object. One of them modifying the object , due to OS scheduling  it may cause incorrect results. Core of the problem is non-atomic operation performed on shared object . Solution - identifying  the critical section where race condition happened and protecting with  synchronized block.
    https://stackoverflow.com/questions/34510/what-is-a-race-condition
  • Data race : solution, establish happens-before semantics by one of these methods
    • synchronization of method
    • using volatile. No compiler re-ordering will happen. whatever code before and after volatile will run as is.
Locking Strategies
  • Coarse-grained strategy : lock whole object. Might impact the performance
  • Fine-grained strategy  : lock party of shared objects using lock object

Deadlock 
  • Condition to leads to deadlock
    • Mutual exclusion
    • Hold and wait
    • Non-preemptive allocation 
    • Circular wait
  • Solution to deadlock is avoid one the conditions mentioned above
    • Avoid circular wait - this one easiest one. 
  • Deadlock detection
    • Watchdog
    • Thread interruption 
    • tryLock operation
Reentrant Lock
  •  Similar locking with synchronized locking but provides more control over lock with advanced operations
  •  Pattern to use it
    class SharedData{
       private Lock lockObject = new ReenterantLock();

       public void method(){
            lockObject.lock();
            try{
                 userSharedObject();
           }finally(){
                lockObject.unlock();
            } 
       }
    }
  • In order to avoid starvation - one thread is continuously using shared object but other are waiting - you can set true into constructor of  ReenterantLock(true) object. which is fairness flag. But this one comes with cost. Use only when you really need it.
  • ReenterantLock.lockInterrupility()
  • ReenterantLock.tryLock()
  • ReenterantReadWriteLock - if our shared object is read intensive we can use it otherwise it can perform worse then traditional locks. Example of using read-write lock is caching where system is read intensive. Multiple read threads can access the shared object and lock it, we can see number of concurrent read threads. Only one write thread can lock the shared object no other write/read threads can access during write lock. 
Semaphore
  • Can restrict number of threads accessing to shared data.
  • similar to lock but different in many ways. 
  • One use case if Producer-Consumer using semaphore. Producer-consumer pattern used in web sockets, video streaming, Actor models
Condition variable


Other methods
  • wait
  • notify() and notifyAll()
Lock free programming
  • AtomicInteger, AtomicLong...
  • AtomicReferences




Tuesday, May 26, 2020

Java Exceptions



  • All RuntimeExceptions are unchecked exceptions rest of them are checked exceptions
  • Always use try-with-resource. In order to use objects  should implement AutoClosable
  • Exceptions are very slowly. Code running inside try-catch is performing slowly. If you have chance just use simple test (like if(!s.empty) s.pop() ) rather then guarded section
  • Throw early, catch late






Sources :




Java hashCode()

  • Objects that are equal must have the same hash code within a running process
  • Whenever you implement equals, you MUST also implement hashCode
  • Whenever two different objects have the same hash code, we call this a collision.
  • A collision is nothing critical, it just means that there is more than one object in a single
    bucket, so a HashMap lookup has to look again to find the right object. A lot of collisions will degrade the performance of a system, but they won’t lead to incorrect results.
  • It is good to generate same hash code in different execution of programs but you should not relay on this. String and Integer are generating same hash code always will be same.But while most of the hashCode implementations provide stable values, you must not rely on it.here are Java libraries that actually return different hashCode values in different processes and this tends to confuse people. Google’s Protocol Buffers is an example.
  • Do not use hashCode in distributed applications
  • You may know that cryptographic hash codes such as SHA1 are sometimes used to identify objects (Git does this, for example). Is this also unsafe? No. SHA1 uses 160-bit keys, which makes collisions virtually impossible. Even with a gigantic number of objects, the odds of a collision in this space are far below the odds of a meteor crashing the computer that runs your program. This article has a great overview of collision probabilities.
  • A cryptographic hash such as MD5 or SHA-1 would be ok for many cases, but might be a bit heavyweight if you’re dealing with a really high-throughput service.

Sources