struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Obinna <obi...@gmail.com>
Subject Re: Pluggable themes for JavaTemplates plugin
Date Wed, 04 Feb 2009 15:30:57 GMT
Hi James, Thanks for getting back so quickly.

I see two major areas of extensibility required:
1) Allow plugging in of custom themes
2) Allow for easy extensibility/re-use of existing themes (currently
SimpleTheme or DefaultTheme)

1) We need a way of specifying custom themes to the JavaTemplateEngine via
configuration. For now, the best I can come up with is a new struts
configuration constant that takes a comma-delimited list of theme names
   as its value.

    So lets add something like the following constant to StrutsConstants:

            /** Custom theme classes for the javatemplates rendering engine
*/
            public static final String STRUTS_JAVATEMPLATES_CUSTOM_THEMES =
"struts.javatemplates.customThemes";

    We can then specify in our struts.xml

            <constant name="struts.javatemplates.customThemes"
value="com.example.ui.struts2.MyCustomJavaTheme" />

    and add to the JavaTemplateEngine class

            /**
             * Allows for providing custom theme classes (implementations of
the org.apache.struts2.views.java.Theme) interface
             * for custom rendering of tags using the javatemplates engine
             * @param themeClasses a comma delimited list of custom theme
class names
             */
            @Inject(StrutsConstants.STRUTS_JAVATEMPLATES_CUSTOM_THEMES)
            public void setThemeClasses(String themeClasses) {

                StringTokenizer customThemes = new
StringTokenizer(themeClasses, ",");

                while (customThemes.hasMoreTokens()) {
                    String themeClass = customThemes.nextToken().trim();
                    try {
                        LOG.info("Registering custom theme '" + themeClass +
"' to javatemplates engine");


                        //FIXME: This means Themes must have no-arg
constructor - should use object factory here

//ObjectFactory.getObjectFactory().buildBean(ClassLoaderUtil.loadClass(themeClass,
getClass()), null);

themes.add((Theme)ClassLoaderUtil.loadClass(themeClass,
getClass()).newInstance());

                    } catch (ClassCastException cce) {
                        LOG.error("Invalid java them class '" + themeClass +
"'. Class does not implement 'org.apache.struts2.views.java.Theme'
interface");
                    } catch (ClassNotFoundException cnf) {
                        LOG.error("Invalid java theme class '" + themeClass
+ "'. Class not found");
                    } catch (Exception e) {
                        LOG.error("Could not find messages file " +
themeClass + ".properties. Skipping");
                    }
                }
            }


    For the custom theme implemetations, most will probably extend
SimpleTheme/DefaultTheme and simply insert/remove component handlers in
their desired sequence and perhaps provide
    a different (or additional) serializer.
    so it would be nice to:

        - lower the  protection level on some of the methods/members to
protected

            (eg. make DefaultTheme.handlerFactories protected, make
FactoryList inner-class protected or a separate public class)

        - provide some utility methods. For example:

                Add to DefaultTheme class:

                     /**
                     * Set (replace if exists) the tag handler factories for
specific tag
                     * @param tagName
                     * @param handlers
                     */
                    protected void setTagHandlerFactories(String tagName,
List<TagHandlerFactory> handlers) {
                        if(tagName != null && handlers != null &&
this.handlerFactories != null) {

                            handlerFactories.put(tagName,handlers);
                        }
                    }

                    /**
                     * Insert a new tag handler into a sequence of tag
handlers for a specific tag
                     * TODO: Need to take care of serializers, if handler
specified is not a TagSerializer it should never
                     * be placed after the serializer, but if it is not a
TagSerializer, it should never
                     * @param tagName
                     * @param sequence
                     * @param factory
                     */
                    protected void insertTagHandlerFactory(String tagName,
int sequence, TagHandlerFactory factory) {

                        if(tagName != null && factory != null  &&
this.handlerFactories != null) {

                            List<TagHandlerFactory> tagHandlerFactories =
handlerFactories.get(tagName);

                            if(tagHandlerFactories == null) {
                                    tagHandlerFactories = new
ArrayList<TagHandlerFactory>(); //TODO: Could use public FactoryList here
                            }

                            if(sequence > tagHandlerFactories.size()) {
                                sequence = tagHandlerFactories.size();
                            }

                            //TODO, need to account for TagHandlers vs.
TagSerializers here
                            tagHandlerFactories.add(sequence, factory);
                        }
                }

        - Allow multiple TagSerializers (make sure framework supports
chaining serizliers). For example, in my application I'd like to add a
serializer which writes some javascript (think Ajax event binding)
            after

        - The way the serializers are registered simply as the last handler
is neat, but it may cause some trouble when developers extend the themes and
iject their own handlers, perhaps
            I like the chaining, so perhaps this should simply be accounted
for carefully in the utiolity methods (such as the insertTagHandlerFactory()
method i suggested above) and in the
            renderTag() method of the DefaultTheme.

        - DefaultTheme could probably be an abstract class and maybe called
somehting like AbstractTheme or AbstractThemeSupport


Incidentally, the reason I am looking into this is because I am starting to
write a jQuery Ajax plugin (given the imminent deprecation of dojo, which I
never really liked so much anyway - too large and clunky)
I'm not sure how far I'll get on this, but I'm currently optimistic.

Best,
Eric

On Wed, Feb 4, 2009 at 4:26 PM, James Holmes <james@jamesholmes.com> wrote:

> I don't know if any plugging mechanism for themes has been discussed.
> Please
> send us your thoughts.
>
> On Wed, Feb 4, 2009 at 2:24 AM, Obinna <obinna@gmail.com> wrote:
>
> > Hi,
> >
> > I'd like to know if there's a 'recommended' way of extending the
> > javatemplates theme.
> > I've been using the default freemarker templates and have developed a few
> > custom tag templates for some custom tags. I'm eager to port to
> > javatemplates.
> >
> > I noticed that the SimpleTheme is 'hard-coded' in the JavaTemplateEngine
> > like:
> >
> >  private Themes themes = new Themes() {{
> >        add(new SimpleTheme());
> >    }};
> >
> > which doesn't really allow for registering new themes. I can suggest a
> > theme
> > plugin/registry but wondered if it's already been considered. There
> should
> > also be a pluggable way of  adding Handlers to a theme.
> >
> >
> > - Eric
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message