Testability, Concurrency, Dependency Inversion, Authentication--101st airhacks.tv

Questions for 101st airhacks.tv (live https://www.youtube.com/c/bienadam/):

  1. 100 episodes back--the topics
  2. The story of Jakarta EE / MicroProfile testability
  3. JAX-RS and endpoint concurrency
  4. About interfaces and Dependency Inversion
  5. A portable QuarkusTest?
  6. Using authentication data for filtering in the business logic

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: gist.github.com/AdamBien/1033b6da5d5e75699f0c9c2c44ecb520 and get the answers at the next airhacks.tv.

AWS Lambda, Events, Quarkus and Java--airhacks.fm podcast

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

The #202 airhacks.fm episode with Goran Opacic (@goranopacic) about:
applying enterprise Java thinking to serverless clouds, Quarkus, AWS Lambda, consistency, DynamoDB and the "undifferentiated heavy lifting."
is available for

Superfluous "Stringification" and javax.json.stream.JsonParsingException

The following exception:

"javax.json.stream.JsonParsingException: JsonParser#getObject() or JsonParser#getObjectStream() is valid only for START_OBJECT parser state. But current parser state is VALUE_STRING"

...can be caused by a superfluous "stringification" of regular JavaScript strings, like e.g. JSON.stringify(aString)

The JSON-P parser expects: {"hey":"duke"} but gets: "{\"hey\":\"duke\"}"

To fix the problem, remove JSON.stringify(aString); and send the string directly to the MicroProfile server:


const payload = "{"hey":"duke"}";
const response = await fetch("http://localhost:8080/imports", {
    method: 'POST',
    body: payload,
    headers: {
        'Content-type':'application/json'
    }
});

Testing With MicroProfile REST Client: How To Prevent WebApplicationException

An invocation of a not-existing resource / endpoint with MicroProfile REST client, like e.g.:


import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@Path("/SHOULD_NOT_EXIST")
@RegisterRestClient(baseUri = "https://microprofile.io/")
public interface ProblematicResourceClient {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    Response fetchNotExistingContent();
}

will cause an WebApplicationException like e.g.:


javax.ws.rs.WebApplicationException: Unknown error, status code 404
at org.jboss.resteasy.microprofile.client.DefaultResponseExceptionMapper.toThrowable(DefaultResponseExceptionMapper.java:21)
(...)   

To test the 404 status code:


import io.quarkus.test.junit.QuarkusTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.inject.Inject;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.Test;

@QuarkusTest
public class ProblematicResourceClientIT {

    @Inject
    @RestClient
    ProblematicResourceClient cut;

    @Test
    public void callNotExistingResource() {
        var response = this.cut.fetchNotExistingContent();
        assertEquals(response.getStatus(), 404);
    }
}

...you need to set the MP config parameter to true::


microprofile.rest.client.disable.default.mapper=true

Now the Response contains the status code 404 and the test passes.

Write, Finish, Improve-jPOS--airhacks.fm podcast

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

The #201 airhacks.fm episode with Alejandro Pablo Revilla (@apr) about:
long distance radio, early internet, opensource innovation, building Point of Sales (POS) software in Java, no-dependencies thinking and having fun with continuous improvement.
is available for

HATEOAS, Data APIs, Java and How htmx Happened--airhacks.fm podcast

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

The #200 airhacks.fm episode with Carson Gross (@htmx_org) about:
data APIs, REST, HATEOAS, Java, frontend architectures and the road to htmx - "high power tools for HTML."
is available for

GraalVM: How To Call C-Function From Java ...with an Annotation

To call a C-function:


#include <stdio.h>

extern "C" int multiply(int a,int b){
    printf("c function called with %d and %d",a,b);
    return a * b;
}

...from Java on GraalVM, you have to declare a static, native method annotated with @CFunction:


import java.io.IOException;
import org.graalvm.nativeimage.c.function.CFunction;
import org.graalvm.nativeimage.c.function.CFunction.Transition;
import org.graalvm.nativeimage.c.function.CLibrary;

@CLibrary("calculator")
public class Calculator {

    @CFunction(transition = Transition.NO_TRANSITION)
    public static native int multiply(int a,int b);

    public static void main(String[] args) throws IOException {

        System.out.println("calling c with parameter");
        var result = multiply(2,21);
        System.out.println("-----------------> result: " + result);
    }
}

you will have to download and install GraalVM first.

To compile the code above, you have to "run" on GraalVM. The command java -version should contain "GraalVM":


openjdk version "17.0.4" 2022-07-19
OpenJDK Runtime Environment GraalVM CE 22.3.0-dev (build 17.0.4+7-jvmci-22.3-b02)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.0-dev (build 17.0.4+7-jvmci-22.3-b02, mixed mode, sharing)

Also the following GraalVM components have to be installed (gu list output):


ComponentId                Component name     
----------------------------------------------
graalvm                    GraalVM Core       
llvm                       LLVM Runtime Core  
llvm-toolchain             LLVM.org toolchain 
native-image               Native Image       

Install any missing components with gu install [ComponentId] e.g gu install llvm

To create the native image:

  1. Compile the c code: $LLVM_TOOLCHAIN/clang -shared -o libcalculator.so calculator.cc
  2. Compile the Java code: javac -cp . -d . *.java
  3. Create native image: native-image -cp target --verbose -H:CLibraryPath=[FULLY QUALIFIED PATH TO: libcalculator.so] Calculator NativeCalculator

Now you can call the calculator with: NativeCalculator.

Output:


calling c with parameter
-----------------> result: 42
c function called with 2 and 21

attention

  1. In case $JAVA_HOME/bin/lli --print-toolchain-path throws an exception, consider using the latest dev build.
  2. The value of the annotation @CLibrary("calculator") contains the name of the *.so file without the "lib" prefix: libcalculator.so -> calculator.so
  3. The flag: -H:CLibraryPath= has to point to the fully qualifed path of the directory containing the libcalculator.so

The entire code and build script is available from: graalvm-hello-java-c

Modules in the JVM or the Clouds--airhacks.fm podcast

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

The #199 airhacks.fm episode with Juergen Albert (@JrgenAlbert6) about:
modularization, dependency management, microservices, Infrastructure as Code, OSGi and the clouds
is available for

AWS CodeBuild supports Amazon Corretto 17 (Java 17)

The AWS CodeBuild image aws/codebuild/standard:6.0 (software.amazon.awscdk.services.codebuild.LinuxBuildImage.STANDARD_6_0) ships with installed Amazon Corretto 17.

To provision CodeBuild with Java CDK use recent CDK and constructs versions:


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

Now you can provision a CodeBuild image with Java 17 support:


import software.amazon.awscdk.services.codebuild.LinuxBuildImage;
import software.amazon.awscdk.services.codebuild.PipelineProject;
import software.amazon.awscdk.services.codebuild.BuildEnvironment;
import software.amazon.awscdk.services.codebuild.ComputeType;

//...
PipelineProject.Builder.create(this, "PipelineProject")
        .projectName("Corretto 17")
        //...
        .environment(BuildEnvironment.builder()
                    .computeType(ComputeType.SMALL)
                    .buildImage(LinuxBuildImage.STANDARD_6_0)
                .build())
        .build();

Amazon Corretto 17 becomes directly available in the buildspec.yml without any additional installation:


version: 0.2
env:
  variables:
    JAVA_HOME: "/usr/lib/jvm/java-17-amazon-corretto/"
phases:
    build:
        commands:
            - java -version
            - mvn package    

The JAVA_HOME variable declared in the env section forces Apache Maven to use the installed Amazon Corretto 17.

You can list all available build images with the following command: aws codebuild list-curated-environment-images

Keynote Voxxed Bucharest : Why The Future of Java in the Cloud is Serverless

"In this keynote, we discuss the pros and cons of monoliths, microservices, containers, fat functions, “Java Functions,” and Event-Driven Architectures; to answer the question: “What is the most efficient and most productive Java architecture for the clouds?”

...and I also managed to answer live questions, roughly estimate the costs, and implement and deploy serverless Java "fat", but fast, functions to the cloud.

I used the aws-quarkus-lambda-cdk-plain template as starting point.

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