简体   繁体   中英

Do I need to call both .dispose() (javax.jcr.Binary) and .close() (java.io.InputStream)?

Do I need to define the Binary object separately so I can call .dispose(); on it (see methodOne() ) or will that be handled automatically when auto-closing the InputStream (see methodTwo() )?

private void methodOne(Resource resource) {
    Binary binary = resource.getValueMap().get("jcr:data", Binary.class);
    try {
        InputStream is = null;
        try {
            is = binary.getStream();
            // ...do something with the InputStream...
        } catch (RepositoryException e) {
            LOG.error("RepositoryException trying to get an InputStream from the resource.");
        } finally {
            if (is != null) {
                IOUtils.closeQuietly(is);
            }
        }
    } finally {
        binary.dispose();
    }
}

private void methodTwo(Resource resource) {
    try (InputStream is = resource.getValueMap().get("jcr:data", Binary.class).getStream()) {
        // ...do something with the InputStream...
    } catch (IOException e) {
        LOG.error("IOException from trying to auto-close InputStream.");
    } catch (RepositoryException e) {
        LOG.error("RepositoryException trying to get an InputStream from the resource.");
    }
}

I'm genuinely confused on how to even test if the anonymous Binary resource in methodTwo is being disposed of properly, which is why I'm even asking this question in the first place.

Unless the class you're getting the stream from documents that closing the stream is sufficient, then you need to ensure that you list the other closeable resources in the try to get try-with-resources to close them for you.

You've said Binary doesn't implement AutoCloseable . Irritating. :-) You could always define a wrapper (as I assume this isn't the only place you need to deal with this), something along these lines:

public class ACBinaryWrapper implements AutoCloseable {
    private Binary binary;

    public ACBinaryWrapper(Binary binary) {
        this.binary = binary;
    }

    public Binary getBinary() {
        return this.binary;
    }

    public void close() { 
        if (this.binary != null) {
            Binary b = this.binary;
            this.binary = null;
            b.dispose();
        }
    }
}

Then:

private void yourMethod(Resource resource) {
    try (
        ACBinaryWrapper acbinary = new ACBinaryWrapper(
            resource.getValueMap().get("jcr:data", Binary.class)
        );
        InputStream is = acbinary.getBinary().getStream();
    ) {
        // ...do something with the InputStream...
    } catch (IOException e) {
        // ...appropriate handling...
    } catch (RepositoryException e) {
        // ...appropriate handling...
    }
}

Note how binary is listed separately from is .


Your LOG statements in the IOException handler and such seemed to assume that the only I/O error that could occur was when closing the stream. In general, reading from streams can cause an I/O error as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM