Differences between revisions 1 and 2
Revision 1 as of 2005-03-22 05:48:35
Size: 24500
Editor: anonymous
Comment: missing edit-log entry for this revision
Revision 2 as of 2009-09-20 23:12:29
Size: 24500
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 84: Line 84:
implementation -- the ["J2EE"] RI -- which (for the servlet and JSP specs) implementation -- the [[J2EE]] RI -- which (for the servlet and JSP specs)
Line 89: Line 89:
source and closed source implementations -- in fact, every ["J2EE"] app server source and closed source implementations -- in fact, every [[J2EE]] app server
Line 91: Line 91:
overall ["J2EE"] requirements. Some incorporate pieces of Tomcat; some write overall [[J2EE]] requirements. Some incorporate pieces of Tomcat; some write

For a good article on integrating Struts, JSF, and Tiles see the following:   http://www-106.ibm.com/developerworks/library/j-integrate/ 

[From a DEV list posting by Craig { { { McClanahan } } }, 06 Jun 2003]

From watching a wide variety of conversations floating arount the 'net, it seems [many people don't understand a few things about Java software and licensing.] Here's a few thoughts that should help illuminate the situation. This is a pretty short summary -- more detailed information can be gathered from the Java Community Process web site:

  http://jcp.org 

The most important thing to understand is the difference between the licenses for Java specifications (i.e. the functionality that any product claiming to be complaint must provide) and implementations of those specifications.

Java Specifications are created under the auspices of the Java Community Process (JCP), and you can keep track of progress at at http://jcp.org . { { { JavaServer } } } Faces, in particular, is being developed under JSR-127. When a JSR is originally proposed, the proposer (Sun, in the case of JSR-127) must also provide the proposed business terms that they anticipate the specification will be licensed under, once it is complete. It is, and has always been Sun's intention, that the terms for JSR-127 would be substantially similar to the terms that resulted from the discussions with Apache last year -- indeed, you will probably remember substantial discussions last year between Apache (and others) and Sun to address the licensing issues for Java technology, particular with respect to open source implementations.

Jakarta Web Site Info About The Agreement:

  http://jakarta.apache.org/news/jspa-agreement.html 

Sun's Letter Of Intent:

  http://jcp.org/aboutJava/communityprocess/announce/LetterofIntent.html 

The upshot of this is that, over a year ago, Sun agreed to modify the license terms for many JSRs, and included funding scholarships for non profit open source organizations that wish to prove their implementations are compatible with the specification. { { { JavaServer } } } Faces (JSR-127) is specifically listed as one of the Sun-led JSRs which would have business terms that support the ability for open source organizations to create an implementation that is compatible.

Now, remember -- a specification is not software -- it is a bunch of requirements that any software wanting to say that it "implements { { { JavaServer } } } Faces" must adhere to. So, how does anyone know that a Java specification can actually, in fact, be implemented in a way that meets all the specification requirements? And, how can you tell if any specific implementation does, in fact, meet the requirements?

The JCP process requires that the specification lead (again, Sun, in this particular case) must also supply a Reference Implementation (RI), to prove that one can actually create a compliant implementation, and a Technology Compatibility Kit (TCK) that can be used to test the compliance of any implementation. Currently, the RI that Sun offers for { { { JavaServer } } } Faces is available under an "early access" license (since the spec isn't final, no redistribution is allowed -- did you notice that the struts-faces distribution doesn't include the jsf-api.jar and jsf-ri.jar classes? this is why -- I don't get to break the rules even though I'm co-spec lead, and am heavily involved in the RI implementation and testing :-). How the RI is licensed is pretty much up to the spec lead and the expert group.

Note, however, that the RI is very unlikely to be the only implementation of { { { JavaServer } } } Faces that ever exists. In fact, because of the Apache agreement, it's perfectly feasible for any open source group to decide that they want to create an open source implementation of { { { JavaServer } } } Faces, and pass the TCKs so that you can prove it. Sun will even offer assistance to qualified non-profit organizations that wish to attempt this. I know of at least one open source implementation effort that was started over at { { { SourceForge } } }; there's no restriction on how many implementations there are in the world.

