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.
- download and install a proper JDK version e.g. JAVA 17
- download an install maven from https://maven.apache.org/
- 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