JavaData & JavaHow to Add Java Print Services to Your Java Application

How to Add Java Print Services to Your Java Application

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Printing services is an important facility provided by any application programming framework. Java initially did not provide any such facility during its inception. But, in the later versions such as in 1.2 and 1.3, it introduced classes through java.awt and java.awt.print packages. These APIs formed the foundation of the new printing API services provided in the javax.print package. This article gives a preliminary idea about how to use the Java Print Services API in a Java application.

A Bit of History

The Printing Service API was formally introduced only after the release of Java 1.1. Versions prior to this had no such support. By printing service, we mean the APIs related to the use of a printer (to be specific). The PrintJob class of the java.awt was the only way to do print-related jobs prior to Java 1.2. It was a very crude implementation and was never liked by the programmers. Java 1.2 introduced a new mechanism, called Java 2D Printing APIs, with several classes and interfaces defined in the java.awt.print package. The principal class that controls all printing in this mechanism is the PrinterJob. This mechanism is still supported, including the PrintJob implementation of version 1.1, even after the introduction of the new APIs in the javax.print package from Java 1.4. Java printing services gets a real accolade of reliability only from Java 1.3. However, there were still problems with these classes: PrintJob (from Java version1.1) and PrinterJob (from version 1.2).

  • Firstly, both classes uses java.swt.Graphics to render the content of printing. This means that anything that needs to be printed first must be rendered into a graphical image. This is clearly an inefficient technique.
  • Secondly, there is hardly any support for setting attributes related to printing.
  • There is no support to dynamically select the printer.
  • Apart from these, it creates confusion due to the availability of so many printing facilities.

Java 1.4 introduced the Java Print Service API, which may be regarded as the flagship of (printer) printing services in Java. It addressed these issues and resolved the problems with a revamped API. The primary interfaces of these new services are PrintService and DocPrintJob, defined in the javax.print package. In addition to the introduction of new functionalities, the new APIs provide all the functionalities of the old print services as well. Therefore, it is recommended that programmers use new printing APIs instead of old ones unless there is a specific need.

Java Print Services

At the outset of using print services in a Java application, we first need to locate a printer. This can be done by invoking the static method called lookupDefaultPrintSetrvice() defined in the PrintServiceLookup abstract class.

PrintService printService=PrintServiceLookup
   .lookupDefaultPrintService();
System.out.println(printService.getName());

This is the most convenient method to locate a printer. But, the problem is that here we are assuming that the printer will be able to print the output correctly by selecting the platform native default print service rather than the one specific printer installed. It gives no choice to select the printer that supports application-specific needs. Therefore, to find out all the print services available, we may use one of two other alternative static functions defined in the PrintServiceLookup class, such as:

public static final PrintService []
lookupPrintServices(DocFlavor flavor,
   AttributeSet attributes)

public static final PrintService []
lookupMultiDocPrintServices(DocFlavor flavor,
   AttributeSet attributes)

The parameter instance DocFlavor specifies the format of data to be supplied for printing, such as MIME type and the name of the representation class. The AttributeSet specifies the attributes related to printing, such as color, orientation, double-sided printing, and so forth. We can get the names of the printer that supports a specific document flavor in the following manner:

DocFlavor df=DocFlavor.URL.JPEG;
AttributeSet attribute=new HashAttributeSet();
attribute.add(OrientationRequested.LANDSCAPE);
attribute.add(ColorSupported.SUPPORTED);
PrintService[] services=PrintServiceLookup
   .lookupPrintServices(df, attribute);
for (int i=0;i<services.length;i++){
   if(services[i].isDocFlavorSupported(df))
      System.out.println(services[i].getName());
}

We can find out the MIME type, media type, and the media subtype supported by a default printer as follows:

PrintService ps0=PrintServiceLookup.lookupDefaultPrintService();
DocFlavor f[]=ps0.getSupportedDocFlavors();
for(int i=0;i<f.length;i++){
   System.out.println("MIME Type:"+f[i].getMimeType());
   System.out.println("Media Subtype:"+f[i].getMediaSubtype());
   System.out.println("Media Type:"+f[i].getMediaType());
   System.out.println("--------------------------------------");
}

Selecting Print Service via a User Interface

It is a common practice to give the end user an option to select the appropriate print service via a print UI. The ServiceUI class provides a method called printDialog(), which can be invoked to show the print dialog. The user can choose the appropriate print service from there.

PrintService[] printServices = PrintServiceLookup
   .lookupPrintServices(null, null);
PrintService defaultPrintService = PrintServiceLookup
   .lookupDefaultPrintService();
PrintRequestAttributeSet attrib =
   new HashPrintRequestAttributeSet();
PrintService selectedPrintService =
   ServiceUI.printDialog(null, 150, 150,
   printServices, defaultPrintService, null, attrib);
if(selectedPrintService!=null)
   System.out.println("selected printer:"
      +selectedPrintService.getName());
else
   System.out.println("selection cancelled");

Beginning to Print

Once we get the reference to a PrintService instance, we need to create a DocPrintJob instance through the PrintService reference. The DocPrintJob is an interface that is used to control and monitor the status of the printing operation with a set of attributes defined by the PrintRequestAttributeSet object. Suppose we want to print a PDF file in the local machine; we may do it in the following manner:

package org.mano.example;

import java.io.FileInputStream;
import java.io.IOException;

importjavax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.Copies;
import javax.print.event.*;

public class PrintingServiceDemo {
   public static void main(String[] args) throws PrintException,
         IOException{

      PrintService ps=PrintServiceLookup.lookupDefaultPrintService();
      DocPrintJob job=ps.createPrintJob();
      job.addPrintJobListener(new PrintJobAdapter() {
      public void printDataTransferCompleted(PrintJobEvent event){
         System.out.println("data transfer complete");
      }
      public void printJobNoMoreEvents(PrintJobEvent event){
            System.out.println("received no more events");
         }
      });
      FileInputStream fis=new FileInputStream("C:/test.jpg");
      Doc doc=new SimpleDoc(fis, DocFlavor.INPUT_STREAM.AUTOSENSE, null);
      // Doc doc=new SimpleDoc(fis, DocFlavor.INPUT_STREAM.JPEG, null);
      PrintRequestAttributeSet attrib=new HashPrintRequestAttributeSet();
      attrib.add(new Copies(1));
      job.print(doc, attrib);
   }
}

Note one thing in the above code is that we have use a default print service. If the printer is unable to print the flavor of document we want to print, the preceding code may throw an exception. The status of the print operation is monitored by implementing PrinJobListener. Here, we have implemented only two events. Other listeners are like, printJobCanceled(), printJobFailed(), and so on.

Conclusion

Obviously, there are more to Java Print Services API than explained in this article. But, to begin with, this can be a starting point. There are deeper things associated with setting up the printer with various attributes. Refer to the Java API documentation to get finer detail on those aspects. Many of the relevant class explanations are overlooked to keep things simple. Also, one of the most interesting aspects of using the Java Print Service APIs is that we can control the formatting of the print. This is a bit complex to begin with. Maybe we’ll touch on that aspect in a separate article.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories