JDK-8223428 : NullPointerException in RasterPrinterJob
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 11.0.2
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2019-05-06
  • Updated: 2019-08-23
  • Resolved: 2019-05-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13
13Resolved
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
We have 3 different printers here.  The failure always happens on 2 of them.  (The two that don't work are color, while the one that works is black and white.  They are all HP printers.)

A DESCRIPTION OF THE PROBLEM :
   at java.desktop/sun.print.RasterPrinterJob.setAttributes(RasterPrinterJob.java:1280)
    at java.desktop/sun.awt.windows.WPrinterJob.setAttributes(WPrinterJob.java:696)
    at java.desktop/sun.print.RasterPrinterJob.print(RasterPrinterJob.java:1550)
    at java.desktop/sun.print.Win32PrintJob.pageableJob(Win32PrintJob.java:573)
    at java.desktop/sun.print.Win32PrintJob.print(Win32PrintJob.java:390)
    at dsi.system.print.client.ActPrint.execute(ActPrint.java:199)
    at dsi.client.request.AbstractRequest.processBackground(AbstractRequest.java:857)

REGRESSION : Last worked in version 8u202

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Some printers always work, some always fail.

Included source code is for an OLD test program I wrote a long time ago.  However, it acts just like my current production code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
For the print to succeed.


ACTUAL -
Some printers will fail every time.

Running this on on a Java 8 VM works every time for every printer.  Printers that fail, fail every time in a similar way on 11.0.1, 11.0.2, 11.0.3 and 12

---------- BEGIN SOURCE ----------
package java6print;

import javax.print.PrintService;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;

public class PrinterSettings implements Cloneable {

	private final float left;
	private final float right;
	private final float top;
	private final float bottom;
	private final int copies;
	private final int startPage;
	private final int endPage;
	private final boolean landscape;
	
	/** Creates a new instance of PrinterSettings */
	public PrinterSettings(float left, float right, float top, float bottom, int copies, int startPage, int endPage, boolean landscape) {
		this.left = left;
		this.right = right;
		this.top = top;
		this.bottom = bottom;
		this.copies = copies;
		this.startPage = startPage;
		this.endPage = endPage;
		this.landscape = landscape;
	}
	private void putCopies(PrintService service, PrintRequestAttributeSet set) {
		set.add(new Copies( copies ));
	}
	private void putPrintableArea(PrintService service, PrintRequestAttributeSet set) {
		set.add(MediaSizeName.NA_LETTER);
		
		MediaSize s = MediaSize.getMediaSizeForName( (MediaSizeName)set.get(Media.class) );
		float totalWidth = s.getX(MediaSize.INCH);
		float totalHeight = s.getY(MediaSize.INCH);
		
		MediaPrintableArea area;
		OrientationRequested or = (OrientationRequested)set.get(OrientationRequested.class);
		
		if (or.equals(OrientationRequested.REVERSE_LANDSCAPE) || or.equals(OrientationRequested.LANDSCAPE)) {
			area = new MediaPrintableArea(top,right, totalWidth - bottom - top, totalHeight - left - right, MediaPrintableArea.INCH);
		}
		else {
			area = new MediaPrintableArea(left,top, totalWidth - left - right, totalHeight - top - bottom, MediaPrintableArea.INCH);
		}
		set.add(area);
	}
	public boolean isLandscape() {
		return landscape;
	}
	private void putOrientation(PrintService service, PrintRequestAttributeSet set) {
		if (!isLandscape())
			set.add( OrientationRequested.PORTRAIT );
		else
			set.add( OrientationRequested.LANDSCAPE );
	}
	private void putPageRange(PrintService service, PrintRequestAttributeSet set) {
		set.add(new PageRanges(startPage,endPage));
	}
	public PrintRequestAttributeSet getAttributes(PrintService service) {
		PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
		putOrientation(service,attributes);
		putPrintableArea(service,attributes);
		putCopies(service,attributes);
		putPageRange(service,attributes);
		return attributes;

	}

	double getLeftMargin() {
		return left;
	}
	double getRightMargin() {
		return right;
	}
	double getTopMargin() {
		return top;
	}
	double getBottomMargin() {
		return bottom;
	}
}
-----------------------------------------------------

package java6print;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.InputStream;
import java.io.Reader;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.attribute.DocAttributeSet;
import javax.swing.JPanel;

public class PrintMe extends JPanel implements Printable, Doc {
	
	private final Dimension landscapeDim = new Dimension(11*72,(int)(8.5*72));
	private final Dimension portraitDim = new Dimension((int)8.5*72,(int)(11*72));
	private final Dimension dim;
	private final PrinterSettings printerSettings;
	
	private final int fontSize;

	public PrintMe(PrinterSettings settings, int fontSize) {
		printerSettings = settings;
		this.fontSize = fontSize;
		if (printerSettings.isLandscape())
			dim = landscapeDim;
		else
			dim = portraitDim;
		setPreferredSize( (Dimension)dim.clone() );
	}
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		draw((Graphics2D)g, 1.0);
	}
	private void draw(Graphics2D g2, double scale) {
		double leftMargin = printerSettings.getLeftMargin();
		double rightMargin = printerSettings.getRightMargin();
		double topMargin = printerSettings.getTopMargin();
		double bottomMargin = printerSettings.getBottomMargin();

		double leftOffset = leftMargin * 72;
		double rightOffset = rightMargin * 72;
		double topOffset = topMargin * 72;
		double bottomOffset = bottomMargin * 72;

		int bigWidth = dim.width - (int) ( rightOffset + leftOffset);
		int topHeight = 70;
		
		Graphics2D temp;
		
		Rectangle rect = new Rectangle( 0,0, bigWidth , topHeight); 

		temp = (Graphics2D)g2.create();
		temp.scale(scale,scale);
		temp.translate(leftOffset, topOffset);
		temp.setColor(Color.BLACK);
		temp.drawRect(rect.x, rect.y, rect.width-1, rect.height-1);
		temp.setFont(new Font("Arial",Font.PLAIN,fontSize));
		

		temp.setColor(Color.BLACK);
		drawString( temp, rect.x,rect.y, rect.width-1, rect.height-1,.5,.5,temp.getFontMetrics(),"April 2007");
		temp.dispose();
	}
	private Rectangle2D drawString(Graphics2D g2, double x, double y, double width, double height, double scaleX, double scaleY, FontMetrics fm, String s) {
		Rectangle2D rect = fm.getStringBounds(s,g2);
		System.err.println("rect: " + rect);
		x = x + (width - rect.getWidth()) * scaleX;
		y = y + (height - rect.getHeight()) * scaleY;
		double rectY = rect.getY();
		y -= rectY;
		g2.drawString(s, (float)x,(float)y);
		return rect;
	}
	public int print(Graphics g2, PageFormat pageFormat, int pageIndex) throws PrinterException {
		if (pageIndex == 0) {
			try {
				draw( (Graphics2D)g2,1.0);
				return Printable.PAGE_EXISTS;
			} catch (RuntimeException e) {
				e.printStackTrace();
				throw e;
			}
		} else
			return Printable.NO_SUCH_PAGE;
	}
	public DocFlavor getDocFlavor() {
		return new DocFlavor.SERVICE_FORMATTED("java.awt.print.Printable");
	}
	public Object getPrintData() {
		return this;
	}
	public Reader getReaderForText() {
		return null;
	}
	public InputStream getStreamForBytes() {
		return null;
	}
	public DocAttributeSet getAttributes() {
		return null;
	}
}
-------------------------------------------------------
/*
 * Main.java
 *
 * Created on December 14, 2006, 10:31 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package java6print;

import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.ServiceUI;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


public class Main extends JFrame {
	
	public Main() {
		//left, right, top, bottom,copies, startPage, endPage, landscape 
		//Last parameter is true for landscape, false for portrait
		PrinterSettings settings = new PrinterSettings(.5f, .5f ,1f, .5f, 1, 1, 1,true);
		//Font size is the last parameter.  50 will get negative width, 20 will not.
		PrintMe pm = new PrintMe(settings, 50);
		getContentPane().add(pm);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		pack();
		setVisible(true);
		print(pm,settings);
	}
	private void print(PrintMe pm, PrinterSettings settings) {
		try {
			DocFlavor f = new DocFlavor.SERVICE_FORMATTED("java.awt.print.Printable");
			
			PrintService[] services = PrintServiceLookup.lookupPrintServices(f, null);
			PrintRequestAttributeSet attributes = settings.getAttributes(null);
			PrintService service =  ServiceUI.printDialog(null, 50, 50, services, null,f,attributes);
			
			if (service != null) {
				DocPrintJob pj = service.createPrintJob();
				pj.print(pm,attributes);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				new Main();
			}
		});
	}
	
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Changed Lines 1273-1285 in sun.print.RasterPrinterJob openjdk 11.0.1

        printerResAttr = (PrinterResolution)attributes.get(PrinterResolution.class);
        if (service.isAttributeCategorySupported(PrinterResolution.class)) {
            if (!isSupportedValue(printerResAttr,  attributes)) {
               printerResAttr = (PrinterResolution)
                   service.getDefaultAttributeValue(PrinterResolution.class);
            }
            if (printerResAttr != null) { //LINE ADDED
	            double xr =
	               printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI);
	            double yr = printerResAttr.getFeedResolution(ResolutionSyntax.DPI);
	            setXYRes(xr, yr);
	        } //LINE ADDED
        }

FREQUENCY : always



Comments
This is a duplicate of JDK-8221411 and the workaround suggested in this bug is exactly the fix that was pushed http://hg.openjdk.java.net/jdk/jdk/rev/b10e1f4f8b69
07-05-2019

Checked with attached test case, but the issue does not reproduce with reported version. From the description the failure appears on a particular HO B&W printer and issue does occur in general. Attached: (PrinterBug.zip), test case to verify this issue.
07-05-2019