Τρίτη 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

Παρασκευή 20 Ιανουαρίου 2023

Concurrency with Synchronized keywork and Atomic classes


 
ACHIEVING SYNCHRONIZATION
 FOR A SHARED INSTANCE BETWEEN MULTIPLE THREADS



Lets suppose we have many threads operating simultaneously on an SynchronizationWith instance which increments a counter by 1 

But we don't want 2 or more to operate at the same time

Because this will create inconsistencies on our controlled adding - counter may increase faster and lose a value. 

So, only one thread should have access to read and write at each moment.

The next thread should get the last value and increment/write on it.

And so on.



THREADS AND MAIN MEMORY








WITH SYNCHRONIZED KEYWORD



Class/Instance for incrementing counter

public class SynchronizationWithSynchronizedKeyword {
private int counter;

int getValue() {
return counter;
}

synchronized void incrementBy1() {
counter++;
}
}

- Synchronized keyword will:

    - Stop other threads from accessing (locking)
    - Read the last value from the main memory
    - Increment it by 1
    - Write the new value in shared memory




Testing

@Test
public void test1() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(3);
SynchronizationWithSynchronizedKeyword syncWithKeyword = new SynchronizationWithSynchronizedKeyword();

IntStream.range(0, 1000).forEach(count -> service.execute(syncWithKeyword::incrementBy1));
shutdownAndAwaitTermination(service);

assertEquals(1000, syncWithKeyword.getValue());
}
- Shared instance: syncWithKeyword
- We initiate 1000 Runnable tasks via a 3-Thread pool
- These tasks reference the shared instance's increment method
- To pass test, each task should increase the counter variable by 1, adding totally to 1000.



Helper method to gracefully shutdown the executor threads
private void shutdownAndAwaitTermination(ExecutorService pool) {
// Disable new tasks from being submitted
pool.shutdown();
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS)) {
// Cancel currently executing tasks forcefully
pool.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(100, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ex) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Result: Success





WITH ATOMIC VARIABLE CLASSES



Class/Instance for incrementing counter
public class SynchronizationWithAtomicClasses {
private final AtomicInteger counter = new AtomicInteger(0);

int getValue() {
return counter.get();
}

void incrementBy1() {
counter.incrementAndGet();
}
}
- AtomicInteger's incrementAndGet when called from a thread, will (atomic operation) :

    - Stop other threads from accessing (locking)
    - Read the last value from the main memory
    - Increment it by 1
    - Write the new value in shared memory



Testing

(Same as above)
@Test
public void test2() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(3);
SynchronizationWithAtomicClasses syncWithAtomic = new SynchronizationWithAtomicClasses();

IntStream.range(0, 1000).forEach(count -> service.execute(syncWithAtomic::incrementBy1));
shutdownAndAwaitTermination(service);

assertEquals(1000, syncWithAtomic.getValue());
}
Result: Success