Functional Programming in Java, Second Edition: All the code for Chapter 6, "Working with Resources" part in one class

Again, organized as a JUnit class of tests.

Some methods and parameters have been renamed for greater clarity

package chapter6;

import org.junit.jupiter.api.Test;

import java.io.FileWriter;
import java.io.IOException;

// ---
// "resources/fpij/FileWriterARM.java" on p. 109
// ARM "Automatic Resource Management" (AutoCloseable + Try with Resources)
// ---

class FileWriterARM implements AutoCloseable {
    private final FileWriter writer;

    public FileWriterARM(final String fileName) throws IOException {
        writer = new FileWriter(fileName);
    }

    public void writeStuff(final String message) throws IOException {
        writer.write(message);
    }

    // this shall be called from a try-with-resources

    public void close() throws IOException {
        System.out.println("close called automatically...");
        writer.close();
    }

}

// ---
// EAM "Execute Around Method Pattern", basically the "Inversion of Control"
// pattern - "don't call us, we will call you!"
// "resources/fpij/FileWriterEAM.java" on p.111
// ---

class FileWriterEAM {

    private final FileWriter writer;

    // private constructor

    private FileWriterEAM(final String fileName) throws IOException {
        writer = new FileWriter(fileName);
    }

    // private close()

    private void close() throws IOException {
        System.out.println("close called automatically...");
        writer.close();
    }

    public void writeStuff(final String message) throws IOException {
        writer.write(message);
    }

    // "resources/fpij/FileWriterEAM.java" on p.111, bottom
    // Rather than "block", which is confusing, let's call the action part "injectedAction"
    // and the interface likewise.

    public static void use(final String fileName, final InjectedAction<FileWriterEAM, IOException> injectedAction) throws IOException {
        final FileWriterEAM writerEAM = new FileWriterEAM(fileName);
        try {
            injectedAction.accept(writerEAM);
        } finally {
            writerEAM.close();
        }
    }
}

// ---
// The code "resources/fpij/FileWriterExample.java" on p.106, verbatim.
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/FileWriter.html
// ---

class FileWriterExample {

    private final FileWriter writer;

    public FileWriterExample(final String fileName) throws IOException {
        writer = new FileWriter(fileName);
    }

    public void writeStuff(final String message) throws IOException {
        writer.write(message);
    }

    // "resources/fpij/FileWriterExample.java" on p.108

    public void finalize() throws IOException { //Deprecated in Java 9
        writer.close();
    }

    @Deprecated
    public void close() throws IOException {
        writer.close();
    }
}

// ---
// "resources/fpij/UseInstance.java" on p.112
// Originally called "UseInstance", "InjectedAction" sounds better to me.
// Note the interesting use of a generic Throwable.
// ---

@FunctionalInterface
interface InjectedAction<T, X extends Throwable> {
    void accept(T instance) throws X;
}

// =================================

public class WorkingWithResources_Cleanup {

    // We don't want the file to appear in the IDE filespace, so "/tmp" seems like
    // a good target directory. The $$ will be replaced.

    private final static String tt = "/tmp/foofile-$$.txt";

    // "resources/fpij/FileWriterExample.java" on p.107

    @Test
    void fileWriterExample() throws IOException {
        String targetFile = tt.replace("$$","test1");
        final FileWriterExample writerExample = new FileWriterExample(targetFile);
        writerExample.writeStuff("peek-a-boo");
    }

    // "resources/fpij/FileWriterExample.java" on p.108
    // DON'T IT LIKE THIS

    @Test
    void fileWriterExample_badAsCloseMayNotBeCalled() throws IOException {
        String targetFile = tt.replace("$$","test2");
        final FileWriterExample writerExample = new FileWriterExample(targetFile);
        writerExample.writeStuff("peek-a-boo");
        writerExample.close();
    }

    // "resources/fpij/FileWriterExample.java" on p.108

    @Test
    void fileWriterExample_betterWithFinally() throws IOException {
        String targetFile = tt.replace("$$","test3");
        final FileWriterExample writerExample = new FileWriterExample(targetFile);
        try {
            writerExample.writeStuff("peek-a-boo");
        }
        finally {
            writerExample.close();
        }
    }

    // "resources/fpij/FileWriterARM.java" on p.109
    // ARM "Automatic Resource Management" (AutoCloseable + Try with Resources)

    @Test
    void fileWriterExampleARM() throws IOException {
        String targetFile = tt.replace("$$","test4");
        try (final FileWriterARM writerARM = new FileWriterARM(targetFile)) {
            writerARM.writeStuff("peek-a-boo");
            System.out.println("done with the resource...");
        }
    }

    // "resources/fpij/FileWriterEAM.java" on p.112
    // EAM "Execute Around Method Pattern" (pass an "injected action").
    // Note that FileWriterEAM.use has just a static use().

    @Test
    void fileWriterExampleEAM() throws IOException {
        String targetFile = tt.replace("$$","test5");
        FileWriterEAM.use(targetFile, writerEAM -> writerEAM.writeStuff("sweet"));
    }

    // "resources/fpij/FileWriterEAM.java" on p. 113

    @Test
    void fileWriterExampleEAM2() throws IOException {
        String targetFile = tt.replace("$$","test6");
        FileWriterEAM.use(targetFile, writerEAM -> {
            writerEAM.writeStuff("how");
            writerEAM.writeStuff("sweet");
        });
    }

}