SGI, NCSA Mosaic, Sun, Java, JSF, Java EE, Jakarta EE and Clouds--an airhacks.fm podcast

Subscribe to airhacks.fm podcast via: spotify| iTunes| RSS

The #161 airhacks.fm episode with Ed Burns (@edburns) about:
SGI, NCSA Mosaic, early Java, Swing, Project Moonwalk, JSF, J2EE, Java EE and Jakarta EE
is available for

Building Reusable "Cloud Components" / Constructs with AWS CDK, Java and Maven

An AWS CDK construct encapsulates a reusable piece of cloud infrastructure. In our example it is the Amazon Elastic Container Registry :


import software.amazon.awscdk.services.ecr.Repository;
import software.constructs.Construct;

public class AirhacksECR extends Construct {

    private Repository repository;

    public AirhacksECR(Construct scope, String id, String repositoryName) {
        super(scope, id);
        this.repository = Repository.Builder.create(scope, id + "-ecr")
            .imageScanOnPush(true)
            .repositoryName("airhacks/" + repositoryName)
            .build();
    }
    
    public Repository getRepository() {
        return this.repository;
    }
}    

Such a construct can be compiled and deployed (mvn install) into a local or remote Maven repository, but requires the declaration of the following dependencies:


<dependency>
    <groupId>software.amazon.awscdk</groupId>
    <artifactId>aws-cdk-lib</artifactId>
    ...recent version
</dependency>
<dependency>
    <groupId>software.constructs</groupId>
    <artifactId>constructs</artifactId>
    ...recent version
</dependency>

Let's assume the construct's GAV coordinates are:


<groupId>airhacks</groupId>
<artifactId>ecr</artifactId>
<version>0.1</version>

After a successful compilation and deployment, the construct becomes available to other CDK projects via the following dependency:


<dependency>
    <groupId>airhacks</groupId>
    <artifactId>ecr</artifactId>
    <version>0.1</version>
</dependency>

Now an opinionated AWS ECR registry can be created via the AirhacksECR construct:


import software.constructs.Construct;
import airhacks.ecr.AirhacksECR;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

public class CDKStack extends Stack {

    public CDKStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        var ecr = new AirhacksECR(this, id, "live");
        var repository = ecr.getRepository();
    }
}

See it in action - deployment included:

The template: https://github.com/adambien/aws-cdk-plain was used in both projects.

RAM, AWS Lambda and Java's Parallelism

On my i9 laptop, Java reports 16 available CPUs:


jshell> Runtime.getRuntime().availableProcessors()
$1 ==> 16    

Which value can we expect on AWS Lambda?

The more RAM you configure for an AWS Lambda function, the more vCPU(s) you get:

Lambda allocates CPU power in proportion to the amount of memory configured. Memory is the amount of memory available to your Lambda function at runtime. You can increase or decrease the memory and CPU power allocated to your function using the Memory (MB) setting. To configure the memory for your function, set a value between 128 MB and 10,240 MB in 1-MB increments. At 1,769 MB, a function has the equivalent of one vCPU (one vCPU-second of credits per second). from https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-memory-console

With the minimal configuration of 128 MB RAM you get only a fraction of a vCPU, and with 1,769 MB RAM a whole vCPU.

What value the following AWS Lambda will report with the 128 MB configuration?


public class Greetings{

    public String onEvent(Map<String,String> input) {
        var processors = Runtime.getRuntime().availableProcessors();
        return String.format("available processors %s ", processors);
    } 
}    

Although, you only have a fraction of the vCPU available, Lambda function returns:


"available processors 2"
With the RAM setting of 10 GB (10240), the AWS Lambda returns: available processors 6 and with 5 GB (5120): "available processors 3"

ForkJoinPool's and parallelStream() are also relying on the number of available CPUs to configure Java's parallelism. On AWS Lambda with 128MB memory you only get a fraction of CPU, but Runtime.getRuntime().availableProcessors() will report 2 which will lead to a more parallelism than expected.