This is exactly analogous to the way that the world is with servlet and JSP. For example, the Servlet 2.3 (and JSP 1.2) specifications were created under JSR-53 in the JCP process. (For the next round, Servlet 2.4 is being developed in JSR-154, and JSP 2.0 is being developed in JSR-152). Sun was and is the spec lead of these specs, and provides a reference implementation -- the J2EE RI -- which (for the servlet and JSP specs) happens to incorporate code that comes from Tomcat.

But, is Tomcat the only implementation of the Servlet and JSP specs in the world? Not by any stretch of the imagination. There are multiple open source and closed source implementations -- in fact, every J2EE app server needs to provide an implementation of these APIs in order to meet the overall J2EE requirements. Some incorporate pieces of Tomcat; some write their own; some incorporate third party code from other suppliers). But all of those implementations need to pass the TCKs in order to claim that they are actually implementations of the corresponding specs.

In short, there is no such thing as "open sourcing" the { { { JavaServer } } } Faces specification itself, because it's not software. There is absolutely an ability for multiple implementations to be created (open source or not doesn't matter -- compliance matters). Or, if you don't believe that { { { JavaServer } } } Faces is the right answer to the "web application user interface components" technology problem, then you can go implement your own APIs and your own framework -- that's fine, and in that case nothing about { { { JavaServer } } } Faces need concern you (except for the fact that more than a few software producers do seem to care about it, so your cool widget library is going to have some serious competition :-).

A couple of points about the Struts-Faces interface library in particular might also be of interest.

  • If you take a glance at the build.xml file (contrib/struts-faces/build.xml), you will note that the RI classes are not in the compile time classpath. Only the API classes are included. That means this library will work portably on any implementation of the { { { JavaServer } } } Faces APIs, in the same way that it compiles against a servlet.jar from anywhere and has no dependence on Tomcat or any other container. As soon as there are other implementations of { { { JavaServer } } } Faces around, this library will work just fine (as long as they implement { { { JavaServer } } } Faces correctly :-).

  • You will also note that the jsf-api.jar and jsf-ri.jar classes are not included in the distribution. As I mentioned above, the EA license prohibits redistribution (because it's not final yet), and that rule applies to me just like it does to everybody else.
  • One of the reasons that Struts has become popular is that people seem pretty confident that their investment in learning and using the technology will be protected for long enough to earn back the investment cost. For Struts, one of the things I felt strongly about doing was ensuring that Struts could interoperate with the latest emerging technologies like JSTL and { { { JavaServer } } } Faces. Indeed, I proved (by doing it) that you could migrate an existing Struts app, one page at a time, to use { { { JavaServer } } } Faces and JSTL tags (instead of the corresponding Struts tags), with nearly zero changes to the back end business logic. MVC really works -- what a concept :-).

  • The lesson I learned from this, and that everyone else should to, is that your investment in existing applications based on Struts is in very good hands -- you are not going to be forced to migrate away from it any time soon in order to take advantage of the latest and greatest Java technologies.
  • An additional lesson, though, is for the Struts developers ourselves. We were one of the pioneers in the webapp framework space, and have arguably been the most successful. But we were not alone. Indeed, my spreadsheet of various implementations of UI component and web app framework architectures (just the ones in Java) has roughtly fifty entries in it. That's way too many for tools to support; it's way too many for potential users to evaluate; it's way too confusing to the market; and it's way too weak for Java as a whole in the face of a determined competitor who feels threatened by the success of Java technologies at every turn.
  • Every technology goes through a lifecycle of innovation, followed by popularization, followed (often, but quite often in the Java world) by standardization, followed by commoditization. We're rapidly approaching the standardization point in the webapp UI component space -- and it's become abundantly clear to me how many serious players in the world have been waiting for this, so that they can build products and packages and libraries and tools on top of a standard (instead of each trying to pitch their own APIs).
  • Once there are robust, mature, implementations of a final 1.0 version of { { { JavaServer } } } Faces (and I know for a fact that there will be more than one), it's decision time for application developers who are currently using what will then become "non-standard" approaches to that API. For Struts users, I have the following recommendations:

    • For your existing apps, and projects currently in development, continuing to use the Struts HTML tag library is a sensible decision. However, I'd still recommend using JSTL tags instead of their Struts counterparts (Struts offers an integration library for JSTL tag usage too :-).
    • If your app deployment plans are further off, and/or you haven't started picking your base technologies yet, I would suggest that using the current Struts HTML tags is not a very good idea. You will be much better off investigating using { { { JavaServer } } } Faces component libraries instead -- not only are they much more powerful than the Struts tags, you'll be able to use component libraries from anyone, just as you can integrate JSP custom tag libraries from anyone today.

As for whether { { { JavaServer } } } Faces is good or bad technology ... I'm willing to let the market answer that question. :-). But I can guarantee you that there are already millions and millions of client devices that can already utilize { { { JavaServer } } } Faces based applications, versus hundreds? thousands? that can use cool things like XForms or XUL today.

Of course, even that comment oversimplifies things a little too much, because it leaves the impression that { { { JavaServer } } } Faces is just for HTML based browsers. That's not the case at all -- if you're at { { { JavaOne } } }, you'll enjoy seeing an SVG based rendering of the same application (with zero changes to the back end logic). Creating renderkits for wireless devices (or even rendering XUL and XForms if you like -- there's a small sample XUL renderkit in the "demos" directory).

I can tell you one thing, though ... working on { { { JavaServer } } } Faces has already had very positive impacts on my professional career. :-)


[From a USER list posting by Craig { { { McClanahan } } }, 16 Sep 2003]

{{{ >> Reading through Sun's Web Services Tutorial section on JSF, things are

  • >> starting to come into focus: JSF provides functionality that overlaps that >> of Struts (my misconception was that JSF was strictly a UI component tag >> library). }}}

Yep ... there's quite a bit of overlap, and { { { JavaServer } } } Faces is FAR more than "a component tag library".

{{{ >> .: Anyone know of a resource that summarizes/contrasts solutions provided by

  • >> both frameworks? }}}

I'll throw in a few short comments below, but caution you that this is based on the EA4 release of { { { JavaServer } } } Faces. Things are still evolving rapidly. (My comments ought to have at least a little relevance, because I'm both the original author of Struts and the co-spec-lead for { { { JavaServer } } } Faces .

  >>     -UI Components 

Struts doesn't really have any notion of components at all (the closest thing is properties of a form bean), while { { { JavaServer } } } Faces has a fairly rich component model that is accessible at both the Java and JSP levels (JSP is not required), supports a separate rendering model (so you can render something like a "select one" control as either a set of radio buttons or a <select> element with one simple change) and is not tied to HTML -- although the default render kit included will be HTML specific. Out of the box, you'll get complex components like a grid and an editable table, and there are already demonstration components for things like trees and menus that (in a Struts world) require additional add-on tag libraries.

For people who have existing Struts expertise and/or applications, this is the key value add of integrating { { { JavaServer } } } Faces -- you can use the fancy UI component model without having to change your back-end form beans or actions.

  >>     -controller components 

This is where Struts shines, and I assume you're familiar with that. { { { JavaServer } } } Faces uses a somewhat different abstraction for navigation, and defers the decision of what page to display next to a { { { NavigationHandler } } } that is configured with a set of rules -- the next page is determined by matching rules for:

  • The page that is currently being displayed
  • Which Action was invoked (for example, you can have multiple submit buttons on the page that do different things)
  • Which logical "outcome" was returned by the Action that was invoked -- sort of like how Struts actions return an { { { ActionForward } } }.

