Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8367666

Printing JTable in Windows L&F throws InternalError: HTHEME is null

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      System: x46-based PC

      OS: Microsoft Windows 11 Pro, Version 10.0.26100 Build 26100
      OS: Microsoft Windows Server 2022

      Java Runtime: OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
      Java Runtime: OpenJDK 64-Bit Server VM Temurin-21.0.8+9 (build 21.0.8+9-LTS, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      Please backport the fix for issue JDK-8322135 to Java 21 LTS.

      Background:
      We are migrating from Windows 10 to Windows 11 on our clients and from Windows Server 2016 to Windows Server 2022 on our servers which provide virtual desktops for our users.

      Currently we are using Java 17 LTS but are in the progress of migrating to Java 21 LTS.

      We use Java Swing applications in our production that routinely use Swing JTable printing.
      For visual consistency they are using the Windows native Look and Feel, i. e. UIManager.getSystemLookAndFeelClassName().
      Unfortunately, on Windows 11 and Windows Server 2022, our users cannot print JTables anymore because they are hitting this bug:

      https://bugs.openjdk.org/browse/JDK-8322135
      Printing JTable in Windows L&F throws InternalError: HTHEME is null
      The bug report states that Java 22 is affected, and it very well may be, but Java 17 LTS and Java 21 LTS are affected as well.

      As a result there currently is no Java LTS release at all where users can print JTables on Windows 11 or Windows Server 2022 when the system-native Look and Feel is used.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Use the JTable.print() functionality in Java 21 on Windows 11 or Windows Server 2022

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The table contents are being printed
      ACTUAL -
      The table contents are not being printed and an exception is thrown:
      Exception in thread "AWT-EventQueue-0" java.lang.InternalError: HTHEME is null
              at java.desktop/sun.awt.windows.ThemeReader.paintBackground(Native Method)
              at java.desktop/sun.awt.windows.ThemeReader.paintBackground(ThemeReader.java:188)
              at java.desktop/com.sun.java.swing.plaf.windows.XPStyle$SkinPainter.paintToImage(XPStyle.java:716)
              at java.desktop/sun.swing.CachedPainter.getImage(CachedPainter.java:175)
              at java.desktop/sun.swing.CachedPainter$PainterMultiResolutionCachedImage.getResolutionVariant(CachedPainter.java:320)
              at java.desktop/sun.java2d.SunGraphics2D.getResolutionVariant(SunGraphics2D.java:3311)
              at java.desktop/sun.java2d.SunGraphics2D.drawHiDPIImage(SunGraphics2D.java:3139)
              at java.desktop/sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3427)
              at java.desktop/sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3411)
              at java.desktop/sun.print.PeekGraphics.drawImage(PeekGraphics.java:960)
              at java.desktop/sun.swing.CachedPainter.paintImage(CachedPainter.java:249)
              at java.desktop/sun.swing.CachedPainter.paint0(CachedPainter.java:217)
              at java.desktop/sun.swing.CachedPainter.paint(CachedPainter.java:114)
              at java.desktop/com.sun.java.swing.plaf.windows.XPStyle$Skin.paintSkinRaw(XPStyle.java:653)
              at java.desktop/com.sun.java.swing.plaf.windows.AnimationController.paintSkin(AnimationController.java:255)
              at java.desktop/com.sun.java.swing.plaf.windows.XPStyle$Skin.paintSkin(XPStyle.java:629)
              at java.desktop/com.sun.java.swing.plaf.windows.WindowsTableHeaderUI$XPDefaultRenderer.paint(WindowsTableHeaderUI.java:221)
              at java.desktop/javax.swing.CellRendererPane.paintComponent(CellRendererPane.java:170)
              at java.desktop/javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderUI.java:744)
              at java.desktop/javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:683)
              at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
              at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:852)
              at java.desktop/javax.swing.JComponent.printComponent(JComponent.java:1292)
              at java.desktop/javax.swing.JComponent.paint(JComponent.java:1132)
              at java.desktop/javax.swing.JComponent.print(JComponent.java:1274)
              at java.desktop/javax.swing.TablePrintable.print(TablePrintable.java:374)
              at java.desktop/javax.swing.JTable$ThreadSafePrintable$1.run(JTable.java:6651)
              at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
              at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
              at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
              at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
              at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
              at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
              at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:742)
              at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
              at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
              at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:117)
              at java.desktop/java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:191)
              at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:236)
              at java.desktop/java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:234)
              at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
              at java.desktop/java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:234)
              at java.desktop/java.awt.Dialog.show(Dialog.java:1079)
              at java.desktop/java.awt.Component.show(Component.java:1728)
              at java.desktop/java.awt.Component.setVisible(Component.java:1675)
              at java.desktop/java.awt.Window.setVisible(Window.java:1036)
              at java.desktop/java.awt.Dialog.setVisible(Dialog.java:1015)
              at java.desktop/sun.swing.PrintingStatus.showModalOnEDT(PrintingStatus.java:204)
              at java.desktop/sun.swing.PrintingStatus.showModal(PrintingStatus.java:172)
              at java.desktop/javax.swing.JTable.print(JTable.java:6460)
              at testcase.SwingPrintHthemeIsNull.printTable(SwingPrintHthemeIsNull.java:142)
              at testcase.SwingPrintHthemeIsNull$1.actionPerformed(SwingPrintHthemeIsNull.java:127)
              at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
              at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2314)
              at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:407)
              at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
              at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
              at java.desktop/java.awt.Component.processMouseEvent(Component.java:6621)
              at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
              at java.desktop/java.awt.Component.processEvent(Component.java:6386)
              at java.desktop/java.awt.Container.processEvent(Container.java:2266)
              at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4996)
              at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
              at java.desktop/java.awt.Component.dispatchEvent(Component.java:4828)
              at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
              at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
              at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
              at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
              at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
              at java.desktop/java.awt.Component.dispatchEvent(Component.java:4828)
              at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
              at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
              at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
              at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
              at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
              at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:98)
              at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
              at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
              at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
              at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
              at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
              at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
              at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
              at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
              at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
              at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
              at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

      ---------- BEGIN SOURCE ----------
      package testcase;

      import java.awt.BorderLayout;
      import java.awt.EventQueue;
      import java.awt.GridBagConstraints;
      import java.awt.GridBagLayout;
      import java.awt.HeadlessException;
      import java.awt.Insets;
      import java.awt.Point;
      import java.awt.event.ActionEvent;
      import java.awt.event.KeyEvent;
      import java.awt.print.PrinterException;
      import java.awt.print.PrinterJob;
      import java.text.MessageFormat;
      import java.util.Locale;

      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.JobName;
      import javax.print.attribute.standard.MediaSizeName;
      import javax.print.attribute.standard.OrientationRequested;
      import javax.swing.AbstractAction;
      import javax.swing.Action;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JPanel;
      import javax.swing.JScrollPane;
      import javax.swing.JTable;
      import javax.swing.JTable.PrintMode;
      import javax.swing.SwingConstants;
      import javax.swing.UIManager;
      import javax.swing.UnsupportedLookAndFeelException;
      import javax.swing.table.DefaultTableModel;

      /**
       * <p>
       * Self-contained reproducible example that triggers a Swing {@link JTable} printing bug in Eclipse Temurin on Windows 11:
       * </p>
       * <p>
       * Exception in thread "AWT-EventQueue-0" java.lang.InternalError: HTHEME is null
       * </p>
       * <p>
       * Known affected Windows version: Microsoft Windows 11 Pro, Version 10.0.26100 Build 26100, x64-based PC
       * </p>
       * <p>
       * Known affected JVMs:
       * </p>
       * <ul>
       * <li>OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)</li>
       * <li>OpenJDK 64-Bit Server VM Temurin-21.0.7+6 (build 21.0.7+6-LTS, mixed mode, sharing)</li>
       * <li>OpenJDK 64-Bit Server VM Temurin-21.0.8+9 (build 21.0.8+9-LTS, mixed mode, sharing)</li>
       * </ul>
       * <p>
       * Known <b>not</b> affected JVMs:
       * </p>
       * <ul>
       * <li>OpenJDK 64-Bit Server VM Temurin-24.0.2+12 (build 24.0.2+12, mixed mode, sharing)</li>
       * </ul>
       */
      public class SwingPrintHthemeIsNull implements Runnable {

      private static final String TITLE = "Swing JTable Printing Test";

      private JFrame frame;
      private JTable table;

      public static void main( String[] args ) {
      EventQueue.invokeLater( () -> new SwingPrintHthemeIsNull().run() );
      }

      @Override
      public void run() {

      setSystemLookAndFeel();

      getFrame().pack();
      getFrame().setLocation( new Point( 100, 80 ) );
      getFrame().setVisible( true );
      }

      // Lazy initializers

      private JFrame getFrame() {

      if (frame == null) {
      JScrollPane scpTable = new JScrollPane( getTable(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED );
      JPanel pnlControls = createPnlControls();
      frame = new JFrame( TITLE );

      frame.getContentPane().setLayout( new BorderLayout( 2, 2 ) );
      frame.getContentPane().add( scpTable, BorderLayout.CENTER );
      frame.getContentPane().add( pnlControls, BorderLayout.SOUTH );
      frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
      }
      return frame;
      }

      private JTable getTable() {

      if (table == null) {
      DefaultTableModel tableModel = new DefaultTableModel( new String[] { "Alpha", "Bravo", "Charlie" }, 0 );
      table = new JTable( tableModel );

      tableModel.addRow( new String[] { "One-A", "One-B", "One-C" } );
      tableModel.addRow( new String[] { "Two-A", "Two-B", "Two-C" } );
      tableModel.addRow( new String[] { "Three-A", "Three-B", "Three-C" } );
      }
      return table;
      }

      // Other instance methods

      private JPanel createPnlControls() {
      JLabel lblInfo = new JLabel( getSystemInfo() );
      JButton btnPrint = new JButton( createActPrint() );
      JPanel result = new JPanel( new GridBagLayout() );
      int gridx = 0;

      lblInfo.setHorizontalAlignment( SwingConstants.CENTER );
      result.add( lblInfo, createConstraints( gridx++, 0, 1d, 1d, GridBagConstraints.HORIZONTAL ) );
      result.add( btnPrint, createConstraints( gridx++, 0, 0d, 1d, GridBagConstraints.NONE ) );
      return result;
      }

      private Action createActPrint() {
      Action result = new AbstractAction( "Print Table" ) {
      @Override
      public void actionPerformed( ActionEvent event ) {
      printTable();
      }
      };

      result.putValue( Action.MNEMONIC_KEY, KeyEvent.VK_P );
      return result;
      }

      private void printTable() {
      PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
      PrinterJob printerJob = PrinterJob.getPrinterJob();

      attributeSet.add( new JobName( TITLE, Locale.ENGLISH ) );
      attributeSet.add( MediaSizeName.ISO_A4 );
      attributeSet.add( OrientationRequested.PORTRAIT );
      attributeSet.add( new Copies( 1 ) );

      try {
      if (printerJob.printDialog( attributeSet )) {
      PrintService printService = printerJob.getPrintService();
      getTable().print( PrintMode.FIT_WIDTH, (MessageFormat) null, (MessageFormat) null, false, attributeSet, true, printService );
      }
      } catch (HeadlessException | PrinterException e) {
      throw new RuntimeException( e );
      }
      }

      // Utility methods

      private static void setSystemLookAndFeel() {

      try {
      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
      } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
      throw new RuntimeException( e );
      }
      }

      private static String getSystemInfo() {
      StringBuilder result = new StringBuilder();

      result.append( System.getProperty( "java.vm.vendor" ) ).append( " " ).append( System.getProperty( "java.runtime.version" ) ).append( " " )
      .append( System.getProperty( "os.arch" ) );
      return result.toString();
      }

      private static GridBagConstraints createConstraints( int gridx, int gridy, double weightx, double weighty, int fill ) {
      GridBagConstraints result = new GridBagConstraints();

      result.gridx = gridx;
      result.gridy = gridy;
      result.weightx = weightx;
      result.weighty = weighty;
      result.fill = fill;
      result.insets = new Insets( 2, 2, 2, 2 );
      return result;
      }
      }

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

            pnarayanaswa Praveen Narayanaswamy
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: