Java Generator

ALFA tools generates set of Java POJO classes for the model defined.

The generated code has a single dependency;

<dependency>
    <artifactId>alfa-rt-java-core</artifactId>
    <groupId>io.alfa.rt</groupId>
    <version>2.5.1</version>
</dependency>

Refer to the ALFA Maven Plugin for setting up Maven to generate ALFA into Java.

Exporter Concepts

  • Code is generated into matching packages and as a .java file per user-defined-type (UDT).
  • Immutablity is strongly enforced in generated code.
  • Similar to API patterns used in POJO/serialisation frameworks, ALFA supports builder pattern and method chaining. E.g. MyType.newBuilder().setProp1(p1).setProp2(p2).build();
  • Core Java interfaces are used to represent ALFA collection ( e.g. java.util.Map/Set/List/Optional, java.util.stream.Stream ).
  • To minimize dependencies, generated code only depend on the runtime library, and that in turn only depends on Jackson JSON parser.
  • If assertAll are defined in the model, code is generated in the Builder such that before build() completes, all assert conditions and expressions are applied on the object.

Exporter Example

Consider the following demo.alfa definition. Lets look at what Java code is generated from this.

namespace com.acme

key BankAccountKey {
    IBAN : string
}

entity BankAccount key BankAccountKey {
    Name : string
    Transactions : list< Transaction >
    RegisteredDate : date
    Type : enum< Silver, Gold, Platinum >
}

record Transaction {
   Amount : double
   Description : string
   Date : date
   CorrespondingIBAN  : string
}

service BankService( AuthToken : uuid ) {
   getAccount( IBAN : string ) : try< BankAccount >
   getTransactions( k : BankAccountKey ) : stream< Transaction >
}

This can be generated to Java using the ALFA CLI - alfa -c -e java -o gen/java demo.alfa.

The generated Java code is shown in the screenshot below.

  • A .java file is generated per UDT.
  • The in-line enum in BankAccount Type field is generated as a top level enum.
  • Use platform native types - java.* classes over adding unnecessary abstractions.
  • Utility inner classes are generated - Builder, Mutator, TypeDescriptor and Concrete, and are enclosed in auto code-folded blocks.
  • Inner classes are generated with auto code-folding for IntelliJ.
ALFA Generated Java Code

Type Mappings

ALFA types are mapped to Java as outlined in the table below.

AlfaType JavaType Comments
entity Java class Implements alfa.rt.Entity with method to get entity key
enum Java enum Implements alfa.rt.Enum
key Java class Implements alfa.rt.Key
record Java class Implements alfa.rt.Record
service Java interface Implements alfa.rt.Service, and contains all method declarations
trait Java interface Implements alfa.rt.Trait
union Java interface Implements alfa.rt.Union, and a class per union case containing a single value
     
compressed< T > alfa.rt.Compressed< T > Where T can be any ALFA type
future< T > java.util.concurrent.Future< T > Where T can be any ALFA type
either< L, R > alfa.rt.Either< L, R > Where L and R can be any ALFA type
encrypted< T > alfa.rt.Encrypted< T > Where T can be any ALFA type
try< T > alfa.rt.Try< T > Where T can be any ALFA type
stream< T > java.util.stream.Stream< T > Where T can be any ALFA type
T ? java.lang.Optional< T > Where T can be any ALFA type
list< T > java.util.List< T > Where T can be any ALFA type
map< K, V > java.util.Map< K, V > Where K and V can be any ALFA type
set< T > java.util.Set< T > Where T can be any ALFA type
     
boolean boolean  
byte byte  
binary byte[ ]  
char char  
int int  
short short  
long long  
double double  
float float  
string String  
date java.time.LocalDate  
time java.time.LocalTime  
datetime java.time.LocalDatetime  
duration java.time.Duration  
uuid java.util.UUID  
uri java.net.URI  
     

Runtime Library

The ALFA runtime library, alfa-rt-java-core, contains the core interfaces and utilities required to use the generated code along with a JSON encoder/decoder.

Example creating an ALFA Java POJO:

import alfa.rt.*;

public void testBuildingPojo() throws IOException {
    BankAccount.Builder accBuilder = BankAccount.newBuilder();
    accBuilder.setName("Joe Bloggs").setRegisteredDate( LocalDate.of(1990, 10, 12));
    accBuilder.setType( BankAccount_Type_.Gold);

    BankAccountKey.Builder kb = BankAccountKey.newBuilder();
    accBuilder.key( kb.setIBAN("IBAN342").build() );

    for (int i = 0; i < 5; i++) {
        Transaction.Builder tb = Transaction.newBuilder();
        tb.setAmount( Math.random() * 1000 ).
           setCorrespondingIBAN( "ABCDE" + i ).
           setDate( LocalDate.of( 2020, 2, i+1)).
           setDescription("Purchase from Store" + i );

        accBuilder.addTransactions( tb.build() );
    }

    // Create JSON representation
    String json = Codec.toJsonString(ba);
    System.out.println(json);

    // Decode JSON
    BankAccount decoded = Codec.fromJsonString(json);
    Assert.assertEquals(ba, decoded);
}

Refer to Runtime APIs & Guides Java section for documentation on the ALFA Java APIs and a How-To guide.

Runtime Utilities Library

Further to the ALFA Java Runtime library, an optional ALFA Runtime Utilities library is available.

Randomiser

This is a useful utility that generates a random value generators which is extremely useful for testing applications with sample data. The Java ALFA Object randomiser is able to randomise any value also while respecting any ALFA field constraints.

Given an ALFA definition such as:

record Sample.Result {
    // 3x3 matrix of numbers between 10 to 100
    Matrix3x3 : list<
                   list<
                      int(10,100)
                   >(3,3)
                >(3,3)
}

The randomiser generates the following object, serialized to JSON.

Naturally, the generator respects the model and constraints to accurately generate a valid object. The randomiser is fully model-aware, as a result can generate random values for any ALFA definition.

{
  "$type":"Sample.Result",
  "Matrix": [
                [96, 10, 92],
                [26, 97, 20],
                [14, 44, 83]
            ]
}

If no constraints are defined, the randomiser will create lists with a default length of 5 elements. In the example above, when the JSON is being read, the ALFA Runtime will validate the values against the constraints that have been defined.

Refer to Runtime APIs & Guides Java section How-To guide for examples of using the Randomiser.