The sample code is available as template from: https://github.com/AdamBien/aws-lambda-cdk-plain.

Modules Are Needed, But Not Easy--an airhacks.fm podcast

Subscribe to airhacks.fm podcast via: spotify| iTunes| RSS

The #160 airhacks.fm episode with Ondrej Mihályi (@OndroMih) about:
the benefits and challenges of modules, BCE, OSGi, and Payara on kubernetes and in the clouds
is available for

Serializing and Deserializing Java Records with "stock" Jakarta EE 9 JSON-B

To serialize a Java Record with "stock" JSON-B (Jakarta 9 JSON Binding), you will have to declare a dependency (or use an implementation which ships with your runtime) to a JSON-B implementation:


<dependency>
    <groupId>org.eclipse</groupId>
    <artifactId>yasson</artifactId>
    <version>2.0.2</version>
</dependency>    

A Java Record:


public record Workshop(String title, Date date, String description) {
}    

can be serialized by configuring JSON-B to use private fields with a custom PropertyVisibilityStrategy:


public class PrivateVisibilityStrategy implements PropertyVisibilityStrategy {
    @Override
    public boolean isVisible(Field field) {
        return true;
    }
    @Override
    public boolean isVisible(Method method) {
        return false;
    }
}     

The PrivateVisibilityStrategy has to be passed to JsonbConfig:


import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;

public interface Mapper {

    final static JsonbConfig config = new JsonbConfig()
            .withFormatting(true)
            .withPropertyVisibilityStrategy(new PrivateVisibilityStrategy());

    static String save(Workshop workshop) {
        var jsonb = JsonbBuilder.create(config);
        return jsonb.toJson(workshop);
    }
        
}    

To read the Workshop record back, you will have to create a factory method annotated with @JsonbCreator:


public record Workshop(String title, Date date, String description) {

    @JsonbCreator
    public static Workshop create(String title, Date date, String description) {
        return new Workshop(title, date, description);
    }
}

The Jakarta JSON-B runtime will use the factory method instead of the default constructor to create a record instance and populate it with the JSON data. The parameter names have to be available for reflection. Either make the parameter names available via a compiler switch: (<maven.compiler.parameters>true</maven.compiler.parameters>) or directly annotate the parameters:


import jakarta.json.bind.annotation.JsonbProperty;

//...
@JsonbCreator
public static Workshop create(@JsonbProperty("title") String title, 
                              @JsonbProperty("date") Date date,
                              @JsonbProperty("description") String description) {
    return new Workshop(title, date, description);
}    

Now the Workshop record:


public record Workshop(String title, Date date, String description) {

    @JsonbCreator
    public static Workshop create(String title,Date date,String description) {
        return new Workshop(title, date, description);
    }    
}

can be serialized and deserialized in a Java SE application:


@Test
public void serializeThenDeserialize() {
    var workshop = new Workshop("hello",new Date(),"nothing");

    var serialized = Mapper.save(workshop);

    System.out.println(serialized);

    var copy = Mapper.load(serialized);
    assertEquals(workshop.title(), copy.title());
}

The test generates the following output:


{
    "date": "2021-10-07T07:58:17.606Z[UTC]",
    "description": "nothing",
    "title": "hello"
}    

Getting Method Parameter Names via Reflection and Apache Maven

If you try to get the method parameter names from e.g.:


public void methodWithParameters(String first, int second) {
}

...via reflection:


@Test
public void accessParameterNames() throws Exception {
    var method = this.getClass()
    .getMethod("methodWithParameters",String.class,int.class);
    var parameters = method.getParameters();
    for (var parameter : parameters) {
        var name = parameter.getName();
        System.out.println(name);
    }
}

...you will get the following output:


arg0
arg1    

To get the actual parameter names, you will have to compile the code with the javac -parameters (Generate metadata for reflection on method parameters) switch.

In a maven project, you will have to use newer version of compiler plugin first (the default is ~3.1):


<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
</plugin>   

...then activate compiler parameters with


<properties>
    <maven.compiler.parameters>true</maven.compiler.parameters>
</properties>    

...now mvn test yields:


first
second

AWS Lambda Cold Start, Web Components vs. Angular, Microservices vs. Events, Quarkus--or 92nd airhacks.tv

The 91st airhacks.tv, live stream from https://youtube.com/c/bienadam/, with the following topics:

AWS Lambda Coldstart, JPA Queries, Web Components vs Angular, Typescript or ES 6, Microservice Communication, Events vs. Messages, Microservices vs. Monoliths vs. Event Streaming, MicroProfile and Jakarta EE popularity, Quarkus under the hood, large file upload

...is available:

See you every first Monday of the month at https://airhacks.tv 8pm CET (UTC+1:00). Show is also announced at: meetup.com/airhacks.

Any questions left? Ask now: https://gist.github.com/AdamBien/ed0355d7e3f9880a89f379caf114f2c0 and get the answers at the next airhacks.tv.

AWS Lambda Coldstart, JPA Queries, BCE and Angular, Microservice Communication, MicroProfile and Jakarta EE popularity--or 91st airhacks.tv

Questions and topics: https://gist.github.com/AdamBien/93095b0cdc71892d2bbf562e2856c30d for the 91st airhacks.tv questions and answers live stream on https://www.youtube.com/c/bienadam/live:

  1. AWS Lambda cold start and Java [youtube comment]
  2. Thoughts on JPA queries
  3. JPA entities boilerplate
  4. BCE, ES 6, TypeScript and Angular
  5. Microservice communication: JMS and HTTP
  6. The popularity of MicroProfile and Jakarta EE
  7. Discussion: what is the difference between Spring and a MicroProfile / Jakarta EE?
See you every first Monday of the month at https://airhacks.tv 8pm CET (UTC+1:00). Show is also announced at: meetup.com/airhacks.

Any questions left? Ask now: and get the answers at the next airhacks.tv.

From Java Object to JSON and Back with Jakarta JSON Binding (JSON-B)

To use JSON-B (Jakarta JSON Binding) directly with a Java SE app, like e.g. JUnit, you will need to declare a single dependency:


<dependency>
    <groupId>org.eclipse</groupId>
    <artifactId>yasson</artifactId>
    <version>2.0.2</version>
</dependency>

Now a Java class:


import java.util.Date;

public class Workshop {
    public String title;
    public Date date;
    public String description;

}    

...can be serialized and deserialized with JSON-B:


import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import airhacks.workshops.entity.Workshop;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;


public interface Mapper {
    final static String FILE = "workshops.json";

    static void save(Workshop workshop) {
        var jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true));
        try (var writer = new FileWriter(FILE)) {
            jsonb.toJson(workshop, writer);
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

    static Workshop load() {
        try (var reader = new FileReader(FILE)) {
            return JsonbBuilder.create().fromJson(reader, Workshop.class);
        } catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }
}    

...in a JUnit test:


import java.util.Date;

import org.junit.jupiter.api.Test;

public class JSONBTest {

    @Test
    public void serializeThenDeserialize() {
        var workshop = new Workshop();
        workshop.date = new Date();
        workshop.description = "no slides";
        workshop.title = "java and jakarta";

        Mapper.save(workshop);

        var copy = Mapper.load();
        assertEquals(workshop.title, copy.title);
    }

}    

...and the content of the workshops.json is:


{
    "date": "2021-10-03T05:25:42.168Z[UTC]",
    "description": "no slides",
    "title": "java and jakarta"
}

Humans over Computers and Serverless JBoss on Azure App Service--an airhacks.fm podcast

Subscribe to airhacks.fm podcast via: spotify| iTunes| RSS

The #159 airhacks.fm episode with Theresa Nguyen (@RockClimberT) about:
the brain, developers, Azure Cloud, Java Community, free climbing, Azure App Service and serverless JBoss / Wildfly
is available for

Online Workshops
...the last 150 posts
...the last 10 comments
License