Generating a Test Client for HTTP/JSON (JAX-RS / JSON-B) Services

In this screencast I'm creating a Java EE 8 project from scratch using an archetype, expose a HTTP / JSON service with JAX-RS and JSON-B, build the project WAD using Apache Maven and deploy 4.2kB WAR to openliberty (the largest possible installation with all Java EE 8 + MicroProfile features enabled) in 4 mins:

See you at Web, MicroProfile and Java EE Workshops at MUC Airport, particularly at the Java EE CI/CD, Testing and Quality workshop


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

2018 Predictions Review, Streaming JMS to DB, JPA Refresh, WebComponents and Java EE 8--58th airhacks.tv

In the first episode of 2019, we covered the following topics:

"Watch and Deploy (WAD) demo, 2018 Predictions Review, Streaming JMS to DB, Message parallelism, JPA Refresh, WebComponents and Java EE 8, Async Script Loading"

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

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Illegal base64 character 5f, Illegal base64 character 2d and java.util.Base64

Decoding a String with invalid Base64 '_' character:


import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.junit.jupiter.api.Test;

public class Base64EncodeTest {

    @Test
    public void decodeUnderscode() {
        byte[] bytes = "CAFEHELLO_BABEDUKE".getBytes(StandardCharsets.UTF_8);
        Base64.getDecoder().decode(bytes);
    }
}

raises the java.lang.IllegalArgumentException: Illegal base64 character 5f

and the character '-':

@Test
public void decodeMinus() {
    byte[] bytes = "CAFEHELLO-BABEDUKE".getBytes(StandardCharsets.UTF_8);
    Base64.getDecoder().decode(bytes);
}    

...leads to: java.lang.IllegalArgumentException: Illegal base64 character 2d

Both characters can be decoded with Base64.getUrlDecoder:


@Test
public void urlDecode() {
    byte[] underscored = "CAFEHELLO_BABEDUKE".getBytes(StandardCharsets.UTF_8);
    Base64.getUrlDecoder().decode(underscored);

    byte[] dashed = "CAFEHELLO-BABEDUKE".getBytes(StandardCharsets.UTF_8);
    Base64.getUrlDecoder().decode(dashed);

}    
See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

List to JsonArray Conversion with JSON-P and Java EE 8

List<String> can be converted into JsonArray with:



import javax.json.Json;
import javax.json.JsonArray;
import javax.json.stream.JsonCollectors;
import org.junit.jupiter.api.Test;

public class StringListToJsonArrayTest {

    @Test
    public void conversion() {
        
        JsonArray jsonStringArray = Arrays.asList("duke", "duchess").
                stream().
                map(Json::createValue).
                collect(JsonCollectors.toJsonArray());
                        
        System.out.println(jsonStringArray);
    }
}    

...and the result is: ["duke","duchess"]

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Creating Domain-Specific Metrics On-The-Fly with MicroProfile

Domain-specific counters can be created on-the-fly by injecting the MetricRegistry:


import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.annotation.RegistryType;    

@Path("ping")
public class PingResource {
    
    @Inject
    @RegistryType(type = MetricRegistry.Type.APPLICATION)
    MetricRegistry registry;

    @GET
    public String ping() {
        registry.counter("pingCount").inc();
        return "Enjoy Java EE 8 with MicroProfile ThinWARs!";
    }
}    

curl http://localhost:9080/metrics/application yields:

# TYPE application:ping_count counter
application:ping_count 1    
    
and curl -H"Accept: application/json" http://localhost:9080/metrics/application returns

{"pingCount":1}    
    

The size of the WAR is 4kB. Initial build time: 3292 ms, subsequent build times: < 3s. Deploy time: 0.233 seconds.

Built and deployed with WAD and tested with openliberty (the largest possible installation with all Java EE 8 + MicroProfile features enabled).

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Asynchronous BulkHeads with Fallback and MicroProfile

The org.eclipse.microprofile.faulttolerance.Asynchronous annotation together with org.eclipse.microprofile.faulttolerance.Bulkhead introduces a configurable and monitorable thread pool "on-the-fly":


import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import org.eclipse.microprofile.faulttolerance.Asynchronous;
import org.eclipse.microprofile.faulttolerance.Bulkhead;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.metrics.annotation.Counted;
    
    
public class AsynchronousCalculator {

    @Counted
    @Asynchronous
    @Fallback(fallbackMethod = "onOverload")
    @Bulkhead(value = 2, waitingTaskQueue = 10)
    public Future intenseCalculation(Consumer resultListener) {
        int computation = 2 * 21;
        resultListener.accept(computation);
        return CompletableFuture.completedFuture(null);
    }

    /**
    * onOverload is called on overload :-)
    */
    public Future onOverload(Consumer resultListener) {
        System.out.println("Please call me next time later");
        resultListener.accept(13);
        return CompletableFuture.completedFuture(null);

    }
}    

The fully optional org.eclipse.microprofile.metrics.annotation.Counted annotation causes the application server to emit the metric: "application:com_airhacks_asynchronous_control_asynchronous_calculator_intense_calculation 15" which reflects the current number of instances and so the number of parallel processes (in this example 15) at the same time.

On top of that also Bulkhead metrics and fallback counters are emitted (excerpt):


# TYPE (...)_calculator_intense_calculation_fallback_calls_total counter
(...)_calculator_intense_calculation_fallback_calls_total 0
# TYPE (...)_calculator_intense_calculation_bulkhead_execution_duration_mean_seconds gauge
(...)_calculator_intense_calculation_bulkhead_execution_duration_mean_seconds 1.00234796556958
# TYPE (...)_calculator_intense_calculation_bulkhead_execution_duration_max_seconds gauge
(...)_calculator_intense_calculation_bulkhead_execution_duration_max_seconds 1.007435808
# TYPE (...)_calculator_intense_calculation_bulkhead_execution_duration_min_seconds gauge
(...)_calculator_intense_calculation_bulkhead_execution_duration_min_seconds 1.0000803550000001
# TYPE (...)_calculator_intense_calculation_bulkhead_execution_duration_stddev_seconds gauge
(...)_calculator_intense_calculation_bulkhead_execution_duration_stddev_seconds 0.0016244590722208272
# TYPE (...)_calculator_intense_calculation_bulkhead_execution_duration_seconds summary
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds_count 2370
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.5"} 1.002190041
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.75"} 1.003775723
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.95"} 1.0051155980000002
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.98"} 1.005298392
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.99"} 1.005314287
(...)_calculator_intense_calculation_bulkhead_execution_duration_seconds{quantile="0.999"} 1.006405762
# TYPE (...)_calculator_intense_calculation_bulkhead_calls_accepted_total counter
(...)_calculator_intense_calculation_bulkhead_calls_accepted_total 2400
(...)    

The @Asynchronous methods can be easily combined with asynchronous JAX-RS resources:


@RequestScoped
@Produces(MediaType.TEXT_PLAIN)
@Path("calculations")
public class CalculationsResource {

    @Inject
    AsynchronousCalculator worker;

    @GET
    public void ping(@Suspended AsyncResponse response) {
        worker.intenseCalculation(response::resume);
    }
}

The size of the WAR is 6kB. Build time: 2986 ms, deploy time: 0.233 seconds. Built and deployed with WAD and tested with openliberty (the largest possible installation with all Java EE 8 + MicroProfile features enabled).

The general availability of MicroProfile on all major application servers makes the Porcupine superfluous and your WARs a few KB thinner.

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

2018 Predictions Review, Streaming JMS to DB, Message Parallelism, JPA Refresh, WebComponents and Java EE 8, Async Script Loading -- or 58th airhacks.tv

