JSON-B / JSON-P: From TextBlock To JsonArray

You can directly convert Java TextBlocks to JsonArray with Jakarta JSON Binding (JSON-B) and Jakarta JSON Processing (JSON-P):


import org.junit.jupiter.api.Test;
import jakarta.json.JsonArray;
import jakarta.json.JsonObject;
import jakarta.json.bind.JsonbBuilder;

public class TextBlockToJsonArray {

    @Test
    public void deserializeTextBlock() {
        var input = """
            [
                {
                    "name": "java",
                    "age": 25
                },
                {
                    "name": "python",
                    "age": 52
                
                }]
                """;
        var  jsonArray = JsonbBuilder.create().fromJson(input, JsonArray.class);
        
        //output
        jsonArray.getValuesAs(JsonObject.class).forEach(System.out::println);
    }
    
}

The output:


{"name":"java","age":25}
{"name":"python","age":52}

JSON-B and JSON-P functionality comes as a single dependency:


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

Testing Jakarta EE, JAX-RS concurrency, Bulk Heads, Dependency Inversion, QuarkusTest, Authentication and DB, Secrets, sops, AWS KMS, SSM and SM--101st airhacks.tv Q & A

The 101st airhacks.tv episode with the following topics / questions:

"How to test Jakarta EE applications, JAX-RS concurrency and Bulk Heads, Java interfaces and dependency inversion, dependency on QuarkusTest, using authentication data for filtering, exposing versions, secrets, sops, AWS KMS, SSM and SM"

...is ready to watch:

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

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.

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

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