Updating printers in Java while the application is running

As the title says, I would like to update the printers registered in my computer settings while my Java application was running. Usually I can use PrinterJob.lookupPrintServices() to get printers. However, they are only updated when the application restarts. I read something on this lookupPrintServices () must be done in a new thread in order to get printers. However, this did not help; the list of printers remained the same. The following link shows that this problem should be fixed in Java 5.0, am I something wrong?

Any help is much appreciated!

EDIT Added by MWE.

 public class MTPrinterTest extends Thread { public static void main(String[] args) { MTPrinterTest t1 = new MTPrinterTest(); t1.start(); try { System.in.read(); } catch (Exception e){} MTPrinterTest t2 = new MTPrinterTest(); t2.start(); } public void run() { PrinterJob printerJob; PrintService[] printServices; printerJob = PrinterJob.getPrinterJob(); printServices = printerJob.lookupPrintServices(); System.out.println("Number of servies found: " + printServices.length); for (int i =0; i< printServices.length; i++) System.out.println("--> Available Printer " + i + ": " + printServices[i]); printerJob.printDialog(); } } 
+6
source share
4 answers

There is no need to restart the application to update the list of print services.

Here I found a solution:

 /** * Printer list does not necessarily refresh if you change the list of * printers within the O/S; you can run this to refresh if necessary. */ public static void refreshSystemPrinterList() { Class<?>[] classes = PrintServiceLookup.class.getDeclaredClasses(); for (Class<?> clazz : classes) { if ("javax.print.PrintServiceLookup$Services".equals(clazz.getName())) { // sun.awt.AppContext.getAppContext().remove(clazz); // Use reflection to avoid "Access restriction" error message try { Class<?> acClass = Class.forName("sun.awt.AppContext"); Object appContext = acClass.getMethod("getAppContext").invoke(null); acClass.getMethod("remove", Object.class).invoke(appContext, clazz); } catch (Exception e) { } break; } } } 

In essence, the static class PrintServiceLookup.Services maintains a list of print services. Thus, if you remove this class from the AppContext , you will force PrintServiceLookup to create a new instance again. Thus, the list of printing services is updated.

+3
source

I ran into the same problem before and after several tests, it seems that the list of printers is unchecked at the beginning of the Java application and cannot be updated after that with java lookupPrintServices() .

What I did to solve this problem was to call the Winspool API using JNA. If you intend to do this, the Winspool API is well documented by Microsoft: Winspool API Documentation

In addition, I described part of my solution to the problem that I had several months ago in this issue, this can help you understand the JNA and Winspool APIs.

+1
source

A quick workaround for CUPS based systems:

 System.setProperty("sun.java2d.print.polling", "false"); 

Caution, this is a side effect of slowing down calls (e.g. 80ms ) to PrintServiceLookup.lookupPrintServices(...) .

In particular:

The sun.java2d.print.polling property sun.java2d.print.polling set to true :

  • <1ms call PrintServiceLookup.lookupPrintServices(...)

The sun.java2d.print.polling property sun.java2d.print.polling set to false :

  • 80ms call PrintServiceLookup.lookupPrintServices(...)

Although 80 ms is a very short time span for most user interfaces, in a high-load scenario this can affect performance.

In addition, this 80ms gradually increases with time. For example, 100,000 calls to PrintServiceLookup.lookupPrintServices(...) gradually increase the delay from 80ms to 1,000ms . Long-term programs may experience a noticeable delay.

However, this delay is still preferable to the AppContext , especially on CUPS (Linux, Mac) systems. AppContext provided in other solutions presents JVM streaming problems that ultimately lead to 2,000ms delays and sometimes 200,000ms delays (link: https://github.com/qzind/tray/issues/479 )

Detailed error report: https://github.com/AdoptOpenJDK/openjdk-build/issues/1212

0
source

I'm not sure what you expected. Here's the output for my Windows Vista laptop running Java 7.

 Number of servies found: 3 --> Available Printer 0: Win32 Printer : PamFax --> Available Printer 1: Win32 Printer : Microsoft XPS Document Writer --> Available Printer 2: Win32 Printer : CutePDF Writer x Number of servies found: 3 --> Available Printer 0: Win32 Printer : PamFax --> Available Printer 1: Win32 Printer : Microsoft XPS Document Writer --> Available Printer 2: Win32 Printer : CutePDF Writer 

Printer services do not change every 5 minutes, even on a shared network.

Updated based on comment:

Your Java application will need to stop and start receiving an updated list of printers.

I think I do not understand your environment. In the places where I worked, all printers were defined on the network long before we ever wrote any code. Changes to the printer were rare (I mean once a year).

-2
source

Source: https://habr.com/ru/post/982328/


All Articles