Topics (https://gist.github.com/AdamBien/d8b70f881d893c16a4a192a4efaa5913) for the 58th airhacks.tv

  1. Notes on 2018 predictions
  2. Streaming JMS messages to database
  3. Parallel JMS message consumption
  4. Spring vs. Java EE popularity
  5. ThinWARs and external libraries
  6. Refreshing JPA entities
  7. GPS location with Java
  8. Lazy loading with Hash-based router
  9. Java lambda debugging
  10. Deploying WebComponents with Java EE 8
  11. Installing / bundling vs. referencing external JavaScript libraries
  12. Async script loading
  13. Payara as WebServer
  14. Exceptions, REST, Model -- the root of some evil
  15. JWT, MicroProfile and ES 6
  16. Hexagonal architectures

Ask questions during the show via twitter mentioning me: http://twitter.com/AdamBien (@AdamBien) or using the hashtag: #airhacks. You can join the Q&A session live each first Monday of month, 6 P.M at airhacks.tv or http://www.ustream.tv/channel/adambien

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

From GlassFish to Google Cloud -- a Podcast Episode with Alexis MP

Subscribe to airhacks.fm podcast via: RSS iTunes

An airhacks.fm conversation with Alexis (@alexismp) about:

java -jar glassfish.jar, Community Management at Sun, Developer Relations, how to talk to developers, Texas Instruments 4a, a circle qualifies as "Hello World", Prolog to Java Applets migration for National French Space Agency, Java Center of Excellence at Sun Microsystems, Sun / JavaSoft / IBM as dream jobs, Scott McNealy and the ability of predicting the future - a reference to airhacks.fm episode #19 - interview with Scott McNealy, starting at Sun in 1998, Sun Netscape Alliance, iPlanet Appserver, moving a Reference Implementation to a product called "GlassFish", HK2, GlassFish started faster than Tomcat, moving the industry with GlassFish, fascination with modularity, NetBeans as platform, plugins as quality asurance, lightweight runtimes with 500 MB WARS, making servers bigger and deployables smaller, docker changed the conversation, dealing with boring technologies, different language communities at Google, Java is less ceremonial, than people think, the popularity of Java at Google, AppEngines 10th anniversary, Apache Beam and Google Dataflow, how Sun lost the engineers at Java 5 timeframe, a huge amount of Google projects is based on Java, AppEngine is "serverless", Sun and Google have a lot in common, JAX-RS is Google Cloud Endpoints, Managed PubSub service, PubSub is like JMS, AppEngine as PubSub message listener, Cloud Spanner -- a distributable scalable persistence, DataStore supports versioning is a document, key value store, canary deployments, Objectify an ORM for DataStore, Cloud SQL and PostgreSQL, BigTable, exports to BigQuery, istio , Kubernetes, Helidon on Google Cloud, Kubernetes Engine, you can find Alexis at twitter: @alexismp, LinkedIn, medium: @alexismp and his: blog.
See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Executable Calendar and Dates For 2019 airhacks.tv Shows

Dates for 2019 airhacks.tv shows are available (first Monday of the month, 6pm CET):

  • JANUARY, 7
  • FEBRUARY, 4
  • MARCH, 4
  • APRIL, 1
  • MAY, 6
  • JUNE, 3
  • JULY, 1
  • AUGUST, 5
  • SEPTEMBER, 2
  • OCTOBER, 7
  • NOVEMBER, 4
  • DECEMBER, 2

Generated with:


import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import static java.time.temporal.TemporalAdjusters.firstInMonth;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;

public class AirhacksTVDatesTest {

    @Test
    public void firstMondayOfTheMonth() {

        String firstMondayOfTheMonth = Stream.of(Month.values()).
                map(month -> LocalDate.of(2019, month, 1)).
                map(month -> month.with(firstInMonth(DayOfWeek.MONDAY))).
                map(firstMonday -> firstMonday.getMonth() + ", " + firstMonday.getDayOfMonth()).
                collect(Collectors.joining("\n"));
        System.out.println(firstMondayOfTheMonth);

    }
}

If you don't like to miss a show, subscribe to events and get notified before the show: http://www.ustream.tv/channel/adambien ("upcoming" tab, lower corner).

Ask questions during the show via twitter mentioning me: http://twitter.com/AdamBien (@AdamBien) or using the hashtag: #airhacks. You can join the Q&A session live each first Monday of month, 6 P.M at airhacks.tv or using the built-in chat: http://www.ustream.tv/channel/adambien

See you at Web, MicroProfile and Java EE Workshops at MUC Airport, particularly at the Java EE CI/CD, Testing and Quality workshop


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

Cloud-Ready Configuration for JPA-Integration Tests

In JPA Integration Tests the EntityManager is started locally with a dedicated persistence.xml containing all JDBC-connection settings:


<?xml version="1.0" encoding="UTF-8"?>
<persistence>
    <persistence-unit name="integration-test" transaction-type="RESOURCE_LOCAL">
        <class>com.airhacks.workshops.entity.Workshop</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <validation-mode>NONE</validation-mode>
        <properties>
            <property name="javax.persistence.jdbc.user" value="air"/>
            <property name="javax.persistence.jdbc.password" value="hacks"/>
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
        </properties>
    </persistence-unit>
</persistence>    
The persistence.xml above does not contain the mandatory javax.persistence.jdbc.url property -- the database host is fetched from the environment and directly passed to the createEntityManagerFactory method at runtime:

public class WorkshopIT {

    private EntityManager em;
    private EntityTransaction tx;
    
    static String getDatabaseHost() {
        return System.getenv().getOrDefault("db.host", System.getProperty("db.host", "localhost"));
    }    

    @BeforeEach
    public void init() {
        String dbURL = String.format("jdbc:postgresql://%s:5432/airhacksDB", getDatabaseHost());
        Map<String, String> configuration = new HashMap();
        configuration.put("javax.persistence.jdbc.url", dbURL);
        this.em = Persistence.
                createEntityManagerFactory("integration-test", configuration).
                createEntityManager();
        this.tx = this.em.getTransaction();
    }
}    

Now the integration test can be configured to use a local database at the developer machine and a different database in the CI/CD pipeline. In Kubernetes-based environments like e.g. OpenShift the configuration can be provided with deployment configuration (DC) or Jenkins build parameters.

See you at Web, MicroProfile and Java EE Workshops at MUC Airport, particularly at the Java EE CI/CD, Testing and Quality workshop


NEW: Online Workhop Effective WebApps without Frameworks is also coming to: MUC Airport.

Airport MUC workshops: Web (SPA, PWAs, Offline, Desktop, Mobile) Applications Essentials and Effective Web Applications. No migrations. #usetheplatform

Podcast: airhacks.fm and newsletter: airhacks.news

A book about rethinking Java EE Patterns

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