Attached you will find the source code for a simple java tool that performs a bulk import of documents from a specific folder. It takes the filename of the document an set this for the „DocumentTitle“ property.

package de.company.filenet.importer;

import com.filenet.api.collection.ContentElementList;
import com.filenet.api.constants.*;
import com.filenet.api.core.*;
import com.filenet.api.property.Properties;
import com.filenet.api.util.UserContext;
import org.w3c.dom.Document;

import javax.security.auth.Subject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.*;

/**
 * FileNet P8 5.7 - Dokument-Importer
 *
 * Liest alle Dateien aus einem lokalen Ordner und importiert sie in
 * einen FileNet P8 Object Store. Der Dateiname wird in das Property
 * "DocumentTitle" der Dokumentklasse geschrieben.
 *
 * Erfolgreich importierte Dateien werden in den "done"-Ordner verschoben,
 * fehlgeschlagene in den "error"-Ordner.
 *
 * Aufruf:
 *   java -cp "filenet-importer-1.0.0-jar-with-dependencies.jar;lib\Jace.jar;lib\javaapi.jar;lib\pe.jar"
 *        de.company.filenet.importer.FileNetImporter config.xml
 */
public class FileNetImporter {

    private static final Logger LOG = Logger.getLogger(FileNetImporter.class.getName());

    // ---------------------------------------------------------------- Config fields
    private String ceUri;
    private String username;
    private String password;
    private String stanza;
    private String objectStoreName;
    private String sourceFolderPath;
    private boolean recursive;
    private Set<String> allowedExtensions;
    private String documentClass;
    private String targetFolderPath;
    private String checkinState;
    private String mimeTypeMode;
    private String logFile;
    private String doneFolderPath;
    private String errorFolderPath;

