Thursday, February 16, 2012

ICEfaces Advanced Component Environment

Purpose

The ICEfaces Advanced Component Environment was conceived as a new platform for creating JSF 2+ components, that would solve many of the development inefficiencies and inconsistencies in the previous platform. Many lessons were learned in ICEfaces 1.x components, as they migrated from being JSF 1.1 to JSF 1.1 + 1.2 components. Best practices were found, after many different approaches had been taken by different developers over time.

Some key differences planned for the new components were:

1. Instead of being thin on the client with all processing being done server side, as ICEfaces 1.x components are, the new components would use javascript to do as much processing as possible on the client, and only interact with the server as necessary. There will always be arguments for each approach, as each has its place, so being able to provide both, rounds out our capabilities.

2. Components would rely on many different resources: third party javascript we're wrapping, our integration javascript, structural css, theme css, images and sprite images.

Already we were headed in a direction where the components would have most of their logic in the javascript, and the java should be quite minimalist, with some component specific code, but most everything else could be logically reduced to some declarations that would favour code generation.

There is a lot of wiring code and markup in JSF components, with JSP Tag files, Facelets TagHandlers, the faces-config.xml, taglib.xml. Our previous platform was truly a pain to maintain, and was based on xml files which provided no real type safety, error checking or reporting. We wanted something that would solve all those problems, while also generating all the boilerplate component code, such as property getter/setter methods and state saving code.

JSF standard getter/setter methods aren't really good at all. They don't allow for the component property having a different value for each row of the UIData or UIRepeat that they're in. As well, they can't be used with a combination of the property being tied to a ValueExpression as well as the setter method being called directly. This can happen when the Renderer's decode method needs to set state in the component, or when applications use a component binding or get access to the component via FacesEvents' source. Some properties have an inherently read/write aspect to them, and some have an inherently read only aspect. It seemed best to standardise exactly how that would be implemented. Past disparate implementations exhibited different side effects and bugs.


Debate

There was a large debate between three main approaches to specifying each component:

1. Continue using xml files, but expand what they would state about a component, so that the generator would contain no hard-coded exceptions, like the old one had been rife with.

2. Add annotations directly to the component or renderer, which would be used to generate the component code. This seemed ideal, where we just write the unique component code, and then add annotations to generate the redundant parts.

3. Add separate classes that would have the annotations, which would be separate from the actual component and renderer classes. This was a compromise between the other two options, where the separate annotated classes in theory could be swapped out for xml files, and either declaration format could generate the components.

Right away we favoured annotations in Java files, where the compiler itself could type check most things for us. There were cyclical declaration issues in the concept of annotating either the end component or an abstract super class. We wanted to maintain the option of the Meta classes being completely separate from the resulting component code, so we could make use of that for our IDE integration as well, which we don't release as open source. And it wouldn't be good to clutter the component with info for every single IDE integration, and thereby obscure the core of the component details. The compromise ended up being the best of all worlds.

There was a long process of prototyping the generator with some example components, and continuously pulling code out of the components and pushing the functionality into the generator. JSF 2 was quite the moving target, which really validated the generator concept, as a single change could be made in the generator to immediately affect every component.


Documentation

Documentation is key with ICEfaces components, since the intent behind a property needs to be communicated, along with the implications of different values, and how some properties interact. With modern IDE integration, the documentation needs to be available when editing view definition files as well as when writing bean code and using property getter/setter methods. The ACEnvironment allows for specifying the TLDDoc and JavaDoc in a single place, as well as individually specifying the TLDDoc and the setter JavaDoc and the getter JavaDoc. In practice, having a single place where you can explain a property means it will happen that once, instead of not at all.

The standard TLDDoc doesn't cover aspects like property default values, ClientBehaviors, facets. With ACE, anything in the Meta class can eventually be shown in the TLDDoc and JavaDoc.


Themes, Sprites, Resources

Outside of the generator and Meta files, there's a whole part of the ACEnvironment that provides themeroller standard themes, that creates sprite images from regular images and updates css files to make use of the sprites. There's jQuery and YUI javascript, as well as any other third party javascript that we integrate with. The build process concatenates and minifies the javascript and css files for performance.


Coding Conventions

One huge intangible aspect of the Advanced Components, are the code conventions they use, aided by helper classes. These are derived from many years of experience designing JSF components, all aimed at side-stepping common pitfalls.

The component Base classes contain all of the generated component code, and the concrete sublass of that is the actual component class, which may need to override broadcast(-), queueEvent(-), process*(-) methods. The rest of the java code is in the Renderer, and is comprised of the decode and event queuing logic, as well as the markup and javascript rendering logic. We have moved away from using DOM centric rendering APIs, and instead use the ResponseWriter approach, which ICEfaces internally can use to directly render output to the client, or employ an intermediate server side DOM for optimising transmitted updates. The html is all properly escaped, and the javascript rendering uses a special helper class JSONBuilder that elevates component writers above the level of javascript string concatenation, to a javascript datastructure level, which also employs proper escaping.

On the client end, the javascript dialogs with the Renderer, receiving and transmitting information. Exactly how the javascript functions are called, and how the script tags are placed within the html markup, and what gets ids and what doesn't, are all quite intentionally done. Some of that is to work with IE browsers, and most of it is to facilitate our incremental DOM updates. It's quite common for an Advanced Component to render itself out, and need to be cognoscente of whether the DOM differencing will update the whole component, some sub-section of the html markup, or just the javascript. In many cases, because the javascript adds listeners to the html elements, if one is updated then both should be. Or in other cases we need to ensure that only the javascript is updated and not the html elements. These subtleties can be completely unnoticeable to a non-ICEfaces developer.


Conclusion

ICEfaces 2 ACE and ICEfaces 3 ACE have been a long time coming, with much experience driving the design goals, and many changes in JSF 2.0.x and 2.1.x in both Mojarra and MyFaces continuing to move the goal posts. It's a rich web component library that focusses on client execution, to complement our more server centric ICE component library. As ICEfaces Component Team Leader during its development, I've enjoyed the opportunity to work with my team to develop something so architecturally unique, that overcomes so many challenges, and creates a solid foundation for further development. I'm proud that ACEnvironment is the foundation that ICEmobile is built on, which itself is a revolutionary component library!

Thursday, April 9, 2009

JSF Event Re-Phasing

JSF has a standard mechanism for controling the lifecycle phase that certain events are broadcast in. For ActionSource implementors, such as UICommand, and the ActionEvent(s) they create and queue, and EditableValueHolder implementors, such as UIInput, and the ValueChangeEvent(s) they create and queue, they use their immediate property to determine the phase to be broadcast in. For ActionSource, when immediate="false" (default), its ActionEvent uses the INVOKE_APPLICATION phase, and when immediate="true", it uses the APPLY_REQUEST_VALUES phase. For EditableValueHolder, when immediate="false" (default), its ValueChangeEvent uses the PROCESS_VALIDATIONS phase, and when immediate="true", it uses the APPLY_REQUEST_VALUES phase.

This primarily allows for Cancel buttons. In a form with input components that have validation settings, command components can be set to have
immediate="true", so that they may bypass validation, and accomplish a non-form task, such as navigating to another page. In some cases, input components may wish to convey their information to the server when a Cancel button is clicked. As so applications may set immediate="true" on input components as well.

But how does one make a ValueChangeEvent be broadcast in INVOKE_APPLICATION phase, so that the valueChangeListener will be fired after UPDATE_MODEL phase, when the input values are now all actually in the bean? One needs a way to make that event be broadcast later than there is an API to specify. In practice, applications use event re-queuing. In the valueChangeListener, the event phase is examined, and set to the later phase, and then the event is re-queued, and the listener returns. When it is invoked again, in the properly desired phase, then the real logic is executed. It works, but is tedious to do in every listener. But most of all, it's non-declarative. When reading a view definition page, one can look for immediate and know which phase the event will broadcast in. But one has to know to look in the bean code to know if re-queuing is happening. It would be more ideal if there was a component or a tag that would accomplish this.

In steps the ice:setEventPhase component. It can take any event type, as specified by class name, not just the standard JSF events, and change them to any phase. It operates on the events of child components, that is any component that is within the ice:setEventPhase component.

It works because when a component queues an event, the event bubbles up through its ancestors until it reaches the UIViewRoot. This allows containers like dataTable to wrap events inside other event objects which contain the row index. When child component events bubble up through the ice:setEventPhase, it then modifies their broadcast phase. Quite straightforward.

The prototypical use case is when one input component changes the value(s) of other input component(s) in its valueChangeListener. What goes wrong is that the ValueChangeEvent is broadcast either in APPLY_REQUEST_VALUES or PROCESS_VALIDATIONS phases. Both of which happen before UPDATE_MODEL phase. So when the one component's valueChangeListener modifies the bean values of the other input components, those input components later get their bean values overwritten by their submitted values, which are basically their old values. With ice:setEventPhase, you can change the ValueChangeEvent to broadcast in INVOKE_APPLICATION phase, so that the valueChangeListener gets the last say in the bean property values.


