title: Is there a good way to persist printer settings in a Swing app?
body: <p>We are using the new Java printing API which uses <code>PrinterJob.printDialog(attributes)</code> to display the dialog to the user.</p>
  
  <p>Wanting to save the user's settings for the next time, I wanted to do this:</p>
  
  <pre><code>PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
  if (printJob.printDialog(attributes)) {
      // print, and then...
  
      saveAttributesToPreferences(attributes);
  }
  </code></pre>
  
  <p>However, what I found by doing this is that sometimes (I haven't figured out how, yet) the attributes get some bad data inside, and then when you print, you get a white page of nothing.  Then the code saves the poisoned settings into the preferences, and all subsequent print runs get poisoned settings too.  Additionally, the entire point of the exercise, making the settings for the new run the same as the user chose for the previous run, is defeated, because the new dialog does not appear to use the old settings.</p>
  
  <p>So I would like to know if there is a proper way to do this.  Surely Sun didn't intend that users have to select the printer, page size, orientation and margin settings every time the application starts up.</p>
  
  <p><strong>Edit</strong> to show the implementation of the storage methods:</p>
  
  <pre><code>private PrintRequestAttributeSet loadAttributesFromPreferences()
  {
      PrintRequestAttributeSet attributes = null;
  
      byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
      if (marshaledAttributes != null)
      {
          try
          {
              @SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
              ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));
  
              attributes = (PrintRequestAttributeSet) objectInput.readObject();
          }
          catch (IOException e)
          {
              // Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
              Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
          }
          catch (ClassNotFoundException e)
          {
              Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
          }
      }
  
      if (attributes == null)
      {
          attributes = new HashPrintRequestAttributeSet();
      }
  
      return attributes;
  }
  
  private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
  {
      ByteArrayOutputStream storage = new ByteArrayOutputStream();
      try
      {
          ObjectOutput objectOutput = new ObjectOutputStream(storage);
          try
          {
              objectOutput.writeObject(attributes);
          }
          finally
          {
              objectOutput.close(); // side-effect of flushing the underlying stream
          }
      }
      catch (IOException e)
      {
          throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
      }
  
      preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
  }
  </code></pre>
  
  <p><strong>Edit:</strong> Okay, it seems like the reason it isn't remembering the printer is that it isn't in the PrintRequestAttributeSet at all.  Indeed, the margins and page sizes are remembered, at least until the settings get poisoned at random.  But the printer chosen by the user is not here:</p>
  
  <pre><code>[0] = {java.util.HashMap$Entry@9494} class javax.print.attribute.standard.Media -&gt; na-letter
  [1] = {java.util.HashMap$Entry@9501} class javax.print.attribute.standard.Copies -&gt; 1
  [2] = {java.util.HashMap$Entry@9510} class javax.print.attribute.standard.MediaPrintableArea -&gt; (10.0,10.0)-&gt;(195.9,259.4)mm
  [3] = {java.util.HashMap$Entry@9519} class javax.print.attribute.standard.OrientationRequested -&gt; portrait
  </code></pre>