Search code examples
javanullpointerexceptionjcifs

Getting NullPointerException with SmbFileInputStream


Trying to modify excel which is in another machine. Passing IP address, username, password and file path to access and modify file, but getting NullPointerException at new SmbFileInputStream(sFile). What is the reason for this?

NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domin", "username", "password");
                String path = "smb:\\\\<IPaddress>\\C$\\<FolderName>\\File%20-%20Input.xlsx";
                SmbFile sFile = new SmbFile(path, auth);



                try {
                    SmbFileInputStream inputStream = new SmbFileInputStream(sFile);
                    Workbook workbook = WorkbookFactory.create(inputStream);

                    Sheet sheet = workbook.getSheetAt(0);
                    int rowCount = sheet.getLastRowNum(),i=0;
                    Cell cell;
                    for(ForemostReservedDataDO obj : unsavedRecords){
                        i++;
                        Row row = sheet.createRow(rowCount+i);
                        cell = row.createCell(0);
                        cell.setCellValue(obj.getPolicyNum());
                        cell = row.createCell(1);
                        cell.setCellValue("Recreational Value");
                    }
                    inputStream.close();

                    SmbFileOutputStream sfos = new SmbFileOutputStream(sFile);
                    workbook.write(sfos);
                    workbook.close();
                    sfos.close();

                } catch (EncryptedDocumentException | InvalidFormatException | IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

Full Stack

SEVERE: Servlet.service() for servlet [spring-dispatcher] in context with path [/Foremost] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
    at jcifs.smb.ServerMessageBlock.writeString(ServerMessageBlock.java:213)
    at jcifs.smb.ServerMessageBlock.writeString(ServerMessageBlock.java:202)
    at jcifs.smb.SmbComNTCreateAndX.writeBytesWireFormat(SmbComNTCreateAndX.java:170)
    at jcifs.smb.AndXServerMessageBlock.writeAndXWireFormat(AndXServerMessageBlock.java:101)
    at jcifs.smb.AndXServerMessageBlock.encode(AndXServerMessageBlock.java:65)
    at jcifs.smb.SmbTransport.doSend(SmbTransport.java:439)
    at jcifs.util.transport.Transport.sendrecv(Transport.java:67)
    at jcifs.smb.SmbTransport.send(SmbTransport.java:655)
    at jcifs.smb.SmbSession.send(SmbSession.java:238)
    at jcifs.smb.SmbTree.send(SmbTree.java:119)
    at jcifs.smb.SmbFile.send(SmbFile.java:775)
    at jcifs.smb.SmbFile.open0(SmbFile.java:989)
    at jcifs.smb.SmbFile.open(SmbFile.java:1006)
    at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:73)
    at jcifs.smb.SmbFileInputStream.<init>(SmbFileInputStream.java:65)
    at com.Foremost.Controllers.DataDownController.saveReservedData(DataDownController.java:217)

Solution

  • Your JCIFS version seems to be outdated and not compatible with the remote system. Upgrade to latest JCIFS (current version: 2.1.3, https://github.com/codelibs/jcifs) or to jcifs-ng (https://github.com/AgNO3/jcifs-ng), from which the linked JCIFS is now a fork of.

    Here is some example code on how to use jcifs-ng for reading a file via SMB:

    String fileUrl = "smb://netserver/some/path/to/file.xls";
    
    Properties cifsProps = new Properties();
    cifsProps.setProperty("jcifs.smb.client.domain", "my.domain.int");
    cifsProps.setProperty("jcifs.smb.client.username", USER_NAME);
    cifsProps.setProperty("jcifs.smb.client.password", PASSWORD);
    
    Configuration config = new PropertyConfiguration(cifsProps);
    BaseContext context = new BaseContext(config);
    SmbResource resource = context.get(fileUrl);
    
    if (!(resource instanceof SmbFile)) {
        throw new CIFSException("File URL does not point to a file on a network share");
    }
    
    try (InputStream in = ((SmbFile) resource).getInputStream()) {
        // TODO read from in
    } finally {
        context.close();
    }
    

    For writing a file, well, I think you will be able to figure that out :-)