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:
- 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:
- 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,
- If the appClass has a method with signature of static main(), it will use this method to bootstrap the application, otherwise
- If the appClass is an applet, it will try to create the applet by giving it an empty applet context
- 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.
- 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();
}
- 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.
- 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>
- 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.
-
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("");
}
}
}
});
-
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.