JDK 1.0+: ASCII Progress Indicator

This example implements a progress indicator as an animated rotating character:


public class Progress {

    private int counter = 0;
    private char sequence[] = {'-','\\','|','/'};

    public void showProgress(){
        counter++;
        int slot = counter % sequence.length;
        char current = sequence[slot];
        System.out.print(current);
        //the backspace character
        System.out.print("\b");
    }    
}

The test below will show a rotating character for 5 seconds. The animation may not work in your IDE or unit test, but should work in the console:


public class ProgressTest {
    @Test
    public void rotate(){
        var progress = new Progress();
        for (int i = 0; i < 20; i++) {
            progress.showProgress();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }
}

Kafka Connect CLI, JFR Unit, OSS Archetypes and JPMS--an airhacks.fm podcast

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

The #174 airhacks.fm episode with Gunnnar Morling (@gunnarmorling) about:
kcctl - the Kafka Connnect CLI, JfrUnit - assertions for JDK Flight Recorder events, Layrry - A Launcher and API for Modularized Java Applications and the OSS Quickstart
is available for

kcctl--The Missing Kafka Connect Command Line Interface (CLI)

kcctl is the missing Command Line Interface (CLI) for kafka connect implementations like e.g. debezium. kcctl is a fast and convenient Connect REST Interface wrapper, completely written in Java:

Regular Expressions With Java's Text Blocks / Multiline Strings

A Java regex pattern "java or duke" matches on a regular Java string:


import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.regex.Pattern;

import org.junit.jupiter.api.Test;

public class RegexTest {

    @Test
    public void singleLine(){
        var pattern = Pattern.compile(".*(java|duke).*");
        var text = "java duke";
        assertTrue(pattern.matcher(text).matches());
        
    }
    

...but fails on multiline Java String / Text Blocks:


@Test
public void multiLine() {
    var pattern = Pattern.compile(".*(java|duke).*");
    var message = """
        java
        duke
    """;
    assertFalse(pattern.matcher(message).matches());
}

The option Pattern.DOTALL:

(...) In dotall mode, the expression . matches any character, including a line terminator. By default this expression does not match line terminators (...)

makes the regular expression work on multiline strings:


@Test
public void multiLineDotAll() {
    var pattern = Pattern.compile(".*(java|duke).*",Pattern.DOTALL);
    var message = """
        java
        duke
    """;
    assertTrue(pattern.matcher(message).matches());
}

MicroProfile 5.0--an airhacks.fm podcast

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

The #173 airhacks.fm episode with Emily Jiang (@emilyfhjiang) about:
MicroProfile 4.0, 5.0, MicroProfile relation to Jakarta EE, the MicroProfile book, metrics, OpenTelemetry, APIs, shims, SPIs and some ideas for the future
is available for

Web Components, Boundary Control Entity (BCE) and Unidirectional Data Flow with redux

Web Components are supported by all major browsers (https://caniuse.com/custom-elementsv1) and therefore do not require any additional shims or polyfills. Custom Elements combined with modern JavaScript versions (ES 6+) already provide a Java-like "look and feel":


class JavaDev extends HTMLElement {
    connectedCallback() {
        const message = "Web Components"
        this.innerHTML = `Hello, ${message}`;
    }
    }
    customElements.define('java-dev',JavaDev);

However, the "vanilla" Web Component approach would require a complete re-rendering of the entire element and will result in slower performance in more sophisticated applications. Because we are setting a raw string, which can also contain user input and data fetched from a server, the above approach also comes with a security risk. Thankfully, JavaScript provides a way to declare functions "tagged templates" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates), which process the raw String and can realize a faster or more secure rendering.

A tagged template function receives the entire String with all "bindings," which allows the implementation of additional syntactic sugar. lit-html is an example of such implementation, which optimizes the rendering, escapes JavaScript code, and adds convenient event handlers' attachment:


const template = html`
<button @click="${_ => this.newBookmark()}">new bookmark</button>
`;

Vanilla Web Components combined with plain lit-html templating "function" already feel like a lean and productive JavaScript framework. With lit-html, you are already good to go for smaller web applications. Applications with many interacting components will require a state management solution. Without a central "mediator" (https://en.wikipedia.org/wiki/Mediator_pattern), the individual Custom Elements will have to communicate with each other directly.

Redux (https://redux.js.org) is a lean (single file) implementation of the "mediator" pattern. It is a central singleton that manages the entire state of the application and notifies all listeners about the changes. The Redux library's use may lead to a significant boilerplate, but it integrates well with lit-html and Web Components. Web Components combined with lit-html, redux, and a few conventions are productive and scale for more complex, interactive applications.

The "Boundary Control Entity" is one of the oldest architectural patterns (https://en.wikipedia.org/wiki/Entity-control-boundary), is similar to MVC, and even provides icons available in all popular design and sketching tools. Equipped with BCE, you don't have to argue about the naming conventions, can conveniently ignore the "Parkinson's law of triviality" (https://en.wikipedia.org/wiki/Law_of_triviality), and focus on the semantics instead.

A complex application is divided into functional, feature-driven folders named after essential concepts. Each such folder comprises at most the following directories:
  • Boundary: contains the views implemented with Custom Elements ("Web Components"). The custom elements react to user input and forward the extracted, relevant data to the "controls." All views are listening to redux store changes and are re-rendered at any state mutation.
  • Control: are the glue between the visual views and the redux "store." A control package contains functions that implement business logic and backend communication. Controls are asynchronous, "fire-and-forget" functions that process the user input, call external services, and dispatch the data as "redux actions" to the store.
  • Entity: the entity folder contains reducers that mutate the state. Any state change leads to notification of all listeners. Maintaining object lists, filtering, or changing the state are the typical responsibilities of functions residing in the "entity" package.

Combining vanilla Web Components with lit-html and redux comes with the following advantage:

  1. You can start with Web Components without learning any additional framework. Web Components are built-in into the browser, they are well documented, stable, and not expected to change. Migrations or upgrades are not necessary--you only have to learn them once and never migrate.
  2. lit-html and redux are small utilities with several alternatives available.
  3. BCE comes with a clear and consistent structure, which scales for large frontends.
  4. The combination of Web Components, lit-html, and redux toolkit leads to code similar to React without any framework involved.
  5. The necessary tooling is minimal. No transpilations, build tools, or bundling is required. Only a simple web server with hot-reload functionality like, e.g., https://browsersync.io, is recommended.
Standards APIs like, e.g., Web Components are already backed into the browser. Therefore using a JavaScript framework requires a significant added value to replace an already existing API. Over time JavaScript frameworks become less and less relevant. Even today, you can implement complex web applications with a low-magic approach. SpaceX engineers already recognized the productive mix of Web Components, CSS, and JavaScript: "We are the SpaceX software team, ask us anything!"

Check the following quickstarter, just "git clone && go." https://github.com/adambien/bce.design

See the BCE quickstarter in action:

2021 in review, EDAs, EJB to CDI, JPA, Logging, DDOS, AWS, Asynchronous Processing, Obfuscation, MicroProfile and JDBC--95th airhacks.tv

The first airhacks.tv in 2021, live streamed from youtube.com/c/bienadam with the following topics:

2021 in review, killer use cases for Event Driven Architectures, EJB 2 to EJB 3 and EJB to CDI migrations, JPA alternatives, dynamic log configuration, DDOS prevention on AWS Lambda and AWS Fargate, Asynchronous Processing, JavaScript obfuscation, HTTP PATCH and Java 17, GlassFish vs. Payara, MicroProfile and JDBC
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: https://gist.github.com/AdamBien/a0b7e3fb17efc4c2fff4208641c6bc68 and get the answers at the next airhacks.tv.

Formatting String Lists with Collector#joining, Prefix and Suffix

The method Collector#joining is overloaded with the parameters CharSequence prefix, CharSequence suffix which make List formatting easier:


import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;


public class CollectorsJoiningTest {

    @Test
    public void withPrefixAndSuffix() {
        var words = List.of("java","duke","jvm");
        var message = words.stream().collect(Collectors.joining(",", "[", "]"));
        System.out.println(message);
    }
}

The unit test prints: [java,duke,jvm]

2021 in review, EDAs, EJB to CDI, JPA, Logging, DDOS, AWS, Asynchronous Processing, Obfuscation, MicroProfile and JDBC--or Topics for the 2022.1 airhacks.tv

Questions and topics https://gist.github.com/AdamBien/2578630397cdab8f07e811627240fa5f for the 94th airhacks.tv live stream on youtube.com/c/bienadam/live:

  1. 2021 in review
  2. Event stores, event driven architectures, traditional CRUD and 2022 predictions
  3. Migrating from EJB to CDI
  4. Circular dependencies, bundling with JavaScript
  5. JPA AttributeConverters and RequestScoped
  6. Dynamically changing log level
  7. DDOS prevention in the AWS clouds
  8. Private vs. public clouds
  9. Asynchronous processing, sessions and concurrency
  10. Obfuscating JavaScript code
  11. HTTP Patch and Java 17
  12. MicroProfile and JDBC-based persistence
See you every first Monday of the month at airhacks.tv 8pm CET (UTC+1:00). Show is also announced at: meetup.com/airhacks.

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

Object Mapping Observations and the Deprecated Dozer

In 2013 I wrote a post: "In Case Dozer Or BeanUtils Are Working Well You Have A Problem." Most projects back then copied identical object hierarchies, usually persistent JPA entities and transient Data Transfer Objects, back and forth with the decoupling as the primary goal.

Object copying was intended to act as design insurance: potential JPA / persistence layer changes don't have to be visible in the data transfer layer. Since 2013 I have had the chance to review some of the "object copying" projects and noticed the lack of such incompatible changes. In the vast majority of all cases, identical objects are still copied back and forth. Dozer is not an invasive framework, but at least requires the usage of the org.dozer.Mapper. Depending on the design, there can be hundreds of such dependencies. Dozer is deprecated. You will find the following notice on https://github.com/DozerMapper/dozer (6.5.2):
"The project is currently not active and will more than likely be deprecated in the future. If you are looking to use Dozer on a greenfield project, we would discourage that."

Dozer suggest the use of mapstruct or modelmapper frameworks instead.

However, consider removing any superfluous 1:1 mapping logic altogether before migrating dozer to another mapping framework. With Java Records, JSON-P, or Java Records and JSON-B you get interesting out-of-the-box alternatives to an external library and so dependency.

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