{ { { JavaServer } } } Faces is more flexible in how you organize your processing logic -- you can maintain a Struts-like model of separate "form beans" and "action classes", or you can combine them together (somewhat like how code-behind pages work in ASP.Net).

Struts has a couple of framework features (Tiles and the Validator Framework) that are beyond the current scope of { { { JavaServer } } } Faces -- but one advantage of the integration library is that you'll be able to use these sorts of technologies together.

>> -model components

Being presentation frameworks, both technologies are mostly focused on the view and controller. The important part becomes how the presentation tier and model tier object communicate values:

  • With Struts, you can use property expressions to navigate down a bean hierarchy -- something like:

  <bean:write name="customer" property="address.city"/> 

  • With { { { JavaServer } } } Faces, this is done with "value reference expressions" that use the same syntax as JSTL EL expressions. The equivalent tag to output a bean property would be:

  <h:output_text valueRef="customer.address.city"/>: 

  • In both technologies, it's possible to evaluate expressions like this programmatically in your Java code -- with Struts, you use the commons-beanutils package; with { { { JavaServer } } } Faces, you use the { { { ValueBinding } } } API.

  • With Struts, the framework will automatically create form bean instances for you if you want. If you're using { { { DynaActionForms } } }, you can also preconfigure the properties of the created form bean using the "initial" attribute.

  • With { { { JavaServer } } } Faces, this concept is extended to support creation of any model tier bean (in any scope), complete with configuring the initial properties, using the Managed Bean Creation facility. In the example above, I can configure things such that if the "customer" object does not already exist, a new instance of a configured class will automatically be created, and have its property values also configured based on settings in faces-config.xml.

  >>     -Page Flow 

Neither technology has direct support for page flows. There are add-ons for Struts already; I have no doubt that such things will emerge for { { { JavaServer } } } Faces as well.

  >>     -etc. 

Because Struts is a fairly popular technology, you'll find quite a lot of support for it in development tools. I expect to see the same sort of thing happen for { { { JavaServer } } } Faces; indeed, at { { { JavaOne } } } this year both Sun and Oracle did keynote previews of their upcoming development tools that will be based on { { { JavaServer } } } Faces, and lots of other providers have promised support for it as well.


[From a Struts USER list posting, 17 Sep 2003]

{{{ >> I remember a while ago in one of these architecture- theme emails you

  • >> discussed the OO nature of struts & it had been said that the >> action-form class and the action class broke the OO encapsulation >> principle, by having data in one and functionality in another. You said >> if you were going to design struts again, you would probably address this. >> >> Does JSFaces bring these two closer together? Or is this an area where >> Faces is not involved? I see you say that in a combination of struts & >> Faces, you would still use actions and forms. >> }}}

{ { { JavaServer } } } Faces is designed to give you options to organize things either way. Here's one example of a logon form (and associated back-end logic) that combines the Struts notions of { { { ActionForm } } } and Action into a single class (corresponds to the syntax in the EA4 release):

JSP PAGE (/logon.jsp)

{{{ ...

  • <h:form>

    • <h:output_errors/> <h:panel_grid columns="2">

      • <h:output_text value="Username:"/> <h:input_text id="username" valueRef="logonForm.username"/> <h:output_text value="Password:"/> <h:input_secret id="password" valueRef="logonForm.password"/> <h:command_button label="Log On" type="submit"

        • actionRef="logonForm.logon"/>

        <h:command_button label="Reset" type="reset"/>

      </h:panel_grid>

    </h:form>

  • .. }}}

FACES CONFIGURATION FILE (faces-config.xml)

{{{ ...

  • <managed-bean>

    • <managed-bean-name>logonForm</managed-bean-name> <managed-bean-class>mypackage.{ { { MyLogonForm } } }</managed-bean-class> <managed-bean-scope>request</managed-bean-scope>

    </managed-bean>

  • ..

    <navigation-rule>

    • <from-tree-id>/logon.jsp</from-tree-id> <navigation-case>

      • <from-outcome>success</from-outcome> <to-tree-id>/mainmenu.jsp</to-tree-id>

      </navigation-case>

    </navigation-rule>

  • .. }}}

