Custom File Upload Quicklink

@blazejbadzio As discussed here are the code snippets:

faces-config-snippet


  <managed-bean>
    <managed-bean-name>uploadNICFile</managed-bean-name>
    <managed-bean-class>org.object.UploadNICFile</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>
    <navigation-rule>
      <description>uploadNICFile</description>
      <from-view-id>/workitem/uploadNicFileForm.xhtml</from-view-id>
      <navigation-case>
          <from-outcome>UploadNICFile</from-outcome>
          <to-view-id>/workitem/uploadNicFileForm.xhtml</to-view-id>
          <redirect />
      </navigation-case>
      <navigation-case>
          <from-outcome>success</from-outcome>
          <to-view-id>/home.jsf</to-view-id>
          <redirect />
      </navigation-case>
    </navigation-rule>


uploadNicFileForm

<ui:component
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">

  <style type="text/css">
    .upload-container {
        padding: 20px;
        background-color: #f9f9f9;
        border: 1px solid #ddd;
        border-radius: 8px;
        font-family: 'Inter', sans-serif;
    }
    .upload-header {
        font-size: 24px;
        color: #037DA1;
        font-weight: bold;
        margin-bottom: 20px;
    }
    .upload-field {
        margin-bottom: 15px;
    }
    .upload-label {
        font-weight: 600;
        margin-right: 10px;
        color: #333;
    }
    .upload-box {
        border: 2px dashed #037DA1;
        padding: 30px;
        text-align: center;
        border-radius: 6px;
        background: #fff;
        margin-bottom: 20px;
    }
    .btn-group {
        margin-top: 20px;
    }
  </style>

  <h:form id="uploadForm" enctype="multipart/form-data">

    <div class="upload-container">
      <div class="upload-header">NIC File Upload</div>

      <div class="upload-field">
        <h:outputLabel for="server" value="Server Instance: " styleClass="upload-label"/>
        <h:inputText id="server" value="#{uploadNICFile.server}" 
                     style="width:300px; padding:8px; border:1px solid #ccc; border-radius:4px;"/>
      </div>

      <div class="upload-box">
        <h:outputLabel value="Select File to Upload" style="font-weight:bold; display:block; margin-bottom:15px; font-size:16px;"/>
        <!-- Native JSF 2.2 file upload -->
        <h:inputFile id="nicFile" 
                     value="#{uploadNICFile.uploadedFile}"
                     style="margin:auto; display:inline-block;"/>
      </div>

      <div class="btn-group">
        <h:commandButton id="submitBtn"
                         value="Save and Complete"
                         action="#{uploadNICFile.saveAction}"
                         styleClass="primaryBtn"
                         style="padding:12px 30px; border-radius:4px; cursor:pointer; font-weight:bold;"/>
        
        <h:commandButton value="Cancel"
                         action="#{uploadNICFile.cancelAction}"
                         immediate="true"
                         styleClass="secondaryBtn"
                         style="margin-left:15px; padding:12px 30px; border-radius:4px; cursor:pointer;"/>
      </div>

      <h:messages id="messages" globalOnly="false" layout="list"
                  infoStyle="color:green; margin-top:15px;" 
                  errorStyle="color:red; margin-top:15px;"
                  style="font-family:sans-serif; list-style-type:none; padding-left:0;"/>

    </div>

  </h:form>

</ui:component>

Workflow

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1775718388251" explicitTransitions="true" id="7f0000019d701d0e819d7110521b2dd9" modified="1775721074783" name="Community-Workflow-Upload-NIC-file" significantModified="1775721074783" type="UpdateIdentity">
  <Variable initializer="true" name="transient"/>
  <Variable input="true" name="requester"/>
  <Variable input="true" name="lastApprovalState"/>
  <Variable input="true" name="approved"/>
  <Variable initializer="Upload NIC file" name="flow"/>
  <Variable initializer="false" name="optimisticProvisioning"/>
  <Variable initializer="spadmin" name="fallbackApprover">
    <Description>A String that specifies the name of the Identity that will
      be assigned any approvals where the owner of the approver
      can&amp;#39;t be resolved. Example if the scheme is &amp;quot;owner&amp;quot; and the
      application doesn&amp;#39;t specify and owner.</Description>
  </Variable>
  <Step icon="Start" name="Start" posX="28" posY="10">
    <Approval mode="serial" name="NIC File Upload Form" owner="ref:requester" renderer="uploadNicFileForm.xhtml">
      <Arg name="workItemType" value="Test"/>
    </Approval>
    <Transition to="Stop" when="approved"/>
  </Step>
  <Step icon="Stop" name="Stop" posX="508" posY="10"/>