http://wiki.icefaces.org/display/ICE/ICE+Components+Reference
http://res.icesoft.org/docs/latest/tld/ice/setEventPhase.html

Thursday, May 15, 2008

EJB 3.1 calendar based timers

I attended Ken Saks' session on EJB 3.1 at JavaOne, and found it quite interesting, mostly because I tend not to work on the back-end of applications, since I'm more of a GUI / component developer, so it was informative to me. But one thing immediately leaped out to me, which was the ommission of time zone and locale parameters for the new calendar based timer functionality. I've worked on calendar and time entry components, in JSF and Swing, and I can tell you that it's a typical oversight. So, I'm partly writing this, to hopefully influence the EJB 3.1 team to include it, but partly to raise awareness of this issue in general.

I'm going to start with a simple example, taken from page 38 of the PDF of slides, from the session, now available online.

ScheduleExpression expr = new ScheduleExpression().dayOfWeek(“Mon-Fri”).hour(12);

This should make a timer go off at noon every week day. The example uses hard-coded values, but most likely those would be input by a user in some configuration GUI, or by editing some configuration file. In any case, a human would enter those values. And what that human would probably think is that it would be noon, in their time zone. Perhaps they're working in a branch office, so they might think it should be in the time zone of their head office. Unless instructed, they wouldn't know which of the two it may be. To further complicate things, the server, on which that application is deployed, may not even be in either time zone, as it may be co-located elsewhere, maybe in one of those "safe" places that don't flood or get earth quakes. In that case, they would have no idea, and would have to use trial and error. And those are just the mostly likely scenarios. Add on the possibility of distributed applications, with beans executing in containers around the world, or failover servers intentionally geographically dispersed, and we see that this could actually be impossible for a user or developer to account for.

There's also the lesser issue of daylight savings, where some people need to schedule activities that respect daylight savings, and some people need to ignore daylight savings.

While being able to use "Mon" and "Fri" is a usability gain for most people, it ignores the fact that different locales use different starting days of the week. Some places begin with Sunday, others with Monday. In those cases, people want to be able to just give an index into their week, respecting when their week actually starts. Especially for large organisations which have branch offices in varying countries.

Finally, there's the issue that we're all still assuming the Gregorian calendar. There are many countries which do not use the Gregorian calendar. Almost the entire Middle East does not.

My recommendation is to look into java.util.Calendar, and allow for all of the parameters that it requires. And then add in syntactic sugar.

Wednesday, January 16, 2008

Mobile application component considerations

http://www.michaelyuan.com/blog/2007/09/25/jsf-and-mobile-web-applications-part-1-what-looks-good-on-paper-doesnt-always-work-out/

I was reading this guy's article, and more importantly the readers' comments, about writing JSF applications for mobile applications, and thinking about what ideas best fit with ICEfaces. And that led me to think about some other articles I've read, including one by Ted, a co-worker of mine.

http://blog.icefaces.org/blojsom/blog/default/2007/09/07/Ajax-on-the-iPhone-with-ICEfaces/

The problem is that you can't really write once and run anywhere a web application, with a sophisticated user interface, simply due to screen real-estate trade-offs. If you have a large screen, then you'll want to make more of the interface available to the user at a glance. There's a psychological limit to that though, creating an upper-bound on what you can have in a web page, even on a 30" display. Unfortunately, there's a lower-bound as well, so we can't just target mobile browsers with small screens, and expect desktop users to be happy. So, I'm going to look at ways of addressing this, from a component writer's perspective.

A few differences between desktop and mobile web applications are:

Complexity of the user interface

Showing the user less information, and asking them to do less work, at a time. This can be accomplished by breaking that page into several pages, like a wizard, or by relying more on drill-down detail pages to show successively more detail.

The problems is that you then have to have parallel page hierarchies, which have to be kept in sync as your application evolves.

Another approach is to remain with the single large page, but use intra-page data hiding, so that all of the data is on that one page, just not necessarily at the same time. For example, you could use an <ice:panelTabSet> component, or an <ice:menuBar> in conjunction with an <ice:panelStack> to create sub-panels, where only one will be shown at a time. And the switching will be done via Ajax, without disturbing the rest of the display. Or, better yet, you can use several <ice:panelCollapsible> components, where all of them could be expanded at once, for the desktop user's benefit, or only one at a time be expanded, for mobile users. This is quite simple to do at the application level.

Functionally equivalent components

Some components might be able to accomplish the same tasks, where one would be richer than the other, or have other trade-offs. Just looking at the <ice:panelTabSet> versus list of <ice:panelCollapsible> components, we can see that there are several ways of accomplishing the same goal, but with implications for mobile applications. Perhaps a better example is with date selection, where we could use a calendar or a text field. The text field will be smaller, and fit on a mobile screen easier, but will probably be more cumbersome for actual date entry. Plus, there's the whole issue of date format validation, whether they enter "January 16, 2008" or "2008/01/16" or "01/16/2008", etc. So, showing a date is best accomplished as text, and entered via a calendar. In that case, one would use <ice:selectInputDate renderAsPopup="true"/>.

Still, in the immediate-term, it will undoubtedly be necessary for some applications to use lowest-common-denominator components, or different pages with different components, for mobile versus desktop interactions.

Device aware component rendering

Probably the biggest TODO item in supporting mobile devices, for the component team, is simply rendering differently for mobile devices. Where possible we'd like to keep the HTML markup the same, and simply be more mobile browser friendly. But, where necessary, we'll have to detect when rendering to a mobile browser, and adjust accordingly.

In a way, <ice:selectInputDate renderAsPopup="true"/> exhibits some of the first strategy already, by adapting between the two modes of displaying and entering data. Another example of this would be text entry on the iPhone, with the popup keyboard. Pretty much every input component could be made to simplify its rendering, visually, while not actively being used to input data. This is something that really would not be possible without Ajax.

The iPhone, while simplifying some user interactions, actually complicates others. For example, how does one do Drag and Drop, when finger dragging has been re-appropriated to mean scrolling? Will we simply not support Drag and Drop, or will we have to render some WebKit specific markup? Or, since the iPhone uses a special interface for menu selection, how can we adapt <ice:selectInputText> to benefit from that, if at all possible?

The main example of a component that already renders itself differently, depending on the user's browser, is <ice:outputStyle>, which will output a link for a main CSS file, as well as one that is specific to the user's browser, thereby allowing for CSS work-arounds for web browsers' idiosyncrasies.

CSS styling

Which brings us to CSS, and styling web pages differently for desktop versus mobile browsers. Currently, <ice:outputStyle> can differentiate between:
  • Internet Explorer 6.x and below
  • Internet Explorer 7
  • Safari
  • Safari on the iPhone
  • Opera
  • Opera Mobile
How can you tell that we're Firefox centric? ;)

As you can see, you can serve out different CSS files for the main mobile browsers, automatically, without any application level coding. Over time, the default CSS styles for our components, for the mobile browsers, will get more and more refined. But, the beauty of targeting feature-complete mobile browsers, like Safari and Opera, is that few changes need to be made to styling.

What we're not doing

Notice how I didn't mention using different RenderKits for mobile devices that don't support straight HTML + CSS, or have limited Javascript or Ajax capabilities? Because most cellphones are moving away from those constraints. Maybe a few years ago it was worth throwing a couple years of development into those devices. Hell, maybe even now it appears tempting. But within a year or two that's just going to be a mistake.

Wednesday, January 9, 2008

Bonjour

After getting a taste for writing on the ICEfaces Forums, I've decided to make my own blog, to have as a single place to express my ideas related to ICEfaces. But first, I should explain who I am, and what I do, for this to make any sense at all :)

I work at ICEsoft, where we've got three main products, ICEfaces, ICEbrowser, and ICEpdf. I actually started there working on ICEpdf, which is a Java library for viewing PDF files, that you can embed into your Java applications or applets, say for online help features or whatever. I mostly focussed on adding support for more image types, added the ability to parse the newer PDF file formats which allow for faster incremental loading of PDF files, and a tonne of memory and speed optimisations.

Now I spend most of my time working on ICEfaces, which is an Ajax framework for JSF (JavaServer Faces). Its goal is to transparently add Ajax capabilities to regular JSF applications, where developers just don't have to worry about Javascript or manual configuration of what interactions will update what parts of the page. I've worked in several parts of the framework, most notably in our integration with Facelets, and also as a member of the Component team.

I've always worked on closed source applications in the past, sometimes contributing to opensource projects that my work relied on. So, it's been a new experience working on ICEfaces, where we're actively encouraged to connect with our community. I think that we're pretty privileged in that our community is so strong, helpful, and insightful. Sometimes it's pretty surprising just how superior developing with a community is, over just developing for clients. Hopefully, as times goes by, I'll be able to share those kinds of anecdotes here.