BACKING CLASS

{{{ package mypackage;

  • public class { { { MyLogonForm } } } { // No required base class or interface

    • // Property for "username" field private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } // Property for "password" field private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } // Return an Action for processing a logon public Action getLogon() {
      • return new Action() {
        • public String invoke() {
          • return logon();
          }
        }
      } // The actual logon processing logic private String logon() {
      • DAO dao = ...; // Data Access Object for user database User user = dao.findUser(this.username);

        if ((user != null) && password.equals(user.getPassword())) {

        • .. record successful logon ... // Return logical outcome denoting success return ("success");
        } else {
        • // Add an error message

          { { { FacesContext } } }.{ { { getCurrentInstance } } }().addMessage(...); // Return logical outcome denoting "redisplay this page" return (null);

        }
      }
    } }}}

In this scenario, you can see that the form field values are stored in the same bean as the processing logic. Therefore, the processing logic can just use the field values directly (they are in the instance variables). However, it's only in the same class because the page author used "logonForm" at the beginning of the valueRef and actionRef expressions -- they could just as easily have been stored in separate files.

A couple of things not real obvious from this simple example, but interesting nevertheless:

  • The <managed-bean> declaration causes a new instance of the specified class to be created in (in this case) request scope, if it is not there already, similar to the way that Struts creates form beans for you as needed. However, { { { JavaServer } } } Faces generalizes this to happen automatically whenever it evaluates a reference expression and the first element does not identify an existing attribute in some scope. This can be very handy for instantiating "service" or "processor" objects whose precise characteristics are defined in the configuration file, rather than being coded in the page.

  • { { { JavaServer } } } Faces uses logical outcomes to manage navigation, similar to the way that Struts uses the returned { { { ActionForward } } } for this. The returned value is matched against a set of navigation rules that choose the next page to be displayed based on three criteria:

    • What page am I currently displaying? (Wildcard rules are allowed)
    • What action was performed? (You can have more than one submit button)
    • What logical outcome is returned?

If no rule matches, the current page is redisplayed. I've adopted the convention in my code to return null as the logical outcome if this is what I want (i.e. the logon failure case here).

  • Struts encourages you to use Strings for field values that might need conversion, in order to redisplay correctly in case of conversion errors. You don't need to worry about that with { { { JavaServer } } } Faces, because the redisplay is handled by the components themselves. You will generally use the native data types for your field properties.

  • Programmers used to ASP.NET are familiar with the ability to programmatically interact with the actual user interface components themselves in code-behind files. It's very likely that this approach will also be accomodated in the final version of { { { JavaServer } } } Faces.

The above example is likely to be typical if you're writing a new applicaton from scratch based on { { { JavaServer } } } Faces. But what if you've got an existing application based on Struts, and you just want to use { { { JavaServer } } } Faces to get the fancy UI widgets? That's where you would use the struts-faces integration library, because it lets you change just the JSP pages, and keep all your back end actions and form beans from before.

{{{ >> The reason I ask is that I just had a hard time redesigning a page

  • >> because my initial design failed. The page allows an edit of one parent >> object, while showing a list of its child objects with >> move-to-new-parent / delete controls. I got in a mess initially over >> whether to use the parent or child's form and action for the child >> operations. >> }}}

In Struts, I would tend to model this sort of thing as a single form rather than two different forms.

In { { { JavaServer } } } Faces, there will be a nice "editable table" or "data grid" type component that supports this type of use case.

{{{ >> Fortunately I solved it nicely by nesting the child objects in the

  • >> parent form, and passing the whole lot to the parent's model, which then >> worked out if it needed to call the child's model for any operations. >> }}}

Makes sense.

  >> 
  >> Adam 
  >> 

Craig


To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org For additional commands, e-mail: struts-user-help@jakarta.apache.org

StrutsMoreAboutJSF (last edited 2009-09-20 23:12:29 by localhost)