</Workflow>

UploadNICFile.java

package org.object;

import javax.faces.context.FacesContext;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.servlet.http.Part;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import sailpoint.api.SailPointContext;
import sailpoint.api.SailPointFactory;
import sailpoint.object.WorkItem;

@ManagedBean(name="uploadNICFile")
@SessionScoped
public class UploadNICFile {

    private String server;
    private Part uploadedFile;

    private static final Logger log = LogManager.getLogger("tempFile.Logger");

    public UploadNICFile() {
        System.out.println("UploadNICFile bean instantiated.");
    }

    public Part getUploadedFile(){
        return this.uploadedFile;
    }

    public void setUploadedFile(Part uploadedFile){
        this.uploadedFile = uploadedFile;
    }

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public void cancelAction(){
        System.out.println("cancelAction() called.");
        this.uploadedFile = null;
    }

    public String saveAction() {
        System.out.println("saveAction() ENTERED.");
        log.info("saveAction() triggered.");
        log.info("Server value = " + this.server);
        log.info("UploadedFile (Part) = " + (this.uploadedFile != null ? this.uploadedFile.getSubmittedFileName() : "null"));

        try {
            if (uploadedFile != null) {
                String fileName = uploadedFile.getSubmittedFileName();
                
                // Clean filename from path characters
                if (fileName != null) {
                    if (fileName.contains("\\")) {
                        fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
                    } else if (fileName.contains("/")) {
                        fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
                    }
                } else {
                    fileName = "uploaded_file_" + System.currentTimeMillis();
                }

                String baseDir = "<YourDirectory Path>";
                File dir = new File(baseDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                File targetFile = new File(dir, fileName);
                System.out.println("Attempting to save to " + targetFile.getAbsolutePath());
                log.info("Saving file to: " + targetFile.getAbsolutePath());

                try (InputStream input = uploadedFile.getInputStream();
                     OutputStream output = new FileOutputStream(targetFile)) {

                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = input.read(buffer)) != -1) {
                        output.write(buffer, 0, bytesRead);
                    }
                    System.out.println("File saved successfully: " + targetFile.length() + " bytes");
                    log.info("File saved: " + targetFile.length() + " bytes");
                    
                    try {
                        SailPointContext context = SailPointFactory.getCurrentContext();
                        // Retrieve the Work Item ID from the request parameter
                        String workItemId = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
                        
                        if (workItemId != null) {
                            WorkItem wi = context.getObjectById(WorkItem.class, workItemId);
                            if (wi != null) {
                                System.out.println("Completing Work Item " + workItemId);
                                log.info("Automatically completing Work Item: " + workItemId);
                                wi.setState(WorkItem.State.Finished);
                                wi.setAttribute("approved", true); // Signal workflow transition
                                context.saveObject(wi);
                                context.commitTransaction();
                            }
                        }
                    } catch (Exception ex) {
                        System.err.println("Work Item Completion failed: " + ex.getMessage());
                        log.error("Error during automatic Work Item completion: " + ex.getMessage());
                    }

                    this.uploadedFile = null;
                    return "success";
                }
            } else {
                System.out.println("uploadedFile (Part) is NULL in saveAction.");
            }
        } catch (Throwable t) {
            System.err.println(" CRITICAL ERROR in saveAction():");
            t.printStackTrace();
            log.error("Failed to save file: " + t.getMessage(), t);
        }
        
        return null;
    }
}