Δευτέρα 2 Δεκεμβρίου 2024

Exception handling with Spring Boot

 EXCEPTION HANDLING WITH SPRING BOOT



1. Use @ResponseStatus for simple cases




When ResourceNotFoundException get thrown, client will get a 404 status code.



2. Use @ControllerAdvice for Centralized Exception Handling



  • @ControllerAdvice handler intercepts exceptions thrown from any controller.
  • With ResponseEntity, we can return custom error messages, objects, HTTP status codes and response bodies.



3. ErrorResponse custom pojo class


     Moreover, we can define an ErrorResponse custom pojo model to include in                         ResponseEntity:






4. Include validation errors in ResponseEntity




    We can stream all errors gathered, into an ErrorResponse's errorMessage string value.




5. Map custom exceptions to error codes for API integrity




In our CustomBusinessException we link a specific Error Code (e.g. ERROR_1)
Then, we add it in ErrorResponse and to ResponseEntity.

That way, clients that consume our API will have a clear matching between our backend errors and an identifying reason (error code)





Κυριακή 1 Δεκεμβρίου 2024

Microservices with Spring Cloud

MICROSERVICES WITH SPRING CLOUD





CONFIG - EUREKA - GATEWAY - BOOK-SERVICE





CONFIG SERVER


We centralize all application properties of business microservices, plus Eureka and Gateway


       Simple business service              

         book-service properties:




    Eureka / Discovery Server:
     All services register here. When service1 looks for service2, it looks up Eureka server           first.

     Eureka server properties:



   Gateway server:
    Provides one unified "gateway" / reverse proxy for our clients to make easy requests to        services, without complex configurations or CORS issues.
           
    Gateway server properties:




EUREKA 


 bootstrap.properties:





BOOK-SERVICE 


 bootstrap.properties:






GATEWAY


 bootstrap.properties:




Gateway uses Eureka (service discovery). 
This allows the gateway to dynamically resolve service instances.

Τρίτη 22 Αυγούστου 2023

Overview - Run embedded Keycloak with Spring Boot

             Run embedded Keycloak with Spring Boot



No need to download and setup Keycloak locally. To run embedded Keycloak, we need generally to:

1.
Create a json for our Keycloak:





2.

Import maven dependencies and plugin in pom:


        <dependency>

            <groupId>org.jboss.resteasy</groupId>

           <artifactId>resteasy-jackson2-provider</artifactId>

            <version>${resteasy.version}</version>

        </dependency>


        <dependency>

            <groupId>org.keycloak</groupId>

            <artifactId>keycloak-dependencies-server-all</artifactId>

            <version>${keycloak.version}</version>

            <type>pom</type>

        </dependency>

        

        <dependency>

            <groupId>org.keycloak</groupId>

            <artifactId>keycloak-crypto-default</artifactId>

            <version>${keycloak.version}</version>

        </dependency>


        <dependency>

            <groupId>org.keycloak</groupId>

            <artifactId>keycloak-admin-ui</artifactId>

            <version>${keycloak.version}</version>

        </dependency>


        <dependency>

            <groupId>org.keycloak</groupId>

            <artifactId>keycloak-services</artifactId>

            <version>${keycloak.version}</version>

        </dependency>

    

         <dependency>

    <groupId>org.keycloak</groupId>

    <artifactId>keycloak-rest-admin-ui-ext</artifactId>

    <version>${keycloak.version}</version>

 </dependency>


...


  <plugin>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-maven-plugin</artifactId>

                <configuration>

                    <mainClass>com.codeinpackets.auth.

                         AuthorizationServerApp</mainClass>

                    <requiresUnpack>

                        <dependency>

                            <groupId>org.keycloak</groupId>

                            <artifactId>keycloak-model-jpa</artifactId>

                        </dependency>

                    </requiresUnpack>

                </configuration>

            </plugin>



3.
In our application yml, where we mention the json:


server:
  port: 8083

keycloak:
  server:
    contextPath: /auth
    adminUser:
      username: cip-admin
      password: pass
    realmImportFile: cip-realm.json



4.
Create a config properties class to bind our properties above:

@ConfigurationProperties(prefix = "keycloak.server")
public class KeycloakServerProperties {


    String contextPath = "/auth";
    String realmImportFile = "cip-realm.json";
    AdminUser adminUser = new AdminUser();


    // getters, setters
    public String getContextPath() {
        return contextPath;
    }
    public void setContextPath(String contextPath) {
        this.contextPath = contextPath;
    }
    public AdminUser getAdminUser() {
        return adminUser;
    }
    public void setAdminUser(AdminUser adminUser) {
        this.adminUser = adminUser;
    }
    public String getRealmImportFile() {
        return realmImportFile;
    }
    public void setRealmImportFile(String realmImportFile) {
        this.realmImportFile = realmImportFile;
    }
    public static class AdminUser {
        String username = "admin";
        String password = "admin";
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
}



5.
Finally bind and run all together:

@SpringBootApplication
@EnableConfigurationProperties({ KeycloakServerProperties.class })
public class AuthorizationServerApp {


private static final Logger LOG = LoggerFactory.getLogger(AuthorizationServerApp.class);


public static void main(String[] args) throws Exception {
SpringApplication.run(AuthorizationServerApp.class, args);
}

// Log and verify Keycloak runs fine:
@Bean
ApplicationListener<ApplicationReadyEvent> onApplicationReadyEventListener(ServerProperties serverProperties,
KeycloakServerProperties keycloakServerProperties) {


return (evt) -> {
Integer port = serverProperties.getPort();
String keycloakContextPath = keycloakServerProperties.getContextPath();
LOG.info("Embedded Keycloak server has started, use http://localhost:{}{}", port, keycloakContextPath);
};
}
}

Δευτέρα 21 Αυγούστου 2023

@ConstructorBinding in Spring Boot

                  @ConstructorBinding in Spring Boot 3



This annotation is no longer needed along with @ConfigurationProperties classes. If there's at least one constructor, Spring Boot implicitly uses constructor binding for our properties.



@ConfigurationProperties(prefix = "mail.credentials")

public class ImmutableCredentials {


    private final String authMethod;

    private final String username;

    private final String password;


    public ImmutableCredentials(String authMethod, String username, String password) {

        this.authMethod = authMethod;

        this.username = username;

        this.password = password;

    }


    public String getAuthMethod() {

        return authMethod;

    }


    public String getUsername() {

        return username;

    }


    public String getPassword() {

        return password;

    }

}


Only if we have multiple constructors, we have to use it on the prefered constructor:


@ConfigurationProperties(prefix = "mail.credentials")

public class ImmutableCredentials {


    private final String authMethod;

    private final String username;

    private final String password;

 

// constructor 1

    @ConstructorBinding

    public ImmutableCredentials(String authMethod, String username, String password) {

        this.authMethod = authMethod;

        this.username = username;

        this.password = password;

    }


// constructor 2

    public ImmutableCredentials(String authMethod, String username) {

        this.authMethod = authMethod;

        this.username = username;  

    }


    public String getAuthMethod() {

        return authMethod;

    }


    public String getUsername() {

        return username;

    }


    public String getPassword() {

        return password;

    }

}




       @ConstructorBinding was introduced in Spring Boot 2.2


Before version 2.2 one could only use setters to bind properties with Java fields. But after 2.2, this annotation was introduced to allow binding the properties via a parameterized constructor.




Sources:

Spring docs - Constructor Binding

Spring docs - ConfigurationProperties

Spring Boot 3 - Constructor Binding





Σάββατο 4 Φεβρουαρίου 2023

Project Valhalla Value objects and user-defined primitives



PROJECT VALHALLA: VALUE OBJECTS AND USER-DEFINED PRIMITIVES




THE PROBLEM

In a project there are classes that don't have any use for identity and their field values can be permanently set once on instantiation, and thus their instances don't need any synchronization and other OOP related optimizations.

However, by default they act like identity components and at runtime, the support for identity can be expensive. Particular memory location is required for object's data and extra metadata to support the object's functionalities.


PROJECT VALHALLA  

An alternative approach is to represent program data using primitive data types. As primitive values do not have a unique identity, they can be easily copied and efficiently stored as compact bit sequences. At the same time, we want to retain object-oriented semantics.

That said, the purpose here is to "augment the Java object model with value objects and user-defined primitives, combining the abstractions of OOP with the performance characteristics of primitives".



VALUE CLASSES


Value classes will be the bridge between the OOP benefits and primitives' performance.

With Valhalla, the JVM will try inlining value objects where possible. These value objects will be encoded directly   with its primitive field values, avoiding any overhead from object headers, indirections, or heap allocation.

As a non-goal of the related JEP, the Value classes will be reference types, stored in memory and can  be pointed to by multiple variables.


Structure:

