|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Jacob Hookom's BlogCommunity: Java Enterprise ArchivesJSF 1.2 RI - Bean Instantiation and AnnotationsPosted by jhook on May 01, 2007 at 03:38 PM | Permalink | Comments (4)JavaServer Faces 1.2 includes support for Resource Injection and annotations such as JavaServer Faces currently has a couple great frameworks that extend application coordination and ease development. Since not everyone uses these frameworks, I wanted to write a short blog on what you can do out of the box with JavaServer Faces 1.2 and the reference implementation. Push vs. Pull in ViewsSince JSF's inception, you've been able to declare any number of java objects within multiple Sometimes it's difficult with action frameworks to be able to setup (push) everything the view may or may not need at the time of evaluation. When you have something like managed beans and EL within JSF, nothing needs to be pre-executed as your view can just pull in the managed beans it needs. A simple use case is displaying data conditionally in the view-- happens all the time. Since you can pull only what you need into your view, there's less concern of pushing unnecessary database state into a view which may not actually need it. A second case is reuse. You may need to generate a list of current orders in multiple places. With JSF, the practice is to just create a 'CurrentOrdersBackingBean' which can be pulled into any view. Often many from the Struts world would've populated that list within any possible action that results in a view which may display the list of orders. Basically, the development mentality with a pull MVC is to create fine-grained beans with a single purpose (SRP). JSF's managed bean declarations will allow you to wire in other state from session beans or request parameters. In the case of displaying a list of orders, you may end up with a config like so:
The above configuration will allow views to use/declare
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Algorithm/Type | Size in Bytes | Write in Milliseconds | Read in Milliseconds | Total in Milliseconds | Request/Second | Bytes/Second | # of Hits |
|---|---|---|---|---|---|---|---|
| None (Default MyFaces) | 174,345 | 78.14 | 198.12 | 276.26 | 91.8 | 2,529.89 | 27,598 |
| GZip (Default RI) | 12,864 | 103.72 | 205.68 | 309.4 | 58.6 | 518.05 | 17,633 |
| Default Compress | 12,852 | 93.42 | 174.08 | 267.50 | - | - | - |
| Best Compress | 11,855 | 110.24 | 171.04 | 281.28 | 62.2 | 544.76 | 18,695 |
| Best Speed | 16,480 | 86.58 | 176.24 | 262.82 | 63.5 | 569.02 | 19,091 |
| Huffman | 15,190 | 79.46 | 175.22 | 254.68 | 63.8 | 590.21 | 19,181 |
| Filtered | 16,480 | 79.36 | 176.88 | 256.24 | 64.1 | 600.97 | 19,272 |
The different algorithms are listed within the java.util.zip package in the javadocs, but I found the numbers to be pretty interesting. Of course, I'm a compression n00b, so if anyone had any comments on why it would be bad to switch to one of the other algorithms as a set-able option with JSF, please let me know!
I should note too that smaller page sizes, all the algorithms fluxate in timings between runs by quite a bit (5ms > 0ms) which may be attributed purely to GC or the ObjectOutput/InputStream itself.
Facelets 1.1.12 was just uploaded to Java.net and includes many small bug fixes for JSF 1.1 (MyFaces 1.1.4) and JSF 1.2 (RI 1.2_03b5).
This release is considered 'draft' until users call it stable for production use. More information is found over at Facelets' web site.
Please give it a whirl and post any issues to the tracker or dev/user lists so we can push for another stable release!
Updated 11/17/2006 with JEXL and upgraded MVEL and added Serialized size
I decided to test the following EL libraries available today:
Here's a table of features I thought were pertinent:
| Library | A.B Accessors | Math | Method Invocation | Projections | Regular Expressions | Coercion | Conversion | Pluggable Property Resolution | Pluggable Method Resolution | Serializable | Factory Caching |
| Commons-EL | Yes | Yes | No (functions) | No | No | Yes | No | No | No | No | Yes |
| OGNL | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | Yes | Yes | No |
| MVEL | Yes | Yes | Yes | No | Yes | Yes | No | No | No | ? | No |
| EL-RI | Yes | Yes | No (functions) | No | No | Yes | No | Yes | No | Yes | Yes |
| JEXL | Yes | Yes | Yes | No | No | Yes | No | No | No | No | No |
Pretty obvious things that stand out are that OGNL and MVEL have a lot more syntax features compared to the standardized EL. I think this is largely impart to the fact that EL was only intended for simple notation within the View counterparts and not as a scripting language. I will say that there's absolutely no reason why these other syntax features shouldn't be added to future releases.
Pertaining to pluggability of syntax evaluation, OGNL is the most expressive with Method, Property, Index, etc. The new EL-API has similar capabilities for Property and Index Accessors with chainable ELResolvers.
*Factory Cached means the API's factory method inherently cache expressions to some degree and do not re-parse on every call.
API Use:
Commons-ELExpressionFactory fact = new ExpressionFactoryImpl();
VariableResolver vars = new VariableResolverImpl(..);
Expression expr = fact.parseExpression(str, Object.class, null);
Object value = expr.evaluate(vars);
OGNL
Map vars = new HashMap();
Object expr = Ognl.parseExpression(str);
Object valu = Ognl.getValue(expr, vars);
MVEL
Map vars = new HashMap();
Object value = Interpreter.eval(str, vars);
EL-RI
ExpressionFactory fact = new ExpressionFactoryImpl();
ELContext ctx = new ELContext(...);
ValueExpression ve = fact.createValueExpression(ctx, str);
Object value = ve.getValue(ctx);
JEXL
Expression e = ExpressionFactory.createExpression( jexlExp );
JexlContext jc = JexlHelper.createContext();
Object value = e.evaluate(jc);
Finally, I have some performance numbers at 10,000 iteration, average time in milliseconds:
| Library | test.fubar != null | test.num + 10 - 1 |
| Commons-EL | 0.00249 | 0.00343 |
| OGNL | 0.20751 | 0.23535 |
| MVEL | 0.02032 | 0.03775 |
| EL-RI | 0.00714 | 0.00715 |
| JEXL | 0.34199 | 0.21907 |
| Commons-EL (re-use) | 0.00597 | 0.01462 |
| OGNL (re-use) | 0.00342 | 0.00712 |
| EL-RI (re-use) | 0.00394 | 0.00767 |
| JEXL (re-use) | 0.04946 | 0.01123 |
*re-use means take the Expression returned from the factory and keep evaluating that instance instead of going back to the factory again. This didn't show much of a difference for those EL libraries that cache within their factories, but it did show a big improvement with OGNL and JEXL.
Serialization can be important for some libraries and the EL-RI was optimized for use with JSF's state-saving architecture. I'm sure other frameworks may have similar concerns. Here are the sizes in bytes for the couple libraries that were actually Serializable.
| Library | test.fubar != null | test.num + 10 - 1 |
| OGNL | 594 | 764 |
| EL-RI | 170 | 169 |
Synchronization was another thing I wanted to test, but haven't yet. Supposedly OGNL has some unwanted synchronization blocks and JEXL has not been optimized at the Factory level at all-- putting a synchronization block around expression creation, with calls to commons-logging.
In summary, here's just my observations from an afternoon of testing. While I'm not an expert on all of the libraries listed, feel free to comment on where I might have missed a point or gotten things wrong.
If you take a look at GWT (Google Web Toolkit), you are dealing with a subset Java API to accomodate JavaScript execution on the client. While this does tend to push more execution on the client, it does limit your ability to coordinate traditional transactions and APIs that you are used to with the full JEE stack. What if you were to flip the tables on GWT and use server-side Java to generate JavaScript to execute on the client?
With this approach, an AJAX request is made to the server, and instead of responding with data, you respond back with JavaScript code to execute which manipulate the screen or refresh different parts of the screen. JavaScript generation is supplemented by 'native' APIs to Java.
While I'm sure there were others doing this long before, the Rails community has made the approach quite popular with RJS. You can read a bit on Rails solution here.
As part of our JavaOne demo last year, I included an example of this with JSF, but the API looked like:
ClientWriter writer = ...;
String errorMsg = "This is an Error to push to the client.";
writer.select('myDiv', Element.hide());
writer.select('errorMsg', Element.setHtml(errorMsg), Element.show(), Element.highlight());
This would generate the following JavaScript in the response, which would use JavaScript libraries such as Prototype or Scriptaculous.
<script type="text/javascript">
Element.hide($('myDiv'));
$('errorMsg').innerHTML = 'This is an Error to push ....';
Element.show($('errorMsg'));
Effects.highlight($('errorMsg'));
</script>
This JavaScript would then be evaluated on the client when the AJAX response was received, just like any other local JavaScript function, except we've generated the logic on the fly, using the full JEE stack on the server.
While we can identify elements in the browser DOM by ID, JSF has a (complex) clientId system for identifying elements in the DOM. We can simplify this by adding methods to the ClientWriter which just take in a UIComponent as your selection criteria:
<h:inputText value="#{bean.name}" binding="#{bean.nameInput}"/>
<h:commandButton action="#{bean.action}"/>
// MyBean.java
private UIInput nameInput;
public void setNameInput(UIInput input) {
this.nameInput = input;
}
public String action() {
....
if (loginFailed) {
ClientWriter writer = ....;
writer.select(this.nameInput, Effect.highlight());
}
}
You can see a live prototype of this in the context of constructing a cart and updating various parts of the page here.
Some of the logical pros of this approach to server-side generation of JavaScript with AJAX are:
So what does the API look like in implementation?
// ClientWriter.java
public ClientWriter select(String id, Script... s) throws IOException {
if (s == null) return this;
String var = this.getBuffer().append("${'").append(id).append("')").toString();
for (Script i : s) {
i.write(var, this);
}
return this;
}
// ClientWriter.java (for CSS-like selectors from Prototype.js)
public ClientWriter select(String selector, Script... s) throws IOException {
if (s == null || selector == null) return this;
this.writer.write(this.getBuffer()
.append("$$('")
.append(selector)
.append("').each(function(e){").toString());
for (Script i : s) {
i.write("e", this);
}
this.writer.write("});");
return this;
}
// Script.java
public interface Script {
public void write(String variable, ClientWriter writer) throws IOException;
}
// Element.java
private final static Script Show = new Script() {
public void write(String variable, ClientWriter writer)
throws IOException {
writer.write(variable);
writer.write(".style.display='';");
}
};
private final static Script Hide = new Script() {
public void write(String variable, ClientWriter writer)
throws IOException {
writer.write(variable);
writer.write(".style.display='none';");
}
};
public static Script toggle(boolean show) {
return show ? Show : Hide;
}
I'd be interested if others have ideas on a better method of handling/coordinating generation of JavaScript code in a Java API? As you add more JavaScript libraries, you can add additional Script singletons to generate the necessary code-- I guess similar to what would be required to code custom GWT components with their method of handling 'native' calls.
JavaOne was fantastic this year. Being a presenter did put a very different twist on the week-- especially going at the end. This left Ed Burns, Adam Winer, and I plenty of time to go over our presentation. I might as well been tied at the hip with them because of all our practices dotted throughout my session schedule.
While I didn't get a chance to attend all of the sessions I planned to (I guess it was kind of like my time in college), it was a great week. I attended a few Swing presentations to boot where I heard people comment that they wanted more data binding/structure as we do for application development in the webtier, where others in the webtier presentations were seeking more swing-ish functionality with AJAX.
Our presentation went pretty well. I think we were able to get our point across that JSF is great for AJAX, but we didn't do a good job of explaining that it has been for years now with Oracle ADF, IceFaces, and Exadel. My concern was that as end developers start approaching AJAX on their own, that they have their bases covered and understand the problems that these vendors have already solved in their own ways.
The highlight of the week was the WebTier EG meeting. While the content of the discussions aren't public, I can say that we did bring in other framework developers for their input. And thankfully, they weren't too shy ;-) It was a great commitment from the Sun spec leads to bring them in-- we need the guys writing these popular frameworks, which have traditionally needed to jump out of convention for various reasons, to help us correct/ease development for them and others.
Finally, Don Brown (of Struts fame) has started to put the framework wars to rest by putting them in bed together (metaphorically speaking of course). Check out his blog and the code. I did leave talking to him at JavaOne thinking that he would be able to 'template' out a common controller for JSF 2.0. We'll see how well the approach goes compared to JBoss Seam's alternate route of going from JSF to Action MVC. I've used both JSF and WebWork on projects both professionally and otherwise and there are times when all I need is WebWork and there are times when I spend a lot of work 'hacking' WebWork when JSF's component model would've 'just worked'. I'm a very happy developer today :-)
With JSF, we have this robust component model, an extreme amount of collaboration that has existed since the spec's inception. AJAX has arrived, but many of the examples online simply jump outside of JSF to provide ivory tower solutions with lots of manual coding by the end developer. This can inevitably falter long term and place developers back into the same situation they were in with JSP and JSF where things didn't 'jive'.
In hopes of pioneering a different perspective on AJAX with components acting as pure, mediating collaborators-- Adam Winer, Ed Burns and I will be presenting a possible future in TS-1161 at JavaOne.
A while back, I started to write DAO's for an application at work; and of course we chose Hibernate. I've been on this 'K.I.S.S My App' kick lately with keeping things as simple as possible and actually leveraging APIs to their full extent. This theme was carried out so much so that the DAOs actually returned Criteria objects:
public class WidgetDao extends DaoService {
public Criteria queryByCategory(long catId) {
return this.getSession().createCriteria(Widget.class)
.add(Restrictions.eq("category.id", catId);
}
public List findByCategory(long catId) {
return this.queryByCategory(catId).list();
}
}
So why the heck would I expose Criteria objects? Well, the answer is simple: I wanted to allow the most flexability at the point of most concern. So the DAOs expose this initial constraint over the data with whatever business/domain logic (the case above is really simple), but as to the what and how the data is returned, now the client of the DAO is free to decide.
This really came to light when creating UIs where we could gain Criteria instances, then assign projections, sorting, and additional filtering over the data without pressing this use case back onto my DAO/Services layer. The end result was highly efficient, agile, and fast data mining within the UI. No needless layers of complexity and procedural contracts with my service layers to expose the information I needed.
Let's apply this concept to SOA and RPC. Many of these new AJAX 'frameworks', and Action MVC frameworks in general, rely on pushing content around. You spend time building up these procedural contracts to expose data models, but there's no way to know what information is used and how the information will be used.
This blindness really comes to light when you are dealing with desparate systems with client/server or server/server architectures. You've written an RPC method to deliver a set of Widgets. Well, in your domain, Widgets have a lot of aggregate and composite relationships, how do you know what to expose and how to expose it to all clients? You may simply choose to push 2K of object graphs when all you needed was the Widget's ID and Description. So you begin to see the waste. This gets even more tricky when clients access to some of that aggregate data on Widgets, and if that fails in performance, are you going to write more RPC methods?
Some of the public SOA APIs from major vendors kind of do this with providing specialized parameters/attributes within their requests to specify client-based constraints such as, "Do you want short or long details on the product search?" (Amazon).
Because we are blind to all possible use cases of our domain models and services, we come up with a way for the client to interrogate the data or add constraints to our RPC calls within the remote request itself. Ideally, this would be taken care of by some mediator framework such that the RPC could be invoked on the server, but based on the constraints provided by the client, we can selectively return "lighter" responses.
So take a Widget catalog exposed over SOA. We still have the RPC contract for security such that we apply initial constraints, but client could use XQuery or some other standard to specify how and what is being transported back over the network. How do you know all the possible ways of exposing your data model to a client? Wouldn't it be easier to just use some kind of mediator to query/filter/sort your data as each client needs it?
In terms of the UI, it would be conceivable to back this by a templating engine on the client such that a JavaScript Agent could pre-determine what data is presented and selectively query generic RPC services on the server.
It all comes down to a cost highlighted with network latency. Having objects in memory on the server is cheap, but we all know that XML/etc is horrible at efficiently representing object graphs and that network latency is an obvious crutch in thin-client applications. We alleviate this issue to some extent by coming up with an Agent-based solution on the client with a server-side mediator which will specify the what and how data is transported over the network. Keep in mind, the traditional push model for data can be both expensive to the client and server.
At JavaOne, we'll be talking about other approaches with AJAX and how component-oriented MVC (in general) not only supplements the complexity of UI constraints, but also is more agile than traditional approaches. JSF Avatar carries the torch in this context such that we've gone through the work, once, of defining our view and how the 'domain' of the UI relates; then we allow the client Agent to describe how it wants to interact with the view in an efficient and secure manner.
After a lot of community testing with the 1.1 releases, we've decided to create a stable, milestone release available here. Facelets already has great documentation and provides unbeatable error handling with debugging features for the JavaServer Faces framework.
Many component frameworks available today still fall within the same development requirements as Model 2 frameworks, such as Struts. You have to create a document that represents your view and produce a secondary action or page object of pure adaptor logic/code. With JavaServer Faces, you just have your single document, and the work required of other component frameworks is done automatically by weaving the view and controller aspects together when needed.
Facelets goes one step further as a view technology as it caters specifically to the mechanics of JavaServer Faces. Starting with the compiler, all content, such as text and non-components, is interwoven in such a way that the expensive character data is shared for all users/threads. This helps to keep the pricey aspects of buffering/appending character data within the view to a minimum while avoiding wasteful evaluation.
This really comes to light when you start to look at what's around the corner for MVC with AJAX and partial processing. Views can be constructed without evaluating unecessary results unless required-- setting the stage for things like avatar. No specialized actions, no breaking up of documents, this is purposeful and practical applications of AJAX without lock-in or commitment in your development strategy. Developers complain enough as is about the complexities of MVC on the web, now they think writing specialized logic for AJAX will make their lives easier? Come on, lets approach this sensibly with component-based frameworks.
Finally, Facelets really pushes convention over configuration in the presentation, removing the need to write adaptor code even within the presentation for UIComponents, Validators, and Converters. Although, custom tag development is a piece of cake.
Adam Winer contributed a weekend to modifying the way that shared content, such as non-components, were handled with Facelets' compiler. Now Facelets works directly with the ResponseWriter to produce all the appropriate events for writing elements, comments, attributes, text, etc. The result of this is two fold: we've now cleared up browser specific issues (eg. <script/> tags) and JSF developers are now able to customize the their ResponseWriter implementation to further enhance the output of the whole view for specific platforms, markups, or client/server communication (such as DOM or Fast Infoset).
Along with other bug fixes, the templating features now have better support for inheritance of views and a <ui:repeat/> component was added for times when you need to iterate over collections of data. This component, in conjunction with Facelets' common aliasing features, allows you to inline the repeating right on your <tr/> or <li/> tags in HTML.
As always, open source projects are a work in progress. While much of the core of Facelets has stablized in functionality, I'd like to start vesting time in purposeful component development and web standards with JavaServer Faces. I'm also getting more eager to produce examples of XUL and XAML (windows vista) with JavaServer Faces and Facelets. Lastly, Facelets EL implementation is configurable, so I'd like to see OGNL or JEXL implementation of the the standard EL-API available soon ;-)
All MVC frameworks basically operate within the same 5 phases:
Each of our favorite frameworks are implemented differently, but these phases always exist in some form or as an optional phase. Look at Struts w/ ActionForms and Actions or the hook methods and interceptors within WebWork.
Historically, all of these frameworks start their integration with an HttpServlet or Filter. This is their platform:
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// start here
}
Wow, thanks JEE. You can begin to see why there's so much redundancy or one off approaches to MVC implementations.
A while back, Kito Mann started a WebTier Alignment Group of framework developers. While the group unfortunately never really took off, there were some great discussions and comments. The group did identify that there's common artifacts and points of integration between these frameworks. Maybe a common way of defining validators or converters-- or even a common way of integrating a project's domain model?
I'm going to go out on a limb and suggest that frameworks instead piggy back on the FacesServlet. I'm not saying that framework developers use JSF as end developers do, but being that it's part of the JEE 5 specification, use the bits and pieces you need. There's so much there that can be provided to frameworks that operate completely different.
To elaborate on this, I'm going to template out a simple Action framework that sits on top of JSF, but only uses a little bit of the features, not including the overhead of stateful components. Ideally, we want to process URIs like this:
/order.addItem.do?item.id=41667&item.qty=3&item.code=SA
First, based on our familiarity with the HttpServlet, where do we start with our simple solution for JSF? The easiest route is to implement a PhaseListener which intercepts requests and does all the processing itself. Alternately we can look at simply providing a Lifecycle implementation.
Because we want to provide RoR/WebWork-like features, it would be great if we can simply invoke or set properties directly on our domain objects from an IoC container. Well, the Faces API has a scoped IoC container built in and has integration from both Spring and JBoss Seam to name a few. Sounds like we're already ahead of the game for our simple Action framework.
To implement our request processing, we'll break the URI into parts and evaluate them using JSF's built-in EL capabilities. The following is example code for basically implementing the 5 MVC phases with the help of JSF. While there's more to be added, this provides the basics required in pseudo code.
// get our JSF-provided FacesContext
FacesContext faces = FacesContext.getInstance();
Application app = faces.getApplication();
// JSF provides Portlet/Servlet wrapper
ExternalContext ext = faces.getExternalContext();
// EL support from JSF's API
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext el = faces.getELContext(); // local to thread
// to store messages
Map<String, String> msgs = new HashMap<String,String>();
ext.getRequestAttributeMap().put("messages", msgs);
// our view result to forward to when we're done
String result = null;
// 1: decode phase
String action = faces.getViewRoot().getId(); // w/ massaging
Map<String,String> params = ext.getRequestParameterMap();
// 2: validate phase
boolean valid = true;
Map<String,ValueExpression> paramEL = new HashMap();
// enable our ValidateResolver
el.putContext(ValidateResolver.class, Boolean.TRUE);
ValueExpression ve = null;
for (Map.Entry pair : params) {
try {
ve = elFact.createValueExpression(el,
"#{"+pair.getKey()+"}",
Object.class);
paramEL.put(pair.getKey(), ve);
// ValidateResolver could throw an error here
ve.setValue(el, pair.getValue());
} catch (ValidatorException ve) {
valid = false;
msgs.put(pair.getKey(), ve.getMessage());
}
}
// disable our ValidateResolver
el.putContext(ValidateResolver.class, Boolean.FALSE);
// if we validated successfully
if (valid) {
// 3: update phase
for (Map.Entry pair : params) {
ve = paramEL.get(pair.getKey());
// set it for real
ve.setValue(el, pair.getValue());
}
// 4: invoke phase
String elAction = "#{"+action+"}";
MethodExpression me = elFactory.createMethodExpression(el,
elAction, Object.class, null);
Object invResult = me.invoke(el, null);
result = (invResult != null) ? inResult.toString : null;
if (result != null) {
// delegate routing of result
NavigationHandler nav = app.getNavigationHandler();
nav.handleNavigation(faces, action, result);
}
}
// 5: encode
faces.renderResponse();
While the above is only pseudo code, it does show that JSF could be used without needing to use stateful UIComponents with a custom, lightweight MVC framework. Because your framework would have a FacesContext always available, it would be much easier for you to include UIComponents down the road if you so choose.
I guess the point I'm making is that these new frameworks should take advantage of the JSF API, even though you're not using all of it. Facilitating other framework developers with the JSF API is something that should be pursued more vigorously by the JSF EG. With each phase of MVC outlined within JSF and the delegation of concerns around ViewHandlers, NavigationHandlers, ActionListeners, Converters, Validators, etc, the whole stack is very customizable. Ideally, developers could co-habitate MVC solutions on top of the JSF-API such that you can have the best of both worlds with action and component frameworks.
In a previous blog, "New Feature for JSF 1.2", I concluded with a few sentences on breaking through traditional MVC with JSF:
At the 30,000 foot view, here we've broken through the traditional URI/resource in request/action based frameworks such as RoR, where each thing you want to partially handle has to be separated out and coordinated as a specialized endpoint. Not so with JSF since we've extended the concept of a URI into the page itself, allowing you to uniquely operate on resources embedded into the page. The best part is that your components don't need to know that they are processed as part of a whole or part. In truth, the same applies to your domain model-- refresh that list of employees or modify just one employee without needing to coordinate actions or special cases.
Let me elaborate on this a bit in relation to where I see JSF progressing through JSF 1.2 and future specifications. Keep in mind, I'm only one EG member with my own views. First, it'd probably help to explain the what's different about JSF in relation to other, common MVC implementations available.
![]() |
|
![]() |
|
![]() |
|
I thought you'd say that! I believe a deficiency in many MVC solutions is that at some point, you are required to supplement the framework with action or page artifacts in order to coordinate request processing. With Component Frameworks, the view becomes self sustaining for request processing via declaration. With this, we've flipped the traditional 1:many role of actions to views in development and we now have a many:1 relationship. This seems to be more natural to developers for handling event systems instead of coding handlers (actions) for each possible event in the application.
To circle back on my original point of this blog, because components are self-sustaining within the framework, this provides the aforementioned benefit of flipping action and view relationships and allowing your documents and views to be processed as a whole or as partial fragments. Traditionally, since MVC events are mapped via URI as a special case-- that's one channel of communication. With component frameworks, a single URI can be processed/handled in multiple ways in part or in whole, which leads the way to richer forms of communication on the web while easing development.
Take a look at what would be required for development, keep in mind, what is categorized as an 'action' is java code that only exists to coordinate event or request processing of state.
| Traditional MVC | Component MVC |
![]() |
![]() |
For traditional MVC each possible event from the view, you've been required to develop and maintain an endpoint that often includes one more artifact that supports rendering (a view). On top of that, the coordination between client and server is only supplemented by convention and is not automatic. With component frameworks, your development time is spent producing a single artifact that describes the view, composed of pre-fabricated and reusable components that automatically coordinate client and server communication.
As we push forward into richer client interactivity, AJAX for one, what expectations are going to be put back on the developer for not only coordinating, but maintaining these specialized solutions? By the nature of component MVC, each component handles it's own state coordination as supported by the overall framework. This means that components can encapsulate handling AJAX or other rich-content delivery without concerning the application developer or other components included in parallel-- 'they just work'.
It depends on what kind of scalability you are looking for. It's like the old project management grid, the division of: time, money, and quality. You can't have everything-- yet. What I'm talking about is scalability of requirements vs. hardware/bandwidth. I jokingly remember when Struts first came out and people asked about the additional overhead on hardware, Craig replied something along the lines of, "Hardware's cheap, you can always add more, programmers and application maintenance is what's expensive." While this is true, everyone knows there can be restrictions.
| Traditional MVC | Component MVC |
![]() |
![]() |
The above graphs only serve to highlight differences between the two routes of development.
One may retort, "Why do you think component frameworks are much better at scaling complexity?" To avoid sounding like a broken record, let me ask why everyone uses Spring. Spring provides a series of pre-packaged, pluggable artifacts that support development on the JEE stack. Components work the same way. I could, for example, provide a component that generates an editable table, backed by EJB 3. Similar to portlets, a developer can drop components into their application and use in parallel with others. It's a vertical solution such that it doesn't require much, if at all for additional development.
Pre-packaged solutions aside, since component artifacts are self sustaining, so are developer-created supplements that increase maintainability and re-use. The solutions are vertical.
With traditional MVC, you end up with a series of horizontal solutions that must be maintained and coordinated across multiple layers. The EJB-backed table example would probably require: directly interacting with a PersistenceContext, generating actions for each event type, manually coordinating state transfer between the client and the server, and creating a view to handle passing the appropriate state to the correct actions. On top of that, could you ever use all of those artifacts along side other widgets in a larger view? You can quickly realize the exponential growth in complexity for development with traditional MVC.
So you've warmed up to the idea of component solutions for MVC, but the stateful overhead gives you chills. Well, to do component solutions correctly, you are going to have some additional overhead. Really, are you supporting a few hundred users or tens of thousands? If it's the latter, I have an answer for that (surprise). Just like with ORM solutions for persistence, there's cases where you need to optimize. Nothing would stop you from dipping into SQL queries or direct JDBC use. Well, with component frameworks, there's nothing stopping you from either marking components transient or basically limiting their use. For those 'dump content to screen' use cases, you may not need any components at all-- thusly a lack of overhead where the calls could be stateless. But for those cases where things start to get complex, go ahead and utilize components to support development.
Basically, it's a major misconception that because you use components, everything must be coordinated via components. As mentioned in previous blogs, you can produce/render URLs that simply pass identifiers without requiring component state to be maintained across requests.
First, it's a standard. While some may simply ignore this fact, it's already blossomed a large market of solutions/services. This is Web 2.0. You have multiple vendors, shops, and open source projects that can be literally dropped into and utilized with your applications. While other frameworks do support component development, no where else are you seeing this kind of support from the community at large.
Look at JSF's track record. JSF is built more like a platform, allowing extreme amounts of customization. Since it's initial spec, we've seen many alternatives pop up for describing views, managing application state, and tying in existing popular frameworks. I could start a list, but again, no other framework on the market has been as actively customized or added to-- including Struts.
Finally, look at the way you develop applications. It's the interface/UI that sells your product or more commonly sells your capabilities as an application developer. Going the route of components, knowing you can more easily scale UI complexities-- you're not going to be selling yourself short.
First off, thanks to the JCP and JEE EG for allowing us to add this feature so late in the game. The system *does* work! Now, on to the details...
The core of JSF views are mutable component trees, uniquely identified, black boxes of encapsulated features that can be dropped in and combined in the true academic definition of a 'component'. Each component can participate not only in rendering, but all other phases of MVC including updating, validation, invoking actions, etc as part of an event system. One way to look at it is Action chaining to the Nth degree in the form of widgets that will coordinate/handle MVC request processing.
So here we have trees of components. How do I ask for a particular component in the tree? Well, currently the JSF API only had UIComponent.findComponent(FacesContext, String id), which used a specialized logic of interpreting that passed String id to find the associated component. Developers immediately assumed that the ids JSF produces work for the findComponent() method. Sorry to say, they don't.
The reason why findComponent() doesn't work is in how JSF works with iterative contexts-- something traditionally done with a c:forEach, h:dataTable, or d:displayTag. If you have a parent component who will render its children a hundred times, it doesn't mean there's a hundred children. The parent component simply evaluates its one or two children 100 times, saving on memory. Makes sense doesn't it? So, now we have to uniquely identify each child for each iteration, so JSF produces ids (Client Ids) in the form of mytable:3:text, mytable:4:text, mytable:5:text, etc. You get the picture.
Now, lets say you wanted to take that identifier of mytable:4:text and operate on it later, such as re-rendering part of the page without evaluating the rest of the page. We know that UIComponent.findComponent doesn't work since it returns a UIComponent instance-- but for what row, what state-- there's only one instance in the component tree! And, findComponent knows nothing of the client identifiers your custom UIComponents produce. What do we do?
To solve this, we've added boolean UIComponent.invokeOnComponent(FacesContext faces, String clientId, ContextCallback callback). This allows, in a Chain of Responsibility fashion, a callback to be passed into the tree and when a UIComponent decides to handle it, it invokes the callback and returns true, telling the process that we're done.
This allows black box components, like UIData (h:dataTable) to allow you to operate on a specific component within a given row. Keep in mind, each iteration, just like with a for loop in Java is volatile, so by passing a callback, as in an event system, you can operate on state within a given iteration without collision.
Here's a simple example of partially rendering a JSF component model for things like AJAX. JSF renders your page and produces a series of client identifiers in the page. Now, you want to refresh only part of the rendered page for a known client identifier. Simple!
public static final ContextCallback RENDER = new ContextCallback() {
public void invokeContextCallback(FacesContext ctx, UIComponent c) {
c.renderAll(ctx);
}
};
// custom ajax request
String clientId = paramMap.get("renderId");
UIViewRoot root = faces.getViewRoot();
boolean found = root.invokeOnComponent(faces, clientId, RENDER);
if (!found) throw new FacesException(clientId + " not found!");
Notice, we didn't need to process or render the whole tree and mess with special content buffering or wasteful evaluation. We just pick out what we want to operate on. The RENDER ContextCallback was a simple example, but could be extended for any number of things. Since each UIComponent knows how it produces client identifiers, you can optimize the invokeOnComponent seach to jump to the correct component state in just a few hops, avoiding visiting or evaluating 100 child component iterations when you know the client id was for index 101.
Fantastic stuff in my opinion. At the 30,000 foot view, here we've broken through the traditional URI/resource in request/action based frameworks such as RoR, where each thing you want to partially handle has to be separated out and coordinated as a specialized endpoint. Not so with JSF since we've extended the concept of a URI into the page itself, allowing you to uniquely operate on resources embeded into the page. The best part is that your components don't need to know that they are processed as part of a whole or part. In truth, the same applies to your domain model-- refresh that list of employees or modify just one employee without needing to coordinate actions or special cases.
With traditional Action MVC frameworks (Struts), you have a specific set of scopes to store state in over transactions: request, session, and application. Often, while developing applications with Action MVC frameworks, you have to make a decision to store objects/state in the request or the session. There can be consequences to the the performance of your application in either case. You can go the transient route and just retain state for a request cycle, or you can live with and manage it in your session.
Let's disect a request to an MVC application-- when you compare the time your in-memory Java code takes compared to DB calls, often times, the time spent by the MVC framework is marginal-- JSF or Struts. So we go back to trying to fix performance with the DB by either specializing operations in the request or storing results in the session.
JSF has acted as a foundation for frameworks like JBoss Seam and Oracle ADF because it provides context to user interactions. These contexts can be used to scope cached data in more meaningful processes without committing to a full transient (request) or persistent (session) solution. It becomes much more practical to store results from the DB within the context of a particular paging table component, avoiding the 600ms->20sec DB queries. I hope you see my point.
Take a look at your caching strategies and ORM mappings-- what's driving those fetch policies and associations? Are you making decisions to not-lazy fetch an association because you display it with the parent object? I would say that a lot of your decisions around caching/fetching policies is formulated by what's being coordinated in the presentation. Doesn't it make a lot of sense then to have a MVC solution that retains and manages those contextual associations for you?
Now, pair that meaningful, contextual state management with encapsulated AJAX components that can communicate back to that managed state without 'requiring' DB calls for partial requests....
In one my last blogs on the concepts behind Avatar involved trying to gain performance via AJAX by partially processing a UIComponent tree in JSF.
I'd like to bring another possible idea up with JSF: what about treating all components as stateless? Not stateless as in Servlet-stateless, but stateless as in request scoped.
As mentioned in the Avatar blog, component tree creation is dirt cheap (especially with Facelets). What's expensive is state saving and rendering. So here we have this idea that evolved out of Avatar about partially rendering component trees, but then there's still a state saving issue. Even though we would render only part of the document for AJAX requests, theoretically, any part of the component tree could have changed-- so the whole tree has to be saved on every request.
JSF currently allows two different modes of state saving: client and server. In current implementations of Avatar (such as Galen Dunkleberger's), state saving only works in server mode. This is because there isn't a requirement to update the client document on every request because the server manages that state for you. With client state saving, you are required to maintain state change in the client document via hidden variables and inputs. This is a big hurdle to say the least.
Well, what if we were to throw that requirement of state saving out the window? This way partial rendering, restful communication, and server load wouldn't be so much of a problem. Maybe because I've spent too much time in the 'boiler room' of JSF to see the importance of retaining state in UIComponents, but I'd like to explain some of my reasoning behind this approach in hopes of getting feedback from other developers.
There's two ways to manage state. Actually Store the result of the process, or be able to consistently repeat the process to be able to conclude the same result. Think about JSF's tree building process and the the fact that it's clearly repeatable-- structually the same[1] and expressions can be bound on every request. So why store the same stuff for every user on your site?
[1] With JSF's tree building process, imperative control tags, such as JSTL, force a mark'n'sweep process on tree creation. While this does allow the page to be structually different from the previous request, it's easily avoidable by using JSF counter parts. In some cases, one could say that re-evaluating the structure of the tree on every request would be preferred.
With the new EL-API and webtier alignment with JSP, there's no longer a disconnect on variable management and attribute assignment between the evaluated JSP document and the UIComponent tree. Again, this only leans towards the fact that retaining variable/attribute state across requests (document evaluations) could be unecessary.
Compared to other frameworks, like WebWork or Struts ActionForms, you have request-scoped state to operate on in different ways. Example, you can take a WebWork action and invoke multiple methods on that object such as update, validate, execute, etc. Hey, wait! So could JSF. Why couldn't you produce a JSF UIComponent tree at the start of every request, then update it from the incoming request, possibly validate, update the model, invoke actions, and then render?
Statesaving in JSF is [really] bad in implementation. It's very much like JSP tags where all possible attributes have to be processed. Same thing with any variable state for JSF-- both within the UIComponent itself and the whole tree structure. It's not like EJB3 or Hibernate where the framework can freely managage or optimize state deltas for you since JSF lets you explicitly implement state saving, even if you don't want to. I've thought about doing automatic state saving deltas, but then I'd lose any contract with invoking the state saving template methods on UIComponent.
JSF probably does the best job (out of the MVC frameworks) of clearly separating the View from the Model and Controller via EL. Again, this introduces an interesting point such that anything we would want to retain reference to within the JSF lifecycle and state saving-- is defined by a [static] EL expression that can be assigned and evaluated, disjoint from the UIComponent's state.
As we move into more client-side functionality with JSF and AJAX or simply client side DOM, it may introduce a disconnect between the captured state and the actual state the client sees. Then being able to 'lighter' requests back to the server becomes much more important (Avatar) and state saving of the perceived server state becomes [unecessary] overhead.
At this point you may think I'm either really dense or just maybe have a point. Again, I haven't had a chance to look at other people's components and what they require for state saving. Please let me know your thoughts and requirements where not saving state would cause problems for your components.
Truthfully, I see some issues with this approach, but they aren't without their own work arounds...
At this point, I would like to show you some of the JSP pages we have in our application, but I'm sure there's a clause somewhere in my contract that says otherwise.
Over the long term maintenance and feature-adds on large web applications, your JSP pages can start to look like variable soup. You have 10 to 15 variables being accessed that may have come from any scope, set by any action, somewhere in the process of using that site. Maybe that variable came from a filter somewhere?
Eventually things can become difficult to keep track of. With traditional MVC2-- Struts and WebWork, we are able to tie the request scope back to some semblance of an action. But as we move into rich component UIs, where the lines between URL and scope are blurred, what can a developer do to bring some variable continuity and identity into large applications?
One way you can provide scope over your variables is to use stronger grained references. This means that you possible introduce the concept of a page bean, where all variables you need are located. Here's an example:
Some developers encourage providing scope prefixing in general across their pages, such as requestScope or sessionScope. This becomes very easy to simply ignore when you are dealing with robust variable resolution within the EL-API. The EL-API and it's concept of a CompositeELResolver means you can pretty much pull variables from anywhere you like. Now marry that with a component framework like JSF, and you might be walking into a maintenance nightmare.
What would be nice is if with each of the ELResolvers or VariableResolvers used within JSF, that the developers would provide a scope variable. So a Spring VariableResolver would provide a springScope reserved variable so anyone looking at the pages would know where those variables are coming from-- Spring's configuration xmls.
The next step would be to provide semantic scopes that are meaningful to your domain model. This way you can create and use scopes like orderScope or addLineItem scopes. These scopes would be managed in relation to your business logic and can provide more maintainable grainularity to variables used in your view. Essentially it would be like creating a Bean with all of the member variables you need. Really, the issue becomes more about being able to assert inherent lifecycles around known business processes.
Does anyone else experience this tracability issue with the 'global variable' phenomenon within large web applications? Does anyone have any suggestions on how to make variables in the view more maintainable?
In my last blog entry, I 'kind of' complained about how JSF's component model was maintained and all the overhead involved. Really, I can't think of it as overhead, because it is tremendously richer in what it can do than other component frameworks.
With JSF, each component has control over each step in the request cycle. But this is only half true. When I started to look at ways to efficiently handle partial component tree requests, there really isn't any way for components to also have control over other component's lifecycles. Example, an autocomplete component that wants to be refreshed, but not require the rest of the tree to be processed.
Currently, the JEE blueprints suggest alternate servlets or phaselisteners that deliver 'xml model' data back to the page over AJAX for further processing before rendering. MS's Atlas does the same kind of processing and the only thing I can say is, "Why??"
What if there was a way to simply 'refresh' components without requiring any translation or behavioral injection outside of the component itself? So JSF would be able to selectively update and re-draw the one autocomplete component instead of the whole tree. No phaselisteners, no alternate response renderers, no need to have knowledge of AJAX-- just redraw yourself. Sounds very swing-ish?
Well, I originally started development on a solution under Facelets called, "Avatar" that would do this. But this ran into problems. As I stated before, JSF's components are so rich (that they are essentially black-boxes) and it's hard for a framework to externally dictate component processing (UIData for example). What JSF does right now is just walks the whole tree to allow each black-box component to do its thing. Again, this isn't very efficient for AJAX requests-- hence all of the solutions in JEE blueprints and online that require extra, unique cases.
Anyways, back to 'Avatar'-- the idea is to carry JSF's event handling over into the concept of ProcessingContexts. A ProcessingContext acts as a pointer to a branch or leaf in the component tree and exposes the same processXXXX methods as the UIComponent has.
Just like events are gained and broadcast through the component tree, a ViewHandler could ask the component tree for one or more ProcessingContexts by client id. So take that autocomplete component's ID, pass it up in an AJAX request, ask the component tree for a ProcessingContext for that single ID and just operate on that one. So basically, Everything in JSF operates as normal, just that the Root Component (UIViewRoot) now only operates on these ProcessingContext pointers instead of the whole tree (by default, the whole tree though). The end result is that UIComponents are request-type agnostic, allowing everything in JSF to suddenly be 'AJAX' capable with only a few small API changes (UIComponent, UIComponentBase, UIViewRoot).
// custom viewhandlerList pcs = ...; for(String clientId : clientIdList) { pcs.add(viewRoot.getProcessingContext(clientId); } CompositeProcessingContext cpc = new .... (pcs); viewRoot.setProcessingContext(cpc); // UIViewRoot public void processDecodes(FacesContext faces) { this.processingContext.processDecodes(faces); } // AutoCompleteComponent public void encodeBegin(FacesContext faces) { // no changes :-) }
Because this processing is delegated within UIViewRoot, everything else in JSF stays intact. You could even have components or Actions add additional components to render during the lifecycle to say, "When action X is fired, re-render components A and B on the screen." Again, the best part is that components wouldn't need to know/care about AJAX and they should all be able to continue to work in this alternate processing method. The whole component tree is still there, referenceable, just that we are selectively processing events.
More discussion would have to come up as to how we could standardize this secondary communication over AJAX, but this would could also work for things like XUL too! You could have a rich UI that is defined in a single page (or with Facelet templates) that never needs to be fully refreshed. Now the overhead from JSF's component model doesn't sound bad at all, and actually quite useful! I was wrong, JSF is [near] perfect :-)
I would like to get a mod-ed version of JSF 1.2 prototype working, but again, this requires an official spec enhancement-- how about it? JSF 1.2a for Avatar?
I setup some initial unit tests for a medium sized page with lots of static text and a couple data tables, displaying 40 developers in two, separate spots. My example is automatically updating the DB when a single field in the column loses focus, so rendering one component back in the AJAX response. Some of my initial results where:
Now, was it fair for me to use such a large document? Nope, but it helps to emphasize my point! The same document was processed in both cases, but since we only wanted one part of it actually updated back to the client (or visa versa), there was a much smaller request to be processed under the SAME lifecycle. No special phaselisteners, or separate documents or servlets-- again, there's only one document being used with the same components as everyone uses from the JSF API (h:dataTable, h:inputText, h:panelGrid, etc).
In relation to Facelets, this isn't a Facelets specific solution. In my own tests, tree building requirements are nothing (<< 1 ms) compared to the rendering time. I don't see this cost being any different with JSF 1.2 and JSP 2.1.
I've been racking my brain lately, tossing around ideas. I've been working tons with Facelets technology with trying to push JSF into new directions, but it still sits on top of JSF. Not that there's anything wrong with what JSF does, it's really rich, almost too rich.
JSF really 'gets' the concept of a component. It allows you to mingle components and accessory concerns such as listeners, validators, and converters within the same document. Great. But...
As a carry over from JSP, you place JSF in a non-declarative environment, which means that if you are using JSP, then you must handle the fact that there could be predicate logic that may or may not include some component or some action listener for a given page evaluation (JSTL or custom tags). JSF gets around this by capturing the component models state and either storing it in the session or serializing over your precious bandwidth.
Tapestry seems to handle things slightly different such that anything that should be declarative, is, and externalized into a separate document. Correct me if I'm wrong, but Tapestry basically says that I don't want to have to worry about capturing uneccessary state for declarative artifacts, so I'm not going to put them into the 'view' where imperative logic is present. It does clean things up logically, but somewhat scatters UI concerns into multiple places. The benefit of JSF in this case is that everything can be expressed in the same document and collaborate with almost any other logic. So which is better? I don't have an opinion either way, both of them have their strengths.
Let me present the use case that has been pushing this reflection. You want to iterate over 50 products, but use AJAX to refresh only one of the products in the page. With JSF, the product iteration is a transient process-- your JSP model is different than the rendered HTML markup basically. So there's no efficient way to selectively evaluate only one product without reproducing the iterative process. Because of imperative semantics that JSF accomodates, you can only re-evaluate the component model as a whole in attempt to capture that tiny bit of state you wanted to refresh.
A really good example of my point is lets say that you are using Struts. When I request, 'product.do?id=333343&view=detail', it's a simple, straight Map look up to find the associated stateless action and process those parameters. Now lets apply this to JSF. Your struts-config now allows predicate logic like c:if's or c:forEaches around your action-mappings. In addition, each Action can provide logic in selection. Now, how easy is it to translate that URI to the correct Action and guarantee it's evaluated correctly? Think about it. That's what JSF and these rich component models have to deal with in managing all of that imperative overhead.
I guess I can't completely blame imperative logic poisoning declarative component models, because there's enough trouble as is translating component 'trees' over HTTP's 'flat' request string. JSF does a lot with rendering id's and names to translate those unique id's back to the component tree during evaulation.
Well, what if you were to take id management to the next step? Imagine if you were to write a truely stateless/declarative compiler, such that id management is built where given a unique id, you can 'reach into' the compiled page and selectively choose components to evaluate. Basically what you are doing by staying strictly declarative in your component models is that your framework can start to draw presumptions and inference behavior/state that doesn't need to be preserved in the way that JSF does.
Like I said before, JSF is really rich with what you can do. But it's that richness and all the possibilities it provides will also create overhead. Reading about the principles behind REST, there's a lot of genuine truths there that make me think that Struts/WebWork are partially right with being able to handle pure URI navigation. In the process, that purity allows them to inference a lot of things and produce lighter weight/stateless artifacts. There really isn't much room for that in the JSF API, but it does a really nice job of handling the fact that it can't really presume anything from its developers.
Ruby on Rails: love it or hate it, but it does have a lot of fresh ideas.
One of the really great things that RoR has done is presented AJAX functionality in an easy to use API. John Reynolds provided a nice list of AJAX/JavaScript sites in one of his last blog entries, one of which was script.aculo.us. The site includes RoR AJAX examples with source code. While light weight, I was suprised to see that much of the grunt work in some of that functionality was delegated to another freely available JavaScript library, called Prototype. So what RoR is able to do is just generate a couple method calls to Prototype's excellent AJAX API to make requests to other pages. Hmm. Don't you think a developer could do the same with a JSP tag or a Struts action without much effort at all?
I started asking around to see if JSF had any of that functionality in relation to components and AJAX. The idea of refreshing any component on the page. By clicking a button or pressing a key, it will go out and auto complete or change/valdidate text on the fly auto-magically. It seems do-able, but how come no one's done it yet? Well, Oracle did do it and I am really impressed with what they call 'partial-page rendering' or PPR within their ADF JSF Component Framework.
<af:commandButton action="#{bean.method}" partialSubmit="true"/><af:inputText valueChangeListener="#{bean.doRefresh}" autoSubmit="true"/><af:commandButton text="Refresh Some Things" partialSubmit="true" id="refresh"/>
<af:outputText value="#{oneValue}" partialTriggers="refresh"/>
<af:outputText value="#{anotherValue}" partialTriggers="refresh otherRefresh"/>There's a lot more functionality within the ADF framework and their releases have deployable wars that show off all this. They also came out of the gates with Facelets support for their EA19 release a couple weeks back, so you would be able to use ADF along side all of those templating features from Facelets.
While JSF doesn't have the components yet to provide the visual candy that RoR has in demonstration, from a practical application standpoint, Oracle's ADF Component framework is a already there. One thing to take note is that Oracle's ADF library didn't have to delegate rendering to separate page as in some of the RoR demos at script.aculo.us. ADF really blows away the traditional request/response constraints that web developers are so familiar with while being able to provide a richer experience for users.
What I would like to explore is enhancing the concept of PPR within Facelets' stateless architecture. I think there's a lot of opportunity there to really blur the lines between a page and a component within the JSF architecture as a whole.
I just got back from a trip out to Boston. Being away from my home and cappuccino maker, I found myself standing in line at Starbucks far too many times-- listening to all kinds of orders for 'coffee'.
One could compare the JavaServer Faces framework to a chain like Starbucks. Starbucks offers a multitude of choices under a packaged 'brand'. You have those that know exactly what they want and will order things like a 'grande, low-fat, sugar-free hazel nut latte with skim milk' and you have those that will simply ask for a 'medium coffee' . You know who you are.
What does this mean for the application developer? Everyone wants the same thing-- an application. For some, they will want to wire JSF into various controller frameworks and bean containers, with a dash of in-house components. Others might just opt to use an IDE like Studio Creator to easily drag and drop an application together. Both types of developers can get what they want under the same packaged 'brand' with JSF.
You have your baristas, like Oracle or Apache, who are masters at brewing up rich-- components. And there are those of you who like to always add a little something of your own to your morning brew (you know that flask in the bottom left drawer of your desk).
JavaServer Faces, like Starbucks, hope to cater to everyone on different levels; the guy that needs to reherse his five-part order and the guy that just wants 'coffee'. I hear people grumble and recall the days when you could just order a 'medium coffee'. JSF's stack is a vibrant echo of that point. Go ahead and order your 'medium coffee'-- it's as easy as it's ever been. For those of you have tuned your tastebuds to something a little more rich-- JSF will do wonders for your palette.
I was a JavaOne virgin; I didn't know what to expect. I had been contributing to the JavaServer Faces specification and the reference implementation for quite some time, but was looking forward to finally meeting everyone involved in person. Tell you what, the folks from Sun are some of the nicest people I've ever met professionally.
I made a point to try to make it to sessions that I felt would most apply to my job (including JBI), but often times I ended up wandering over to the web framework presentations. It's no wonder why they spark so much interest and debate as it's the keystone to your application's stack-- where everything is finally orchestrated and labeled as a finished product.
I'm probably digressing a bit, because I would like to talk about JavaServer Faces and how it's evolving. I was really dissapointed to read David Geary's blog, where he mentions being a contributing expert on the original JSF specification, and in the same entry put JSF off as overly vendor oriented as if the framework didn't 'get it right'. I think his blog failed to mention all the opportunity within JSF (although he wrote he would blog more on the topic). Thousands of people attended JavaServer Faces-related presentations at JavaOne and the reason is the potential that the platform provides. AJAX (sorry Dan), alternate view technologies, toolability, controller options such as Shale or Spring MVC, and specialized components just to name a few.
I keep on referring to JavaServer Faces as a platform. Anyone that attened Kito Mann's BOF at JavaOne, the guy went on for an hour with all of the options and additions that you can use with JSF. People compare JSF to Tapestry, Ruby on Rails, Spring, and Struts, but the clear point for everyone is that the JSF platform could use any of the aforementioned technologies or replicate their capabilities.
I gave a presentation last June in Minneapolis on the web tier alignment (which I will get to ;-)), but I emphasised the possiblities that developers could take and run with. Right now you could tie in Spring on numerous levels within JSF, you could easily develop EJB3-backed components to give you Ruby on Rails 'scaffolding' functionality, you can integrate Shale into your development for extended controller functionality, or you could start using JSF with frameworks like Facelets for Tapestry-like features.
One of the major events to occur for JEE 5, was the web-tier alignment between JSP, EL, and JSF. Some of the features to come from this alignment are:
Where do you go from here? Well there's a couple options available to you depending on your needs as a developer and your project deadlines:
|
|