@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&#39;t be resolved. Example if the scheme is &quot;owner&quot; and the
application doesn&#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;
}
}