Ron and Ella Wiki Page

Extremely Serious

Page 13 of 33

Record Class

A record class is a restricted form of classes that models data as data. Thus, also can be thought as data only class. Additionally, this type of class is immutable.

It automatically implements the following methods:

  • public boolean equals...
  • public int hashCode...
  • public String toString() {...}

The class generated by the record is a final class.

The constructor will also be handled and the parameters is matching the arrangement of the record parameter(s).

Use Cases

  • Data Transfer Objects (DTO) (i.e. not applicable to JPA entities)
  • Compound map keys
  • Multiple return values

Syntax

record <IDENTIFIER>([[[<FIELD_TYPE_1> <FIELD_NAME_1>][, <FIELD_TYPE_2> <FIELD_NAME_2>]][,... <FIELD_TYPE_2> <FIELD_NAME_N>]]) {}
Token Description
IDENTIFIER A valid Java identifier.
FIELD_TYPE_1
FIELD_TYPE_2
FIELD_TYPE_N
The type of the field(s) in the record parameter(s).
FIELD_NAME_1
FIELD_NAME_2
FIELD_NAME_N
The name of the field(s) in the record parameter(s).

The identifier has an equivalent cannonical constructor with parameters equivalent to its parameters.

Each fields has the following:

  • private final field of the same name.
  • public accessor method of the same name and type.

Example

record Person(String firstName, String lastName) {}

The above example is equivalent to the following class definition:

public final class PersonC {

    private final String firstName;
    private final String lastName;

    public PersonC(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String firstName() {
        return this.firstName;
    }

    public String lastName() {
        return this.lastName;
    }

    public boolean equals...
    public int hasCode...
    public String toString() {...}

}

Compact Constructor

In the record definition we can use a compact constructor. This constructor is the shorthand form of the generated default constructor. All of the fields indicated on the record parameters are implicitly available in it.

Syntax of the Compact Constructor

pubic <IDENTIFIER> {
    // Initilization logic.
}

The IDENTIFIER here is matching the record IDENTIFIER, just like when you are writing a constructor of a class but without parameters even the parentheses.

Example Usage

record Person(String firstName, String lastName) {
    public Person {
        java.util.Objects.requireNonNull(firstName);
        java.util.Objects.requireNonNull(lastName);
    }
}

Module Resolution

Resolve modules from the root module using the following syntax:

java --show-module-resolution -p <MODULE_PATHS> -m <ROOT_MODULE>
Identifier Description
MODULE_PATHS List of modules paths delimited by semi-colon (i.e. ;).
ROOT_MODULE The module to start the resolution.

Module-Info Syntax

[open] module <MODULE_NAME> {
    [[requires [transitive] <MODULE_NAME>;]
    [exports <PACKAGE>[ to <MODULE_NAME_1>[,<MODULE_NAME_2>..,<MODULE_NAME_N>];]
    [opens <PACKAGE>;]
    [provides <SERVICE> with <SERVICE_IMPLEMENTATION_1>[,<SERVICE_IMPLEMENTATION_2>..,<SERVICE_IMPLEMENTATION_N>];]
    [uses <SERVICE>;]]
}
Identifier Description
module The module keyword that holds the module directives.
<MODULE_NAME> The module identier.
<PACKAGE> The package identifier.
requires The requires directive indicates that this module depends on another module. ^1
transitive The transitive directive indicates that the user of the current module will also requite another module that the current user will also have access into.
exports The exports directive indicates which public types of the module's package are accessible to other modules. ^1
opens The opens directive also indicates which public types of the module's package are accessible to other modules. The difference between that and exports is that opens is not for compile time, only during runtime, while exports is for both compile time and runtime. The opens directive can typically be used when you want to allow other modules to use reflection for the types in the specified packages, but not to use them during compile time. Let's make this more clear by means of an example. ^1
open This is like the opens directive but with this it opens the whole module.
to <MODULE_NAME_1>[, <MODULE_NAME_2>.., <MODULE_NAME_N>] This indicates to target just specific module(s).
provides...with The provides...with directive indicates that the module provides a service implementation.^1
uses The uses directive indicates that the module requires a service implementation.
<SERVICE> The interface or abstract class that will be implemented as a service.
<SERVICE_IMPLEMENTATION_1>[, <SERVICE_IMPLEMENTATION_2>.., <SERVICE_IMPLEMENTATION_N>] The implementation classes of the SERVICE_INTERFACE.

Java Text Blocks

The text blocks is Java's way to simplify rendering of a string that spans multiple lines. A text block begins with three double-quote characters followed by a line terminator.^1

Example:

String text = """
    The quick 
    brown fox 
    jumps over 
    the lazy dog""";

The above example is equivalent to:

String text = "The quick \n"
    + "brown fox \n" 
    + "jumps over \n"
    + "the lazy dog";

Notice who how simple the example against its equivalent.

Incidental and essential white space

The java text blocks differentiates the incidental white space from essential white space^1. Like the following example:

void writeHTML() {
    String html = """
········<html>
········    <body>
········        <p>Hello World.</p>
········    </body>
········</html>
········""";
    writeOutput(html);
}

The dots, preceding the tag represents the incidental white spaces while the space preceding the tag not including the dots, represents the essential white spaces.

Normally the left incidental white space can be controlled by the location of the ending delimiter of the text blocks.

Trailing white space on each line in a text block is also considered incidental and is stripped away by the Java compiler^1.

Removing the ending new line of each line

Using the backslash at the end of each line will remove the implicit \n character.

String text = """
    The quick \
    brown fox \
    jumps over \
    the lazy dog""";

If you output the preceding variable it will become a single line like the following:

The quick brown fox jumps over the lazy dog

Java as a Windows service with NSSM

Pre-requisite

Installing a Java Service

  1. Register a java application as a windows service using the following syntax:

    nssm install <SERVICE_NAME> <JAVA_EXECUTABLE> <JAVA_ARGUMENTS>

    Example

    nssm install "JavaService" "${JAVA_HOME}\bin\java.exe" "-jar java-service.jar --spring.profiles.active=dev"
  2. Update the service with application directory using the following syntax:

    nssm set <SERVICE_NAME> AppDirectory <JAR_FILE_DIRECTORY>

    Example

    nssm set "JavaService" AppDirectory "C:\apps"
  3. Update the service with description using the following syntax:

    nssm set <SERVICE_NAME> Description <APP_DESCRIPTION>

    Example

    nssm set "JavaService" Description "A custom java service."

Displaying the NSSM details of the Java Service

Use the following syntax to display the details of the services:

nssm dump <SERVICE_NAME>

Example

nssm dump "JavaService"

Uninstalling a Java Service

Use the following syntax to remove a java service using nssm:

nssm remove <SERVICE_NAME> confirm

confirm parameter here specifies that we don't want to see the gui confirmation.

Example

nssm remove "JavaService" confirm

Private Signing a CSR

Signing the CSR

  1. Download OpenSSL binaries from the following link if you are using windows:

    https://slproweb.com/products/Win32OpenSSL.html

  2. Create a v3.cnf file using the following template:

    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Self-signed Certificate"
    
    [ alternate_names ]
    
    DNS.1       = <DNS_1>
    #DNS.2       = <DNS_2>
    #DNS.3       = <DNS_3>
    #DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1
    
    # IPv6 localhost
    # DNS.8     = ::1

    Replace the following fields on the template:

    Field Name Description
    DNS_<INDEX> Identify the DNS names from the CSR.

    Example:

    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Self-signed Certificate"
    
    [ alternate_names ]
    
    DNS.1       = www.ronella.xyz
    #DNS.2       = <DNS_2> 
    #DNS.3       = <DNS_3>
    #DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1
    
    # IPv6 localhost
    # DNS.8     = ::1
  3. Generate a CA private key and certificate pair. The following link can help:
    PRIVATE CERTIFICATION AUTHORITY (CA)

  4. Once you have the pair (i.e. key is ca.key.pem and the certificate is ca.cert.crt), sign the CSR using the following command:

    openssl x509 -req -days 365 -sha256 -in domain.csr -extfile v3.cnf -CA ca.cert.crt -CAkey ca.key.pem -CAcreateserial -out domain.crt

Viewing the generated certificate from CSR

  1. View the signed certificate using the following the command:

    openssl x509 -in domain.crt -text

Certificate Signing Request (CSR)

Generating a CSR

  1. Download OpenSSL binaries from the following link if you are using windows:

    https://slproweb.com/products/Win32OpenSSL.html

  2. Create a domain.cnf file using the following template:

    [ req ]
    default_bits        = 2048
    default_keyfile     = private.pem
    distinguished_name  = subject
    req_extensions      = req_ext
    x509_extensions     = x509_ext
    string_mask         = utf8only
    
    [ subject ]
    countryName         = Country Name (2 letter code)
    countryName_default     = <2_LETTER_COUNTRY_CODE>
    
    stateOrProvinceName     = State or Province Name (full name)
    stateOrProvinceName_default = <STATE_NAME>
    
    localityName            = Locality Name (eg, city)
    localityName_default        = <CITY_NAME>
    
    organizationName         = Organization Name (eg, company)
    organizationName_default    = <ORGANIZATION_NAME>
    
    organizationalUnitName         = Organizational Unit (eg, section)
    organizationalUnitName_default = <ORGANIZATIONAL_UNIT>
    
    commonName          = Common Name (e.g. server FQDN or YOUR name)
    commonName_default      = <YOUR_NAME>
    
    emailAddress            = Email Address
    emailAddress_default        = <YOUR_EMAIL_ADDR>
    
    # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
    [ x509_ext ]
    
    subjectKeyIdentifier        = hash
    authorityKeyIdentifier    = keyid,issuer
    
    basicConstraints        = CA:false
    keyUsage            = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Self-signed Certificate"
    
    # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
    [ req_ext ]
    
    subjectKeyIdentifier        = hash
    
    basicConstraints        = CA:false
    keyUsage            = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Private Certificate"
    
    [ alternate_names ]
    
    DNS.1        = <DNS_1>
    
    # Add more DNS by incrementing the DNS.<SUFFIX> like the following.
    # DNS.2       = <DNS_2>
    # DNS.3       = <DNS_3>
    # DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1
    
    # IPv6 localhost
    # DNS.8     = ::1

    Replace the following fields on the template:

    Field Name Description
    2_LETTER_COUNTRY_CODE The two letter code of your country.
    STATE_NAME The name of your state.
    CITY_NAME The name of your city.
    ORGANIZATION_NAME The name of your organization.
    ORGANIZATIONAL_UNIT The name of your section in the organization.
    YOUR_NAME Your full name.
    YOUR_EMAIL_ADDR Your email address.
    DNS_<INDEX> Your DNS name.

    Example:

    [ req ]
    default_bits        = 2048
    default_keyfile     = private.pem
    distinguished_name  = subject
    req_extensions      = req_ext
    x509_extensions     = x509_ext
    string_mask         = utf8only
    
    [ subject ]
    countryName         = Country Name (2 letter code)
    countryName_default     = NZ
    
    stateOrProvinceName     = State or Province Name (full name)
    stateOrProvinceName_default = Wellington
    
    localityName            = Locality Name (eg, city)
    localityName_default        = Wellington
    
    organizationName         = Organization Name (eg, company)
    organizationName_default    = My Organization
    
    organizationalUnitName         = Organizational Unit (eg, section)
    organizationalUnitName_default = IT Department
    
    commonName          = Common Name (e.g. server FQDN or YOUR name)
    commonName_default      = www.ronella.xyz
    
    emailAddress            = Email Address
    emailAddress_default        = ron@ronella.xyz
    
    # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
    [ x509_ext ]
    
    subjectKeyIdentifier        = hash
    authorityKeyIdentifier    = keyid,issuer
    
    basicConstraints        = CA:false
    keyUsage            = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Self-signed Certificate"
    
    # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
    [ req_ext ]
    
    subjectKeyIdentifier        = hash
    
    basicConstraints        = CA:false
    keyUsage            = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "Private Certificate"
    
    [ alternate_names ]
    
    DNS.1        = www.ronella.xyz
    
    # Add more DNS by incrementing the DNS.<SUFFIX> like the following.
    # DNS.2       = <DNS_2>
    # DNS.3       = <DNS_3>
    # DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    # DNS.7       = 127.0.0.1
    
    # IPv6 localhost
    # DNS.8     = ::1
  3. Generate a private key using the following command:

    openssl genrsa -out domain.key.pem 2048
  4. Generate the CSR using the private key with the following command:

    openssl req -new -key domain.key.pem -nodes -out domain.csr -config domain.cnf

Viewing the Generated CSR

  1. View the generated CSR using the following command:

    openssl req -text -noout -verify -in domain.csr
« Older posts Newer posts »