Development guidelines and considerations

Swingweb provides the default web-implementation of most of the commonly use components in java.awt.* and java.swing.* package. (for supported components check Appendix A). If the application being developed mainly uses these components, it should just work when deployed in swingweb environment. If the application uses a custom component (e.g third party component) that is not supported by swingweb by default, the developer need to develop the template and event-input delegate for it. The details can be found in section 2.3.



Except for developing custom component, there are no specific instructions or steps that need to be followed in swingweb application development. Nevertheless, there are a lot of swingweb specific tips and tweaks that the developers should be aware of in the swingweb application development:



  1. Application start-up and the alternative main method

    In the web container, SwingWebServlet is responsible for creating the application instance for a user that access the application url. The servlet will start the class using the following rule:
    1. If the appClass has a method with signature of "public static <anytype> swMain(String[] args)", it will use this method to bootstrap the application, otherwise,
    2. If the appClass has a method with signature of static main(), it will use this method to bootstrap the application, otherwise
    3. If the appClass is an applet, it will try to create the applet by giving it an empty applet context
    4. If the appClass is a window, it will try to create the window and run it
    The swMain() method is something that developer can use to differentiate on how the application starts than it's desktop counterpart.

  2. Closing application session explicitly

    SwingWeb does not use httpsession directly because it tries to abstract the session concepts to avoid dependence on servlet environment. SwingWebServlet will create a SwingWebSession for every HttpSession. The developer should close the SwingWebSession immediately when the session is not needed to free up the resources. The simplest way to achieve that is illustrated by the following code:

    public static void main(String[] args)
    {
        MyApp app  = new MyApp();
        app.addWindowListener(new WindowAdapter()
        {
    
            public void windowClosed(WindowEvent e)
            {
            	super.windowClosed(e);
                SwingWebUtils.getSwingWebContext().getSession().close();
            }
        });
        app.pack();
        app.show();
    }
                

  3. Custom template

    Each component in swingweb app relies on a template to render the component as html. To use a custom template on a component, simply use
    SwingWebUtils.setComponentProperty(myButton, TemplateEngine.KEY_COMPONENT_TEMPLATE, "/mypackage/MyButton.jxp");
    to make Swingweb to use your own template to render the component.

  4. Layout

    For container component, Swingweb uses a layout calculator to calculate the corresponding html table-based representation of the child components and the template uses this information to render the container as a table. If you need to tweak the layout somehow, just use the custom template trick above and write your own layout template. Below is a sample of the template that do custom layout for the component

    <%
    	var components = com.getComponents();	
    %>
    <table align="center">
      <tr>
        <td>
          <%	rendercontext.renderOutput(components[0], writer);  %>
        </td>
      </tr>
      <tr>
        <td>
          <%	rendercontext.renderOutput(components[1], writer);  %>
        </td>
      </tr>
    </table>                  
                      
                    


  5. Detect swingweb mode

    At any code point, you can use SwingWebUtils.isInSwingWebMode()to check if the app is running in SwingWeb mode or normal mode. This allows you to code the application to have slightly different behavior depending on whether it's in swingweb mode or desktop app mode.

  6. Render/Input lifecycle event

    Sometime it is useful to detect when the render/input events occur (e.g. a JLabel that shows error message that will clear up the next time the UI/html is rendered again). This can be done by attaching a BridgeEventListener to the Swingweb container
    SwingWebUtils.getSwingWebContext().addEventListener(new BridgeContextEventListener 
      {
          public void handleBridgeContextEvent(BridgeContextEvent evt)
          {
            //detect the type of event
            if (evt.getEventType() == BridgeContextEvent.RENDER_END)
            {
                console.setText("");
            }
          }
      }    
    });
                    


  7. Modal dialog and ThreadlessEventQueue

    In swing application, all the component events are driven by another thread (EventDispatchThread) started by java.awt.EventQueue. Clearly this is a problematic for web-container as we need to instantiate many EventQueues hence many threads for the swingweb application sessions. To overcome this issue, SwingWeb utilizes a ThreadlessEventQueue, which will not create a new thread for event dispatch. It allows swingweb application to be executed in a monolithic way - from render to event-input to event-dispatch - all in the servlet thread. The only side-effect, however , is that the modal dialog will not work correctly- as swing implementation depending on existence of separate event dispatch thread to function correctly.