   value class Shape {

     int x;

     int y;

   }

  ,where "value" dictates that the class and its fields would be Final, just like the regular VO objects.Value classes contain only primitives.


Being Final, they are immutable, and thus, lack identity:

In Java, final classes are unable to be altered after they have been created, making them immutable. This means that the values stored within their fields cannot be modified, and any attempts to do so will result in an error. This is why final classes lack identity, as their values cannot be changed, and thus their identity cannot be changed.

Subsequently we can compare Value class instances only by comparing all their field values. 


To summarize:

Value classes provide programmers with a mechanism to opt out of object identity, and in return get many of the performance benefits of primitive types, without giving up the other features of Java classes.

They cannot mutate, synchronize, and lack identity.

Value objects significantly improve object performance in many contexts, providing a good fusion of the better abstractions of objects with the better performance of primitives.


Value Classes drawbacks:

Value classes being the middle ground between objects and primitives, they present some drawbacks when used as fields or in arrays:

  • A variable of a Value type could be null, so we require additional bits to encode null.
  • As reference types, Value objects' variables must be modified atomically, so it not practical to inline Value objects.
Specifically, in an array with Value objects, there's still indirections and references to all elements that need memory usage:



This can be improved using Primitive classes, where possible:



PRIMITIVE CLASSES


A primitive class is a special kind of value class that introduces a new composite primitive type. Using class features, we can create a new primitive type containing other primitives. Primitive objects will be stored in stack as a unit, thus supporting a null-free flattened storage, and improved performance.

Contrary to Value classes, Primitive ones are more performant for arrays, as they have no references.They are stored directly in stack memory.

Structure:


Note the "primitive" keyword.

Primitive classes also have class methods to perform any calculations inside the object, ensuring encapsulation like in DDD design.

Primitive classes will come handy in the case of e.g. arrays, where their advantage over Value classes is the lack of indirections. In addition no null encoding needs exist, and atomic modification in also not needed as primitives stored in stack:

A memory layout of a Primitive array:



Primitive members are flattened memory-wise, and no extra pointers are needed.



CLASSES FOR THE BASIC PRIMITIVES


Project Valhalla is an initiative which seeks to migrate the Wrapper classes (java.lang.Integer, java.lang.Double, etc.) to become primitive classes. This is done in order to reduce the overhead of modeling primitive values with classes and offer the capabilities of class types for the basic primitives, with many details delegated to the standard library. Starting from Java 5, primitive values can be stored in the Wrapper classes and represented as objects, although there are drawbacks such as runtime costs and the potential for boxing identical values leading to two objects being unequal. JEP 401 outlines the improvements that will be made with the implementation of Project Valhalla.


ENHANCED GENERICS


To maintain the performance benefits of using primitives, existing frameworks and libraries have resorted to creating specializations such as IntStream<T> or ToIntFunction<T>. Currently, to use language primitives generically, we use boxed types, like Integer for int or Float for float, which introduces an extra layer of indirection and negates the purpose of using primitives. Enhanced generics is an effort to eliminate this workaround and allow generic types to be applied to object references, primitives, value types, and possibly even void.


SOURCES:


Official doc:

https://openjdk.org/projects/valhalla/

https://en.wikipedia.org/wiki/Project_Valhalla_(Java_language)

https://openjdk.org/jeps/8277163

https://openjdk.org/jeps/401