NotSerializableException: java.io.ByteArrayInputStream

Hello,

I’ve got a few screen controllers that use create an image in the same exact way, so I’m attempting to move this into a service, but my return object is a ByteArrayInputStream so I can assign the image that is created as a resource. However, I’m running into a NotSerializableException issue. I found this post which tells why it is occurring, but I haven’t found a solution.

I’ve tried everything I can think of, like simply adding the Serializable implementation to the service bean, having the service itself extend Serializable, returning BufferedImage instead of ByteArrayInputStream, looking for methods to serialize the return element, and praying. None of this worked.

My screen controller method:

    private void createShowBarcode() {
        actionDescriptionLabel.setValue(actionDescription);

        barcodeImage.setSource(StreamResource.class)
                .setStreamSupplier(() -> barcodeService.createBarcode(barcodeText, barcodeType));

        barcodeLabel.setValue(barcodeText + " - " + barcodeType.getId());
    }

My service:

public interface BarcodeService {
    String NAME = "bxjfp_BarcodeService";
    ByteArrayInputStream createBarcode(String barcodeTextToTransform, BarcodeTypeEnum barcodeType);
}

My service bean:

@Service(BarcodeService.NAME)
public class BarcodeServiceBean implements BarcodeService {
    @Inject
    private Logger log;

    public ByteArrayInputStream createBarcode(String barcodeTextToTransform, BarcodeTypeEnum barcodeType) {
        switch (barcodeType) {
            case CODE_39:
                return createCode39(barcodeTextToTransform);
            case CODE_128:
                return createCode128(barcodeTextToTransform);
            case QR:
                return createQR(barcodeTextToTransform);
        }

        return null;
    }

    private ByteArrayInputStream createQR(String barcodeTextToTransform) {
        try {
            QRCodeWriter barcodeWriter = new QRCodeWriter();

            return bitMatrixToByteArrayInputStream(
                    barcodeWriter.encode(barcodeTextToTransform, BarcodeFormat.QR_CODE, 300, 150));
        } catch (WriterException e) {
            log.info("WriterException: " + e.getMessage());

            return null;
        }
    }

    public ByteArrayInputStream createCode128(String barcodeText) {
        Code128Writer barcodeWriter = new Code128Writer();

        return bitMatrixToByteArrayInputStream(barcodeWriter.encode(barcodeText, BarcodeFormat.CODE_128, 300, 150));
    }

    private ByteArrayInputStream createCode39(String barcodeText) {
        Code39Writer barcodeWriter = new Code39Writer();

        return bitMatrixToByteArrayInputStream(barcodeWriter.encode(barcodeText, BarcodeFormat.CODE_39, 300, 150));
    }

    private ByteArrayInputStream bitMatrixToByteArrayInputStream(BitMatrix bitMatrix) {
        BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpeg", byteArrayOutputStream);
            byte[] imageBytes = byteArrayOutputStream.toByteArray();

            return new ByteArrayInputStream(imageBytes);
        } catch (IOException e) {
            log.error("IOException: " + e.getMessage());

            return null;
        }
    }

}

Will you please show me how this needs to be fixed in the middle tier?

Thank you,
Adam

Hi,
If your barcodes are not very big, then you can just change result type of the service method to byte[].
InputStream instances will not work here as you expect, as middleware services serialize all parameters and results when invoked.

Beautiful. Good thinking. Thank you very much!

Adam