JDK-6182986 : Default printer lookup doesn't track changes to the default printer
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.2
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2004-10-22
  • Updated: 2010-04-02
  • Resolved: 2005-03-30
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Calling PrintServiceLookup.lookupDefaultPrintService() correctly returns the default printer. Changing the default printer in the Windows Start/Settings/Printer menu and then running PrintServiceLookup.lookupDefaultPrintService() again, returns the old default printer, not the new one.

This happens in both JDK 1.4.2 and the JDK 1.5.0 beta.

 I realize that the caching done in PrintServiceLookup makes sense. I suggest some way to clear the cache so that the underlying OS interface code will be called again, should the programmer desire.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use a Windows 2000 computer with at least two printers installed. In a "cmd" window, compile and run the DefaultPrinterTest class below. Type <Enter>. Notice that the default printer is printed twice, once as the "API default printer" and once as the "Internal default printer". Right click on a different printer in the Windows Start/Settings/Printers menu and choose "Set as Default Printer" from the resulting pop-up menu. Type <Enter> again at your Java command window. The "API default printer" will be what it was before. The "Internal default printer" will change to the new default you just set.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected to see the "API default printer" track changes to the Windows environment. As I said above, I would be OK with being required to call a PrintServiceLookup.clearCaches() method, or some such, but I can see no way to do that now.
ACTUAL -
C:\>java DefaultPrinterTest
<Enter> to lookup, Ctrl-C to exit:
API default printer:      \\NTCOINS\lj2
Internal default printer: \\NTCOINS\lj2
<Enter> to lookup, Ctrl-C to exit:
API default printer:      \\NTCOINS\lj2
Internal default printer: FAXmaker
<Enter> to lookup, Ctrl-C to exit:

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/* DefaultPrinterTest.java */

import javax.print.PrintServiceLookup;
import javax.print.PrintService;
import sun.misc.Service;

import java.util.Iterator;
import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * Test PrintServiceLookup.lookupDefaultPrintService();
 * Type <Enter> when prompted. Then change the default printer
 * by right-clicking on a printer in the Start/Settings/Printers
 * menu and choosing "Set as Default Printer". Then type
 * <Enter> to lookup the default printer again. The documented
 * API method does NOT change, but the underlying low-level
 * code does.
 */
public class DefaultPrinterTest {

  public static void main(String[] args) {
    BufferedReader reader =
      new BufferedReader(new InputStreamReader(System.in));
    while(true) {
      try {
        System.out.print("<Enter> to lookup, Ctrl-C to exit: ");
        String line = reader.readLine();
        PrintService s1 = PrintServiceLookup.lookupDefaultPrintService();
        PrintService s2 = getDefaultPrintService();
        System.out.println("API default printer:      " + s1.getName());
        System.out.println("Internal default printer: " + s2.getName());
      } catch (Exception e) {}
    }
  }

  /**
   * Get the default PrintService from the low-level code.
   * Extracted from the source for
   * PrintServiceLookup.lookupDefaultPrintService();
   */
  public static PrintService getDefaultPrintService() {
    Iterator i = Service.providers(PrintServiceLookup.class);
    while (i.hasNext()) {
      PrintServiceLookup service = (PrintServiceLookup)i.next();
      PrintService ds = (PrintService)service.getDefaultPrintService();
      if (ds != null) return ds;
    }
    return null;
  }
}

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

CUSTOMER SUBMITTED WORKAROUND :
The getDefaultPrintService() method in the example above. In commercial code, I'll have to change it to use introspection for looking up the Service class and calling its providers method, just in case Sun changes the implementation. I'll also have to check to ensure that the result is in the cached set of print services, likely returning the cached service with the same name as the default I found with the low-level code.
###@###.### 10/22/04 00:27 GMT

Comments
EVALUATION This probably needs to be considered at the same time as 4744405 RFE: lookupPrintServices() to refresh the printers list dynamically since the new default printer may not even be in the original set. ###@###.### 10/22/04 00:29 GMT This is addressed as part of 4744405. Marking as dup of that bug. ###@###.### 2005-03-30 18:48:27 GMT
22-10-2004