sebastiandaschner news


sunday, june 04, 2017

Konnichiwa from Hokkaido!

The last days were full of riding motorbike all across Japan to visit Java User Groups. Similar to our last motorbike Java tours, Steve Chin and myself are on the “Oracle Code Japan Tour” which had the stop in Sapporo yesterday. Now we are exploring the island of Hokkaido and will return to Tokyo in the next days. It is always great to see the engagement of the Japanese Java Community all across the country.

At the JUGs I presented the topic of “Cloud Native Java EE” a buzzword-driven presentation how Java EE shines in the age of modern enterprise environments — Java EE in Docker containers orchestrated by Kubernetes. You can watch the recording of the Hiroshima JUG presentation.

 

What’s new

 

Java EE quiz solution #3

More Java EE quizzes from the official Java twitter handle as part of #100DaysOfJava:

The solution of my next Java EE related question is:

Invoking ask() will output

intercepted!
intercepted!
asked first
asked second
intercepted!
asked second

The QuizInterceptor is included to intercept all invocations of business method on Quiz instances. Therefore the ask() method will be intercepted and intercepted! will be printed first. The askFirst() and askSecond() method calls inside are invoked on another instance of Quiz and therefore intercepted on that object as well. The askSecond() method call inside of askFirst() is not intercepted since this is just a direct method invocation on the same object — see quiz solution #2 of my last newsletter.

 

Java EE quiz solution #4

See the solution of my JAX-RS related question.

Method two() and three() are annotated with @Produces which makes things clear for these methods — they will output application/json and text/plain, respectively.

The Content-Type of the one() method is determined dynamically by the container based on which Accept header is requested and which Java type returned from the method. Depending on the available MessageBodyWriters the container will send a corresponding type — or application/octet-stream as a default. For the String return type the result is very flexible — you can try this out by sending different Accept headers via an HTTP client.

For those who are more interested into this topic have a look into the JSR 339 specification chapter 3.5 and 3.8.

 

Handle custom exceptions with JAX-RS status codes

In the last newsletter issue I showed how to use JAX-RS exceptions to send specific HTTP error status codes and how to avoid the wrapping of exceptions thrown in EJBs. Now we want to combine custom exceptions — thrown in either EJBs or CDI beans — to send custom HTTP responses.

Assuming we have an “exceptional” EJB again:

@Stateless
public class Hello {

    public String greeting() {
        if (new Random().nextBoolean())
            throw new GreetingException("Could not greet");

        return "hello";
    }

}
@ApplicationException
public class GreetingException extends RuntimeException {

    public GreetingException(String message) {
        super(message);
    }

}

The EJB is used in our JAX-RS resource:

@Path("hello")
public class HelloResource {

    @Inject
    Hello hello;

    @GET
    public String hello() {
        return hello.greeting();
    }

}

Now to map the occurring exception to a custom HTTP response we can define a JAX-RS ExceptionMapper.

@Provider
public class GreetingExceptionMapper
    implements ExceptionMapper<GreetingException> {

    @Override
    public Response toResponse(GreetingException exception) {
        return Response.status(Response.Status.CONFLICT)
                .header("Conflict-Reason", exception.getMessage())
                .build();
    }

}

The exception mapper is registered as a JAX-RS extension (by @Provider) and will handle any GreetingException thrown by a resource method.

The example will occasionally output HTTP 409 Conflict with header Conflict-Reason: Could not greet.

 

Thanks a lot for reading and see you next time!

 

Did you like the content? You can subscribe to the newsletter for free:

All opinions are my own and do not reflect those of my employer or colleagues.