Skip to main content

Reading J2HTML

J2HTML (j2html) is a Java library used to generate HTML I have been using it to create Web 1.0 applications in Java. Web 1.0 is server-side rendering pages with minimal Javascript.

As I got deeper into using the library I started to read the actual source code of this library with an eye on following Java best practices and to my pleasant surprise, this code follows many of them.


I am going to show here some examples of using interesting Java features, beyond the basics.

1. Functional Interface

People are aware that Java supports some form of Functional Programming, and here is an example of using it:


@FunctionalInterface

public interface Indenter {

    String indent(int level, String text);

}


public static Indenter indenter = (level, text) -> String.join("", Collections.nCopies(level, FOUR_SPACES)) + text;


Things that I noticed:

  • String has a method called join. I used before StringUtils.join, but now that is in the standard library I don’t need to use that anymore

  • Collections has the method nCopies, never used it but clever to have it here

2. Passing Configuration to Inner Methods

Passing configuration to various methods is always complicated because:

  • If we use parameters then there are more and more parameters to pass

  • Or, we use a static class or thread-storage we add configuration but this just hides a dependency. This is called “Ambient Context” anti-pattern.

  • Or we use a property with a reasonable default in classes that need it.


J2HTML uses the third approach. There is a class called Config. This is passed as parameter in the Builder constructor and has a “good” default.


Some ideas from the Config class:

  • All the “good” defaults are exposed as public

  • There is a “defaults” method that returns a Config with the “good” defaults

  • Has a static factory method called global

  • All the operations on config are “copy on write” this avoids concurrency issues

  • The HtmlBuilder gets the config in the constructor and is optional. If not present it gets the defaults.

3. Renderable, Appendable

J2HTML uses several “marker” interfaces.


Renderable is an interface shared by all the Tags, DomContent. Given a builder it will return a string.


public interface Renderable {

    default <T extends Appendable> T render(HtmlBuilder<T> builder, Object model) throws  IOException;

}


There are a few assumptions in this interface:

  • All the builders will be HTML builders

  • The parameter of the render method is the output type which is appendable (e.g. StringBuilder, StringWriter)


4. Recursive Type Bound

In a few places I see a parameterized class definitions like these:

public abstract class Tag<T extends Tag<T>> extends DomContent  {

  …

}


public class ContainerTag<T extends ContainerTag<T>> extends Tag<T> {

   …

}


public class PTag extends ContainerTag<PTag> {

  public PTag() {

    super("p");

  }

}


These kinds of definitions are useful to implement fluent APIs that are at the same time typesafe. Another advantage is that the autocomplete will show only the appropriate methods.


A good explanation of why this is useful is in this Stack Overflow article: https://stackoverflow.com/questions/7385949/what-does-recursive-type-bound-in-generics-mean


5. No Components

While j2html has many useful and interesting abstractions, it does not have a component model or abstractions to convert business objectives into HTML code. This has to be done by the application developer.


Popular posts from this blog

Performance Testing a New CRM

Performance testing  is challenging, frustrating, often underestimated typically getting attention only after an incident. How did we the performance test and what did we learn during the development and implementation of  web-services for a new CRM system?

What Can Category Theory Do for Me?

Category Theory is one of the hot topics in computer science. There are many blogs, youtube videos and books about it. It is an elusive subject, with the potential to be the ultimate unifier of everything (math, quantum physics, social justice), to allow us to write the best possible programs and many other lofty goals. I decided to explore the field and see how it can help me. Below is a summary of 12 weeks of reading and watching presentations about Category Theory. It took me some time to select the study material. In the end I decided to use David Spivak’s book (Category Theory for Sciences, David Spivak, 2014) and the youtube recording of a 2017 workshop. These provided both a rigorous approach and a lighter version in the youtube videos. In parallel we explored other sources for a more practical perspective. The CTfS book is a systematic introduction to Category Theory, with definitions and proofs. I liked that, it is a solid foundation. The examples are mostly from math (Set,

On Defining Messages

“Defining Message Formats” is the title of a message posted on the Service Oriented Architecture mailing list [1]  which attracted a lot of attention.  The post summarizes  the dilemma faced by solution architects when they have to define a service interface: 1. Base the internal message format on the external message standard (MISMO for this industry). This message set is bloated, but is mature, supports most areas of the business, and is extensible for attributes specific to this company and its processes. 2. Create an XML-based message set based on the company's enterprise data model, which the company has invested a great amount of money into, and includes a very high percentage of all attributes needed in the business. In a nutshell, we've generated an XML Schema from ER Studio, and will tinker with that construct types that define the payloads for messages. 3. Use MISMO mainly for its entity definitions, but simplify the structure to improve usability. We benefit from the