    // ---------------------------------------------------------------- Main
    public static void main(String[] args) {
        String configPath = args.length > 0 ? args[0] : "config.xml";
        FileNetImporter importer = new FileNetImporter();
        try {
            importer.loadConfig(configPath);
            importer.setupLogging();
            importer.run();
        } catch (Exception e) {
            System.err.println("Fehler beim Import: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // ---------------------------------------------------------------- Configuration
    private void loadConfig(String configPath) throws Exception {
        File configFile = new File(configPath);
        if (!configFile.exists()) {
            throw new FileNotFoundException("Konfigurationsdatei nicht gefunden: " + configPath);
        }

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(configFile);
        doc.getDocumentElement().normalize();

        ceUri            = getTextContent(doc, "ce-uri");
        username         = getTextContent(doc, "username");
        password         = getTextContent(doc, "password");
        stanza           = getTextContent(doc, "stanza");
        objectStoreName  = getTextContent(doc, "name");        // <name> under <object-store>
        sourceFolderPath = getTextContent(doc, "source-folder");
        recursive        = Boolean.parseBoolean(getTextContent(doc, "recursive"));
        documentClass    = getTextContent(doc, "document-class");
        targetFolderPath = getTextContent(doc, "target-folder");
        checkinState     = getTextContent(doc, "checkin-state");
        mimeTypeMode     = getTextContent(doc, "mime-type");
        logFile          = getTextContent(doc, "log-file");
        doneFolderPath   = getTextContent(doc, "done-folder");
        errorFolderPath  = getTextContent(doc, "error-folder");

        String extRaw = getTextContent(doc, "file-extensions");
        allowedExtensions = new HashSet<>();
        if (extRaw != null && !extRaw.trim().isEmpty()) {
            for (String ext : extRaw.split(",")) {
                allowedExtensions.add(ext.trim().toLowerCase());
            }
        }
    }

    private String getTextContent(Document doc, String tagName) {
        var nodes = doc.getElementsByTagName(tagName);
        if (nodes.getLength() > 0) {
            return nodes.item(0).getTextContent().trim();
        }
        return "";
    }

    // ---------------------------------------------------------------- Logging Setup
    private void setupLogging() throws IOException {
        FileHandler fileHandler = new FileHandler(logFile, true);
        fileHandler.setFormatter(new SimpleFormatter() {
            private static final String FORMAT = "[%1$tF %1$tT] [%2$s] %3$s %n";
            @Override
            public synchronized String format(LogRecord lr) {
                return String.format(FORMAT,
                        new Date(lr.getMillis()),
                        lr.getLevel().getLocalizedName(),
                        lr.getMessage()
                );
            }
        });
        LOG.addHandler(fileHandler);
        LOG.setLevel(Level.INFO);
        LOG.info("=== FileNet Importer gestartet ===");
        LOG.info("Quelle      : " + sourceFolderPath);
        LOG.info("Done-Ordner : " + doneFolderPath);
        LOG.info("Error-Ordner: " + errorFolderPath);
        LOG.info("CE-URI      : " + ceUri);
        LOG.info("Object Store: " + objectStoreName);
        LOG.info("FN-Ordner   : " + targetFolderPath);
    }

    // ---------------------------------------------------------------- Core Logic
    private void run() throws Exception {
        // 1. Dateien ermitteln
        List<File> files = collectFiles(new File(sourceFolderPath));
        if (files.isEmpty()) {
            LOG.info("Keine Dateien zum Importieren gefunden.");
            return;
        }
        LOG.info("Gefundene Dateien: " + files.size());

        // 2. Done/Error-Ordner lokal sicherstellen
        File doneFolder  = ensureLocalFolder(doneFolderPath);
        File errorFolder = ensureLocalFolder(errorFolderPath);

        // 3. FileNet-Verbindung aufbauen
        Connection connection = Factory.Connection.getConnection(ceUri);
        Subject subject = UserContext.createSubject(connection, username, password, stanza);
        UserContext.get().pushSubject(subject);

        try {
            Domain domain = Factory.Domain.fetchInstance(connection, null, null);
            ObjectStore os = Factory.ObjectStore.fetchInstance(domain, objectStoreName, null);
            LOG.info("Verbunden mit Object Store: " + os.get_DisplayName());

            // 4. Zielordner in FileNet holen oder anlegen
            Folder targetFolder = getOrCreateFolder(os, targetFolderPath);

            // 5. Dokumente importieren
            int success = 0, failed = 0;
            for (File file : files) {
                try {
                    importDocument(os, targetFolder, file);
                    moveFile(file, doneFolder);
                    success++;
                    LOG.info("[OK]     " + file.getName() + "  ->  done");
                } catch (Exception e) {
                    moveFile(file, errorFolder);
                    failed++;
                    LOG.severe("[FEHLER] " + file.getName() + "  ->  error | " + e.getMessage());
                }
            }
            LOG.info("=== Import abgeschlossen: " + success + " OK, " + failed + " Fehler ===");

        } finally {
            UserContext.get().popSubject();
        }
    }

    // ---------------------------------------------------------------- Local Folder Helpers
    private File ensureLocalFolder(String path) {
        File folder = new File(path);
        if (!folder.exists()) {
            if (folder.mkdirs()) {
                LOG.info("Lokaler Ordner angelegt: " + folder.getAbsolutePath());
            } else {
                LOG.warning("Lokaler Ordner konnte nicht angelegt werden: " + folder.getAbsolutePath());
            }
        }
        return folder;
    }

    private void moveFile(File file, File targetDir) {
        File dest = new File(targetDir, file.getName());

        // Falls Dateiname im Ziel bereits existiert -> Zeitstempel anhaengen
        if (dest.exists()) {
            String ts   = new SimpleDateFormat("yyyyMMdd_HHmmssSSS").format(new Date());
            String name = file.getName();
            int dot     = name.lastIndexOf('.');
            String newName = dot >= 0
                    ? name.substring(0, dot) + "_" + ts + name.substring(dot)
                    : name + "_" + ts;
            dest = new File(targetDir, newName);
        }

        if (!file.renameTo(dest)) {
            LOG.warning("Datei konnte nicht verschoben werden: " + file.getName()
                    + " -> " + dest.getAbsolutePath());
        }
    }

    // ---------------------------------------------------------------- File Collection
    private List<File> collectFiles(File folder) {
        List<File> result = new ArrayList<>();
        if (!folder.exists() || !folder.isDirectory()) {
            LOG.warning("Quellordner existiert nicht oder ist kein Verzeichnis: "
                    + folder.getAbsolutePath());
            return result;
        }

        File[] entries = folder.listFiles();
        if (entries == null) return result;

        for (File f : entries) {
            if (f.isFile()) {
                if (isAllowed(f)) result.add(f);
            } else if (f.isDirectory() && recursive) {
                result.addAll(collectFiles(f));
            }
        }
        return result;
    }

    private boolean isAllowed(File f) {
        if (allowedExtensions.isEmpty()) return true;
        String name = f.getName().toLowerCase();
        int dot = name.lastIndexOf('.');
        if (dot < 0) return false;
        return allowedExtensions.contains(name.substring(dot + 1));
    }

    // ---------------------------------------------------------------- FileNet Folder Handling
    private Folder getOrCreateFolder(ObjectStore os, String folderPath) {
        try {
            return Factory.Folder.fetchInstance(os, folderPath, null);
        } catch (Exception e) {
            LOG.info("Zielordner nicht gefunden, wird angelegt: " + folderPath);
            return createFolderPath(os, folderPath);
        }
    }

    private Folder createFolderPath(ObjectStore os, String folderPath) {
        String[] parts = folderPath.split("/");
        Folder current = Factory.Folder.fetchInstance(os, "/", null);

        StringBuilder currentPath = new StringBuilder();
        for (String part : parts) {
            if (part.isEmpty()) continue;
            currentPath.append("/").append(part);
            try {
                current = Factory.Folder.fetchInstance(os, currentPath.toString(), null);
            } catch (Exception e) {
                Folder newFolder = Factory.Folder.createInstance(os, null);
                newFolder.set_FolderName(part);
                newFolder.set_Parent(current);
                newFolder.save(RefreshMode.NO_REFRESH);
                current = Factory.Folder.fetchInstance(os, currentPath.toString(), null);
            }
        }
        return current;
    }

    // ---------------------------------------------------------------- Document Import
    @SuppressWarnings("unchecked")
    private void importDocument(ObjectStore os, Folder targetFolder, File file) throws Exception {

        // Dokumenttitel = Dateiname (mit Extension)
        String documentTitle = file.getName();

        // MIME-Type ermitteln
        String mimeType;
        if ("auto".equalsIgnoreCase(mimeTypeMode) || mimeTypeMode.isEmpty()) {
            mimeType = URLConnection.guessContentTypeFromName(file.getName());
            if (mimeType == null) mimeType = "application/octet-stream";
        } else {
            mimeType = mimeTypeMode;
        }

        // Dokument-Instanz erstellen
        com.filenet.api.core.Document doc =
                Factory.Document.createInstance(os, documentClass);

        // Properties setzen
        Properties props = doc.getProperties();
        props.putValue("DocumentTitle", documentTitle);

        // Primaerinhalt hinzufuegen
        ContentElementList contentList = Factory.ContentElement.createList();
        ContentTransfer ct = Factory.ContentTransfer.createInstance();
        ct.setCaptureSource(new FileInputStream(file));
        ct.set_ContentType(mimeType);
        ct.set_RetrievalName(file.getName());
        contentList.add(ct);
        doc.set_ContentElements(contentList);

        // Checkin
        doc.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
        doc.save(RefreshMode.NO_REFRESH);

        // Im Zielordner ablegen
        ReferentialContainmentRelationship rcr =
                targetFolder.file(doc,
                        AutoUniqueName.AUTO_UNIQUE,
                        documentTitle,
                        DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
        rcr.save(RefreshMode.NO_REFRESH);
    }
}

In addition you need this config.xml to setup the import scenario

<?xml version="1.0" encoding="UTF-8"?>
<filenet-import-config>

    <!-- FileNet P8 Connection Settings -->
    <connection>
        <ce-uri>http://HOSTNAME:PORT/wsi/FNCEWS40MTOM/</ce-uri>
        <username>p8user</username>
        <password>PASSW?RD</password>
        <stanza>FileNetP8</stanza>
    </connection>

    <!-- Object Store -->
    <object-store>
        <name>OS1</name>
    </object-store>

    <!-- Import Source -->
    <import>
        <source-folder>D:/BankStatements/import</source-folder>
        <recursive>false</recursive>
        <!-- Comma-separated list of file extensions to import (leave empty for all) -->
        <file-extensions>pdf,docx,xlsx,tif,tiff,png,jpg</file-extensions>
        <!-- Erfolgreich importierte Dateien werden hierhin verschoben -->
        <done-folder>D:/BankStatements/import/done</done-folder>
        <!-- Fehlgeschlagene Dateien werden hierhin verschoben -->
        <error-folder>D:/BankStatements/import/error</error-folder>
    </import>

    <!-- FileNet Document Settings -->
    <document>
        <!-- FileNet Document Class to use for imported documents -->
        <document-class>BankStatements</document-class>
        <!-- Target folder path in FileNet (must exist) -->
        <target-folder>/ClbTeamspaces/2026/01/Bank Statements_1768463079162</target-folder>
        <!-- Checkin state: RELEASED or RESERVATION -->
        <checkin-state>RELEASED</checkin-state>
        <!-- Mime type detection: auto or fixed value e.g. application/pdf -->
        <mime-type>auto</mime-type>
    </document>

    <!-- Logging -->
    <logging>
        <log-file>filenet-import.log</log-file>
        <!-- Level: INFO, DEBUG, WARN, ERROR -->
        <log-level>INFO</log-level>
    </logging>

</filenet-import-config>

After importing the documents the successfull files are moved to the done folder and error files will be stored in the error folder.

To create a runable programm you need to have the following.

  1. download and install a proper JDK version e.g. JAVA 17
  2. download an install maven from https://maven.apache.org/
  3. download the latest FileNet P8 java api files and copy the Jace,jar and pe.jar in the lib directory of the _build directory

run „mvn clean package“ to create the jar file. Now you can run the programm from a shell with the following syntax:

java -Djava.security.auth.login.config=jaas.conf -cp "filenet-importer-1.0.0-jar-with-dependencies.jar;lib\Jace.jar;lib\pe.jar" de.company.filenet.importer.FileNetImporter config.xml