Tuesday, February 21, 2023

@ControllerAdvice against @ExceptionHandler and using @Order

 Being Each ExceptionHandler is limited to controller. In the case of where multiple controllers exists, @ExceptionHandler using will not be affective and increase duplicate code.

To get Global Exception Handling

Application -wide across all controllers and all exceptions


- While handling it is good to create package-level handlers

- Control the controllers by their annotations (global handling specific to some controllers by include/exclude)


@ControllerAdvice : comes from Aspect Programming

This is single advice across application wide

can also create domain level (scope level)


While writing:

- Mark with @ControllerAdvice

- Add one or many @ExceptionHandler for specific/group of exceptions like @ExceptionHandler

- Can also add catch all exception handler (Refer @Exceptionhandler post)

like below



Spring Provides @ControllerAdvice 

and

@RestControllerAdvice (This is @ControllerAdvice + @ResponseBody) - for REST Services


Topic 6:

Scoping the ControllerAdvice for particular packages also can be done so that this global handler is applicable for only the packages.



to assign to only set of controllers not to packages then



PLEASE NOTE THAT , WE SHOULD NOT HAVE MULTIPLE @CONTROLLERADVICES IN ONE APPLICATION. TO MAKE IT THERE SHOULD BE MORE CARE NEED TO BE TAKEN CARE LIKE USING PRIORITY, ETC., GENERALLY IT IS NOT RECOMMENDED AS IT IS NOT PREDICTABLE


Topic 7:

When multiple ControllerAdvices are present , it will be picked up in Alphabetical order (Please check in your system). As this is not predictable, "Order" annotation can be used to set the order. Generally takes integer value



as these values are integers ranging min to max. value can be given as integer to set the order



Exception Handler

 To make method mark with @ExceptionHandler

Accepts parameters to help with the exception handling and provide response.

Sample Exception handler 

- use the annotation

- pass the exception that this exception hanlder function handles as an argument

- below is handled for indexoutofboundexception


If we add this in controller: Then this will become global exception for that controller class

Can add @ResponseStatus to return desired HTTP Error code


Now when Controller gets this exception, it also return "Oops, something went wrong@ along with HTTP Error Code 400 as provided with @ResponseStatus above


Topic 3:

Controller can have multiple exception handler to handle different exceptions.

One is to add all exceptions as below, which is not practically possible in many cases



OR make indepeent handler so that we can customize the error code 




and by adding below to cover all other unhandled exceptions.



Topic  4)

To  embed some content from request recived  in response while handling exceptions, we can use HttpServletRequet  and Exception e value can be used to log to know about the exception





FAQ :

Q) Can I use ExceptionHandler annotation in any class?

Ans:

The @ExceptionHandler annotation is used in Spring Framework to define a method that handles exceptions thrown by a controller method.

In order to use the @ExceptionHandler annotation, the method that handles the exception should be defined within a class annotated with @ControllerAdvice or @RestControllerAdvice. These annotations allow the class to handle exceptions across multiple controller classes.

So, the answer is no, you cannot use the @ExceptionHandler annotation in any class. It should only be used within a class annotated with @ControllerAdvice or @RestControllerAdvice.

webclient mono and block



What is the purpose of java webclient using bodytomono along with block

Ans:



In Java's Reactive Streams API, WebClient is a non-blocking, reactive HTTP client that allows you to make HTTP requests to a server and receive the response in a reactive manner.

bodyToMono() is a method in the WebClient.ResponseSpec interface that allows you to extract the response body as a Mono, which is a reactive stream that emits exactly one item or an error signal. You can use this method to obtain the response body as a Mono of a specific type, such as a String or a custom Java object.

The block() method is a method on the Mono interface that blocks the current thread until the mono completes, and then returns the emitted value or propagates any error. It's useful when you need to obtain the result of a reactive stream in a synchronous, blocking way.

So, when you use bodyToMono() along with block() in WebClient, you are essentially making a non-blocking HTTP request to a server, and then waiting for the response to be received and the response body to be extracted as a Mono of a specific type. The block() method is used to block the current thread until the response is received, and then returns the extracted response body as the specified type.

