Custom Component Renderers and Updaters
AjaxSwing renderers and updaters can be used to support custom components and to override HTML generation for standard components (java.awt.* and javax.swing.*). Only one custom renderer per application is allowed in the Standard Edition, and if you need more renderers you need to purchase an appropriate commercial license. AjaxSwing maintains a map of components and their renderers. When iterating children of a container generate HTML page AjaxSwing first determines the name of the class of each child component. Then it tries to lookup the renderer for this component in the map of renderers. If a renderer is found, it is instantiated and used, otherwise the superclass of the component is checked for a registered renderer. AjaxSwing has an universal SnapshotRenderer that can render any component as an image on a page.
Supporting custom GUI components requires creating a Freemarker template or coding and registering a renderer class Creating a template is easier and more straightforward, so it is a good choice for components that map cleanly to HTML code. Developing a renderer class is a better choice in cases where a lot of logic needs to be evaluated or calculated to produce HTML. Renderer class is also faster and more maintainable because it doesn't rely on reflection like the Freemarker template. Finally, both approaches can be combined by extending com.creamtec.ajaxswing.v4.render.TemplateRenderer and preparing extra component-specific data for the template.
Custom component rendering using a template (similar to JSP)Another alternative to supporting custom component rendering is to create a rendering template. This approach doesn't require developing Java classes and is similar to writing a JSP page. AjaxSwing uses Freemarker templating engine for processing templates. The templates must be placed into AjaxSwing/conf/templates/custom-components directory and the name of the template must follow
Templates syntax must follow Freemarker rules. The following data objects are available to the template:
- page - currently rendered HTMLPage
- agent - ClientAgent
- component - component to be rendered
- id - id/name of the component to be rendered
- style - component style attributes derived from Swing component
Custom component renderering using a renderer class (similar to a servlet)
Writing renderer is similar to writing a servlet that only produces a portion of a page. All renderers must implement com.creamtec.ajaxswing.v4.render.ComponentRenderer interface. If you look at ComponentRenderer interface, you would see that it is very simple and defines two methods
This method is by AjaxSwing to initialize renderer. This method is only called once per page creation.
void renderComponent(ComponentGraphics graphics, Component component) throws Exception
This method is called to append the HTML representation of the component to the page. This code can be as simple as <IMG> tag or as complex as <IFRAME></IFRAME> section.
graphics is the output that will be returned to the client.
Component is the instance of the component to be
rendered. See API JavaDoc and
on specifics of what methods to use and required parameters.
Registering the custom renderer with AjaxSwing
Once a custom renderer class has been developed, it has to be registered with AjaxSwing. This is done by adding an entry to the application's properties file in the conf directory. The entry follows format <renderer>.<package_name>.<class_name>= <renderer_class_name>. For example, to use our example renderer com.creamtec.ajaxswing.examples.CustomControlProcessor for component com.creamtec.ajaxswing.ui.CustomControl in your application MyFirstApp you will add the following line to <AjaxSwing>/conf/MyFirstApp.properties
Similarly, if you want to use your CustomControlProcessor to render Swing's JSlider you can use
As you have learned, custom renderers allow you to extend AjaxSwing by providing logic to render unsupported controls to HTML page. But what if the control is an input field such as a text field or a radio button? Generating HTML for it will allow the user to see it on the page, but if the user changes the value of the field how would it get propagated back to the UI element such as JTextField? The solution for this is to add a custom ComponentUpdater. Component updaters are used by AjaxSwing engine to set values received from the browser to the UI elements. It can be as simple as calling a setText() on a JTextField and as complicated as synchronizing the JTable model to match the new values received from the HTML table. Just like custom renderers, updaters need to be registered for the controls that they support. For example, the line below tells AjaxSwing to use CustomControlProcessor to update CustomControl
Custom updaters must implement ComponentUpdater interface and provide implementation for updateComponent method. The implementation is specific to the control and the rendering that was used to represent it on HTML page. See Javadoc for more information.
Implementation Example for a Custom ControlCustomControlProcessor.java