CDI RequestScoped,Threading and the javax.enterprise.context.ContextNotActiveException

Accessing a CDI @RequestScoped bean:


import javax.enterprise.context.RequestScoped;

@RequestScoped
public class Greeter {
    
    public String hello(long number){
        return "hello, duke " + number;
    }
}

asynchronously:

import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
@ApplicationScoped
public class GreetingResource {
    
    @Inject
    Greeter greeter;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        var numbers  = Stream.generate(System::currentTimeMillis)
        .limit(10)
        .toList();
        return numbers.parallelStream() //stream() would work...
        .map(number -> this.greeter.hello(number))
        .collect(Collectors.joining(","));
    }
}

may cause a javax.enterprise.context.ContextNotActiveException, like e.g.

javax.enterprise.context.ContextNotActiveException: javax.enterprise.context.ContextNotActiveException: RequestScoped context was not active when trying to obtain a bean instance for a client proxy of CLASS bean [class=airhacks.Greeter, id=59c45f3d436e11499d8793e2c5fc0c26ffbe3933]
- you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding

The entire example was implemented, and explained, "from scratch":

Adding / Merging / Joining two Collections / Lists

To join to List / Collection instances, you can concat their streams:


import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
public class JoiningTwoLists {

    @Test
    public void join() {
        var first = List.of(1,2);
        var second = List.of(3,4);
        var joinedList = Stream.concat(first.stream(), second.stream()).toList();
        joinedList.forEach(System.out::println);
    }
}

Prints: 1 2 3 4

"I first played games I wrote"--airhacks.fm podcast

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

The #203 airhacks.fm episode with Daniel Lipp (@dynamic_123) about:
SmallTalk, ugly Java, enterprise architectures, clouds and Quarkus
is available for

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

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