title: Unable to apply composition over inheritance in Java Swing
body: <p>I'm trying to adopt composition over inheritance when I create Swing components (which means I created a class that does not extend anything, specially not a Swing component such as <code>JPanel</code>) but I'm stumpling upon an issue with the Window Builder plugin for Eclipse when I try to switch to the design view of my code.</p>
  <p>It throws the following exception:</p>
  <blockquote>
  <p><strong>No root methods</strong></p>
  <p>The parser can't find any root method(s) (entry points for parsing). The parser starts parsing from known method(s) for each GUI toolkit. For example, for Swing it starts from the constructor of a JPanel or JFrame. If the currently parsed class is not a subclass of a Swing component, the parser will try to find a main(java.lang.String[]) method. If it also does not exist, this exception will be shown. Usually this means that you are trying to parse something not supported by WindowBuilder (for example, a non-GUI compilation unit).</p>
  <p>Note that even if WindowBuilder can't recognize your code pattern automatically, sometimes you can still teach WindowBuilder to work with it by providing a @wbp.parser.entryPoint JavaDoc hint. For example:</p>
  </blockquote>
  <pre><code>public class MyClass {
      /**
       * @wbp.parser.entryPoint
       */
      public void someNonStandardEntryPoint() {
          JFrame frame = new JFrame();
          ...;
      }
  }
  </code></pre>
  <p>It then suggests methods to which I can apply the above JavaDoc, but when I do that none of them results in a visible design. I haven't created a <code>main()</code> method because it doesn't make any sense in this context.</p>
  <p>The non-subclassed class and the supporting <code>JDialog</code> class follow. I can see the design if the first class subclasses <code>JPanel</code>, but I'm trying to avoid that.</p>
  <p><strong>CustomerAddressesSection.java</strong></p>
  <pre><code>package myapp.gui;
  
  import java.awt.Color;
  import java.awt.FlowLayout;
  import java.util.List;
  import java.util.Objects;
  
  import javax.swing.BoxLayout;
  import javax.swing.DefaultListModel;
  import javax.swing.JLabel;
  import javax.swing.JList;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.border.CompoundBorder;
  import javax.swing.border.EmptyBorder;
  import javax.swing.border.LineBorder;
  
  import myapp.models.CustomerAddress;
  
  public class CustomerAddressesSection {
      private JPanel jPanelCustomerAddresses;
  
      private JPanel panelAbaixoDeCustomerAddresses;
      private JPanel panelTituloEnderecos;
      private JPanel panelContendoOsEnderecos;
      private JLabel lblEnderecos;
  
      private JScrollPane scrollPaneCustomerAddresses;
      private JList&lt;CustomerAddress&gt; jListCustomerAddresses;
  
      private final List&lt;CustomerAddress&gt; customerAddresses;
  
      public CustomerAddressesSection(List&lt;CustomerAddress&gt; customerAddresses) {
          this.customerAddresses = Objects.requireNonNull(customerAddresses);
      }
      
      public List&lt;CustomerAddress&gt; getCustomerAddresses() {
          return customerAddresses;
      }
      
      public void layoutCustomerAddressesSection(JPanel panel) {
          jPanelCustomerAddresses = new JPanel();
          
          jPanelCustomerAddresses.setBackground(new Color(255, 255, 255));
          jPanelCustomerAddresses.setBorder(new CompoundBorder(new LineBorder(new Color(0, 0, 0), 1, true), new EmptyBorder(10, 10, 10, 10)));
          jPanelCustomerAddresses.setLayout(new BoxLayout(jPanelCustomerAddresses, BoxLayout.Y_AXIS));
          
          panelAbaixoDeCustomerAddresses = new JPanel();
          panelAbaixoDeCustomerAddresses.setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
          jPanelCustomerAddresses.add(panelAbaixoDeCustomerAddresses);
          panelAbaixoDeCustomerAddresses.setLayout(new BoxLayout(panelAbaixoDeCustomerAddresses, BoxLayout.Y_AXIS));
          
          panelTituloEnderecos = new JPanel();
          panelTituloEnderecos.setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
          FlowLayout fl_panelTituloEnderecos = (FlowLayout) panelTituloEnderecos.getLayout();
          fl_panelTituloEnderecos.setAlignment(FlowLayout.LEFT);
          panelTituloEnderecos.setBackground(Color.LIGHT_GRAY);
          panelAbaixoDeCustomerAddresses.add(panelTituloEnderecos);
          
          lblEnderecos = new JLabel(&quot;Endereço&quot;);
          panelTituloEnderecos.add(lblEnderecos);
          
          panelContendoOsEnderecos = new JPanel();
          panelContendoOsEnderecos.setBorder(new EmptyBorder(0, 0, 0, 0));
          panelContendoOsEnderecos.setBackground(Color.WHITE);
          panelAbaixoDeCustomerAddresses.add(panelContendoOsEnderecos);
          panelContendoOsEnderecos.setLayout(new BoxLayout(panelContendoOsEnderecos, BoxLayout.Y_AXIS));
          
          panel.add(jPanelCustomerAddresses);
      }
      
      public void addCustomerAddresses() {
          
          DefaultListModel&lt;CustomerAddress&gt; listModel = new DefaultListModel&lt;&gt;();
          for (CustomerAddress customerAddress : customerAddresses) {
              listModel.addElement(customerAddress);
          }
  
          jListCustomerAddresses = new JList&lt;&gt;(listModel);
          scrollPaneCustomerAddresses = new JScrollPane(jListCustomerAddresses);
          panelContendoOsEnderecos.add(scrollPaneCustomerAddresses);
          
          jListCustomerAddresses.setCellRenderer(new PanelIndividualCustomerAddress());
          jListCustomerAddresses.setVisibleRowCount(1);
          //panelContendoOsEnderecos.add(jListCustomerAddresses);
      }
  
      public static void main(String [] args) {
          SwingUtilities.invokeLater(new Runnable() {
              @Override
              public void run() {
                  MainGUI mainGui = new MainGUI(Collections.emptyList(), null, true);
                  CustomerInfo customerInfo = new CustomerInfo(&quot;Nome&quot;, &quot;Email&quot;, LocalDate.now(), &quot;ddd&quot;, &quot;phone&quot;, &quot;observação&quot;);
                  List&lt;CustomerAddress&gt; customerAddresses = new ArrayList&lt;CustomerAddress&gt;();
                  JDViewCustomer jDViewCustomer = new JDViewCustomer(mainGui, true, mainGui, customerInfo, customerAddresses, Collections.emptyList(), null, 1, 3);
                  jDViewCustomer.setVisible(true);
              }
          });
      }
  }
  </code></pre>
  <p><strong>JDViewCustomer.java</strong></p>
  <pre><code>package myapp.gui;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Objects;
  
  import javax.swing.BoxLayout;
  import javax.swing.JPanel;
  
  import myapp.HttpClient;
  import myapp.LoadCustomerOrdersAndGenerateReportWorker;
  import myapp.models.CustomerAddress;
  import myapp.models.CustomerInfo;
  import myapp.models.CustomerOrder;
  import net.sf.jasperreports.engine.JRException;
  
  public class JDViewCustomer extends javax.swing.JDialog {
  
      private static final long serialVersionUID = 1L;
      
      public static final int CUSTOMER_ORDERS_LIMIT = 10;
      public static final String CUSTOMER_ORDERS_SORT_BY = &quot;created_at&quot;;
      public static final String CUSTOMER_ORDERS_SORT_ORDER = &quot;desc&quot;;
      
      private final CustomerInfoSection customerInfoSection;
      private final CustomerAddressesSection customerAddressesSection;
      private final CustomerOrdersSection customerOrdersSection;
  
      private JPanel panelContainingTheOtherPanels;
      
      private final MainGUI mainGui;
      private final HttpClient httpClient;
      private final int customerId;
  
      public JDViewCustomer(java.awt.Frame parent, boolean modal, MainGUI mainGui, CustomerInfo customerInfo,
              List&lt;CustomerAddress&gt; customerAddresses, List&lt;CustomerOrder&gt; customerOrders, HttpClient httpClient,
              int customerId, int maxPage) {
          super(parent, modal);
          this.mainGui = Objects.requireNonNull(mainGui);
          this.customerInfoSection = new CustomerInfoSection(Objects.requireNonNull(customerInfo), this);
          this.customerAddressesSection = new CustomerAddressesSection(Objects.requireNonNull(customerAddresses));
          this.customerOrdersSection = new CustomerOrdersSection(
                  (List&lt;CustomerOrder&gt;)(new ArrayList&lt;CustomerOrder&gt;(Objects.requireNonNull(customerOrders))),
                  mainGui, httpClient, customerId, this, maxPage);
          this.httpClient = httpClient;
          this.customerId = customerId;
          
          getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
  
          panelContainingTheOtherPanels = new JPanel();
          panelContainingTheOtherPanels.setLayout(new BoxLayout(panelContainingTheOtherPanels, BoxLayout.Y_AXIS));
          getContentPane().add(panelContainingTheOtherPanels);
  
          customerInfoSection.layoutCustomerDataSection(panelContainingTheOtherPanels);
          customerInfoSection.addCustomerInfo();
          
          customerAddressesSection.layoutCustomerAddressesSection(panelContainingTheOtherPanels);
          customerAddressesSection.addCustomerAddresses();
  
          customerOrdersSection.layoutCustomerOrdersSection(panelContainingTheOtherPanels);
          customerOrdersSection.createCustomerOrdersTable();
          customerOrdersSection.updateCurrentPageTextField();
          
          initComponents();
      }
  
      public void loadCustomerOrdersAndGenerateReport() throws JRException {
          if (false == customerInfoSection.isLoadingIconShowing()) {
              customerInfoSection.setLoadingIconVisibility(true);
              
              LoadCustomerOrdersAndGenerateReportWorker worker =
                      new LoadCustomerOrdersAndGenerateReportWorker(httpClient,
                              customerInfoSection.getCustomerInfo(),
                              customerAddressesSection.getCustomerAddresses(),
                              customerId, this);
              mainGui.scheduleOnSingleThread(worker);
          }
      }
      
      public void updateCustomerOrdersAndPagingInformation(List&lt;CustomerOrder&gt; customerOrders, int total, int page) {
          customerOrdersSection.updateCustomerOrdersAndPagingInformation(customerOrders, total, page);
      }
      
      private void initComponents() {
  
          setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
          setTitle(&quot;Ver Cliente&quot;);
          
          setMinimumSize(MainGUI.MINIMAL_DISPLAY_DIMENSION);
  
          pack();
          
          // Para centralizar o JDialog em relação a seu parent.
          setLocationRelativeTo(getParent());
          
      }
  
      public void setLoadingIconVisibility(boolean showing) {
          customerInfoSection.setLoadingIconVisibility(showing);
          
      }
  }
  </code></pre>