However, it's important to note that using block() in a reactive application can have negative performance implications, as it may cause thread blocking and disrupt the flow of reactive streams. In general, it's best to avoid using block() whenever possible and instead use reactive operators to process the emitted values of reactive streams.


o in Java Webclient


Venkata Ratnam
What is purpose of mono while using java webclient request with an example


2 / 2

As an AI language model, I cannot be certain about what the user is trying to ask. However, I will try my best to provide some general information about Mono in the context of Java WebClient request.

Mono is a reactive programming library that allows you to work with asynchronous streams of data. It is commonly used in Java web applications to handle non-blocking I/O and handle requests efficiently.

When using Java WebClient to make HTTP requests, you can use Mono to handle the response asynchronously. For example, consider the following code snippet:

Mono<String> result = webClient.get()
  .uri("https://example.com")
  .retrieve()
  .bodyToMono(String.class);

result.subscribe(System.out::println);

In this example, the bodyToMono method returns a Mono that represents the HTTP response body as a String. You can then subscribe to this Mono to get the result of the request asynchronously.

By using Mono, you can make your Java web application more responsive and handle multiple requests efficiently.

Or

Mono<String> result = webClient.get()
  .uri("https://example.com")
  .retrieve()
  .bodyToMono(String.class)
  .block()

To make block and no subscribe is required

Singleton Java

Java Singleton Approaches


Venkata Ratnam
What is the better approach of using Singleton in Java? Is it to use Bean annotation or user defined function with synchronized .

Can you explain with an example 


2 / 2

No preferences.. But I can explain the two approaches with examples.

Using Bean annotation:
This approach involves using the Spring Framework's @Bean annotation to define a singleton bean. Here's an example:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfiguration {
    
    @Bean
    public MySingletonClass mySingletonClass() {
        return new MySingletonClass();
    }
}



In this example, the MySingletonClass will be instantiated only once, and Spring will manage its lifecycle.

Using user-defined function with synchronized:
Using user-defined function with synchronized:
This approach involves using a user-defined function to create and manage the singleton instance. Here's an example 
.
public class MySingletonClass {

    private static MySingletonClass instance;

    private MySingletonClass() {
    }

    public static synchronized MySingletonClass getInstance() {
        if (instance == null) {
            instance = new MySingletonClass();
        }
        return instance;
    }
}

In this example, the getInstance() method creates the singleton instance and ensures that only one instance is created. The synchronized keyword ensures that the method is thread-safe.

Both approaches have their advantages and disadvantages. The @Bean annotation is more concise and easier to read, but it requires the use of the Spring Framework. The user-defined function approach is more flexible, but it requires more code and is more error-prone.


________________&&&&&&&&_______________

What are the bugs in below Singleton java code?
Can you correct this by fixing bugs? 

public class MySingletonClass {

    private static MySingletonClass instance;

    private MySingletonClass() {
    }

    public static synchronized MySingletonClass getInstance() {
        if (instance == null) {
            instance = new MySingletonClass();
        }
        return instance;
    }
}


2 / 2

The code for the singleton class seems correct in terms of achieving the singleton design pattern, but it has a few bugs that can be improved. Here are the bugs and their solutions:

Not using double-checked locking: When multiple threads are involved, the current code can lead to race conditions, where two or more threads try to create an instance of the class simultaneously, resulting in multiple instances of the singleton class. To avoid this, we can use double-checked locking.

Not using volatile keyword: In the current code, the instance variable is not declared volatile, which means that changes made to it by one thread may not be visible to other threads. To ensure that changes to the instance variable are visible to all threads, we can declare it as volatile.

Here's the corrected code for the MySingletonClass:

public class MySingletonClass {
    
    private static volatile MySingletonClass instance;
    
    private MySingletonClass() {
    }
    
    public static MySingletonClass getInstance() {
        if (instance == null) {
            synchronized (MySingletonClass.class) {
                if (instance == null) {
                    instance = new MySingletonClass();
                }
            }
        }
        return instance;
    }
}


And

above code is a basic implementation of Singleton in Java, but there are some potential bugs or issues that can arise in certain situations. Here are some of them:

Multi-threading issue: If multiple threads access the getInstance() method at the same time, there is a possibility of creating multiple instances of the class. To avoid this, we can make the method synchronized to ensure only one thread can access it at a time.

Reflection: A singleton instance can be created using reflection, which can bypass the getInstance() method and create a new instance. To prevent this, we can throw an exception from the constructor if an instance already exists.

Serialization: If a singleton class is serialized and then deserialized, it creates a new instance of the class. To prevent this, we can implement the readResolve() method and return the existing instance instead of creating a new one.

Cloning: If a singleton class is cloned, it creates a new instance of the class. To prevent this, we can override the clone() method and throw an exception.

Garbage collection: If a singleton class is not used for a long time, it may be garbage collected. To prevent this, we can use a static variable to hold the instance, so that it won't be garbage collected.

Subclassing: A subclass of a singleton class can be created, which will create a new instance of the class. To prevent this, we can make the constructor private and final, so that it can't be subclassed.

In summary, the basic implementation of the singleton pattern has some potential bugs that need to be addressed to ensure that it functions correctly in all situations.



Monday, February 20, 2023

Using Template Page for error handling with ThymeLeaf

 

1) To use thymeLeaf add dependency in POM



2) Add a new file in resources/templates (Probably a static html page with error.html)

3) Check if any applicatoin.properties need to be added


and

if we want to response with our own HTTP Error code: @ResponseStatus  Annotation can be used

where when user tries access the end point /people/{id} then along with the function result, it returns HTTP error code as Not found (404)


To be practical we can do this when any exception is raised in the applicable as below



results 404 with the along with message "Cound not find the person" as message. Exception is there because the site.properties is not having the values which are explained in previous posts.




Exception handling in Spring using ErrorControler interface

 1) Using try and catch


Checked Exceptions needs to be handled by using try/catch or by using throws.


3) Template Pages

- Error code based HTML Pages

- Replaces the default whitelable page

- Can use template enginers like Thymeleaf of Spring

- pages can be static or dynamic 

- Best way is also is by using Spring Annotations (examples uses Spring 5 SDK)


3A) While label page - Below error came when user tried to access unavailable page


DANGERS OF ABOVE page:

it shows that application dont have /error page. 

As the page is not available it showed .. 

in case of exception at applicatoin, this shows all stack trace and exposes the sensitive info to user like below


 i) We can solve this also by using application.properties:by adding 


we get below without stack trace



ii) and by adding both as below we wont see the message also



as below



iii) We can also re-direct to default page in case of error (routing to default end point) . Below configuration server.error.path allows, when the error scenario occurs the default end point which is configured (here /people) will be called.

But the HTTP Error code is 500 (Internal Server error)


The above is works for REST ful interface (But if accessing web browser, the empty page will come but not the result of default end point). But it wont expose the stack trace and message. Becaue the error page while accessing using web browser is coming from Tomcat and not from applicatoin. (as below)

So, for error page tomcat configuratoin can be done.



4) To maintain same error information whether it is accessible using REST or Web interface: is 

in Spring is  implementing ErrorController interface.

which is our own Error Controller

Map the error page to error page so that all exceptions will point to the page Or error end point.

Here we can implement and return how we want it 

and

this is applicable for all error exceptions (Global error handling) . So that sensitive stack trace wont be exposed to the end user



using Browser


Using Postman REST



Do you know?

 - adding

debug=true

in applicatoin.properties 

not only prints debug level information 

and

also it prints autocongiruation report. (Which matched and which does not match)

Thursday, February 16, 2023

Lombok Sample @SneakyThrows along with Generated Code

 



import lombok.SneakyThrows;

public class FileUtilsSneakyThrows {

@SneakyThrows
public static String readFile(File file) {
byte[] bytes = new byte[(int) file.length()];
FileInputStream input = new FileInputStream(file);
input.read(bytes);
return new String(bytes);
}

public static void main(String[] args) {
File file = new File("test.txt");
String content = FileUtilsSneakyThrows.readFile(file);
System.out.println(content);
}

}


Generated:

import java.io.File;
import java.io.FileInputStream;

public class FileUtilsSneakyThrows {
public FileUtilsSneakyThrows() {
}

public static String readFile(File file) {
try {
byte[] bytes = new byte[(int)file.length()];
FileInputStream input = new FileInputStream(file);
input.read(bytes);
return new String(bytes);
} catch (Throwable var3) {
throw var3;
}
}

public static void main(String[] args) {
File file = new File("test.txt");
String content = readFile(file);
System.out.println(content);
}

} 

 

Lombok Sample @Builder along with Generated Code

@Builder is an annotation provided by Lombok that can help reduce boilerplate code for creating objects with a builder pattern. The builder pattern is a design pattern that separates the construction of an object from its representation. This allows for more readable and maintainable code, as well as providing more flexibility in object creation.

With @Builder, Lombok generates code that allows you to create instances of a class using a fluent API. The generated code includes a builder class that has methods for setting the values of the class's fields, and a build() method that creates and returns an instance of the class. 


Usage: 

Movie movie = Movie.builder()
.Name("RRR")
.Year(2022)
.build();


Example:

import lombok.Builder;

@Builder
public class PersonBuilder {
        String Name;
        int Age;
}

Generated :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public class PersonBuilder {
String Name;
int Age;

PersonBuilder(final String Name, final int Age) {
this.Name = Name;
this.Age = Age;
}

public static PersonBuilder.PersonBuilderBuilder builder() {
return new PersonBuilder.PersonBuilderBuilder();
}

public static class PersonBuilderBuilder {
private String Name;
private int Age;

PersonBuilderBuilder() {
}

public PersonBuilder.PersonBuilderBuilder Name(final String Name) {
this.Name = Name;
return this;
}

public PersonBuilder.PersonBuilderBuilder Age(final int Age) {
this.Age = Age;
return this;
}

public PersonBuilder build() {
return new PersonBuilder(this.Name, this.Age);
}

public String toString() {
return "PersonBuilder.PersonBuilderBuilder(Name=" + this.Name + ", Age=" + this.Age + ")";
}
}
}

Lombok Sample @Data along with Generated Code

 @Data, on the other hand, generates boilerplate code for a class that includes fields, getters, setters, equals, hashCode, and toString methods.

Original: 

 import lombok.Data;


@Data
public class Person1 {
String name;
int age;
}


Generated :


//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
public class Person1 {
String name;
int age;

public Person1() {
}

public String getName() {
return this.name;
}

public int getAge() {
return this.age;
}

public void setName(final String name) {
this.name = name;
}

public void setAge(final int age) {
this.age = age;
}

public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Person1)) {
return false;
} else {
Person1 other = (Person1)o;
if (!other.canEqual(this)) {
return false;
} else if (this.getAge() != other.getAge()) {
return false;
} else {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}

return true;
}
}
}

protected boolean canEqual(final Object other) {
return other instanceof Person1;
}

public int hashCode() {
int PRIME = true;
int result = 1;
int result = result * 59 + this.getAge();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}

public String toString() {
return "Person1(name=" + this.getName() + ", age=" + this.getAge() + ")";
}

} 

Lombok Sample @Value along with Generated Code

@Value and @Data are both annotations provided by Lombok that can help reduce boilerplate code in Java applications.

@Value is used to create immutable objects with final fields, getter methods, and a constructor that accepts all fields as arguments. This annotation automatically generates the following code for a class:

  • A private final field for each non-static field in the class
  • A public getter method for each field
  • A constructor that accepts all fields as arguments
  • An equals method that compares all fields for equality
  • A hashCode method that uses all fields to generate a hash code
  • A toString method that includes the class name and all field values


Original Code: 

import lombok.Value;

@Value
public class Person {
String name;
int age;
}

Generated Code:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

public final class Person {
private final String name;
private final int age;

public Person(final String name, final int age) {
this.name = name;
this.age = age;
}

public String getName() {
return this.name;
}

public int getAge() {
return this.age;
}

public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Person)) {
return false;
} else {
Person other = (Person)o;
if (this.getAge() != other.getAge()) {
return false;
} else {
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}

return true;
}
}
}

public int hashCode() {
int PRIME = true;
int result = 1;
int result = result * 59 + this.getAge();
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}

public String toString() {
return "Person(name=" + this.getName() + ", age=" + this.getAge() + ")";
}

}