Home

News: Daniel Hinojosa wants replaceable managed beans in JSF

  1. Daniel Hinojosa has asked the JSF spec leads to allow custom managed beans for a given page in JSF, to allow developers to create sort of page hierarchy where different types of beans are passed to a given JSP page and rendered appropriately.
    I like JSF, but there are too many times where I violate the DRY (Don't redo yourself) principle. One such case is when using JSPs in JSF. The JSPs in JSF are too tightly coupled with the managed beans specified in the faces-config.xml. You must always explicitly set a bean into the JSP to be able to use it. If you want a page that is identical to one that you have just created, except that you want it to use a different bean, you can copy and paste your code into the identical page and then go back and set the bean so that it refers to an entirely different bean. But, in Object Oriented Programming, copy and paste can be a bad thing, and should always throw up a red flag.

    What do you think? One comment suggests the MyFaces "aliasBean" component; should JSF support this innately?
  2. If its implementation is framework-independent, the aliasBean tag should be enough.
  3. You can do that with Facelets and Templating with either MyFaces of JSF 1.2 RI.
    <!-- my template -->
    <html>#{animalBean.kingdom}</html>
    <!-- my page -->
    <ui:composition template="/template.xhtml">
      <ui:param name="animalBean" value="#{catBean}"/>
    </ui:composition>
  4. I should note that there's opportunity here to push the concept of a front controller within JSF to handle cases like this, his managed-page suggestion is interesting.
  5. You can make your managed bean resuable. We are using something like this.



    <managed-bean>
    <managed-bean-name>myResuableBean</managed-bean-name>
    <managed-bean-class>com.mycompany.test.myBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>

    And I use the same managed bean in different JSP Pages.
  6. You can make your managed bean resuable. We are using something like this.<managed-bean> <managed-bean-name>myResuableBean</managed-bean-name> <managed-bean-class>com.mycompany.test.myBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope></managed-bean>And I use the same managed bean in different JSP Pages.

    This is slightly off topic, but this is the same way I've done all of my playing around with JSF.

    What is "wrong" with this approach?
  7. I am not sure if I agree with Daniel's specific use case, but I think it would be very helpful to have page-specific configuration for managed beans. In particular, it would be nice if there were a way to ensure that a managed bean was loaded and initialized before the page was invoked.

    Here is my scenario. You have a view that needs to display data, so your managed bean needs to perform database operations, probably in your getters:

    public void getProduct() throws Exception {
      if (this.product == null) {
        this.product = // Load from database
      }
      return this.product;
    }

    As it stands now, any errors caused by failed database access will be thrown as you walk through your JSF binding expressions:

    {#ProductController.product.price}

    If the product fails to load, the getProduct() method fails and you get hideously ugly Expression Language error messages that completely munge the real cause.

    If there were mechanism to pre-load a bean when a page was invoked and pre-initialize your managed properties, you could load your data in the managed property setters instead:

    public void setProductId(Long id) throws Exception {
      // Load product using its id
    }

    Since all of this is happening before your view page is executing, you ought to be able to cleanly and generically catch any errors and report them in a simple manner, using an error-page mechanism similar to JSP:

    <managed-bean>
      <managed-bean-name>ProductController</managed-bean-name>
      <managed-bean-class>....ProductController</managed-bean-class>
      <managed-bean-scope>request</managed-bean-scope>
      <managed-property>
        <property-name>productId</property-name>
        <value>#{param.productId}</value>
      </managed-property>
      <load-before>showProduct.jsp</load-before>
      <error-page>
        <exception-type>java.sql.SQLException</exception-type>
        <location>databaseError.jsp</location>
      </error-page>
    </managed-bean>
  8. backing bean for view is only role of the managed bean. So, I do not think that introducing the new page-specific elements for the managed-bean is a right direction.
    Struts Shale framework has an idea of the view controller already implemented. Shale associate each view with managed bean automatically. If this bean implements the org.apache.shale.view.ViewController interface, the following method will be invoked (quote from the API DOC):

    init() - Called after this ViewController has been instantiated, and after all of the property setters specified above have been called, but before the JSF request processing lifecycle processing and events related to our corresponding view are executed.
    preprocess() - Called after the component tree has been restored (in Restore View phase), if the current request is a postback.
    prerender() - Called before the Render Response processing for this request is performed, whether or not this is a post back request.
    destroy() - Called after the JSF request processing lifecycle has been completed for the current request.

    --
    Sergey : jsfTutorials.net
  9. I think Daniel is thinking too small here. Yes, page reuse is an issue today and that is what he has focused on - this is something that Shale and Facelets and others are looking at addressing. However, the real thing for the EG to look at is reuse of whole processes (or flows, or dialogs or whatever you want to call them :-) ). You can apply similar parameterisation ideas to a sub-flow as a whole to make it reusable and recursive, and also include both navigation outcomes and process level state management. (as an intermediate state bucket between request and session). Of course the smallest flow you can have is a single page, so that neatly solves Daniel's gripe, whilst adding much more besides.
  10. I'd like to put a plug in for the official public issue tracker for the JSF EG. Anyone can file feature requests here!

    javaserverfaces-spec-public.dev.java.net

    Ed JSR-252 spe co lead.
  11. In particular, it would be nice if there were a way
    to ensure that a managed bean was loaded and initialized before
    the page was invoked.Here is my scenario. You have a view that needs to
    display data, so your managed bean needs to perform database operations,
    probably in your getters:

    There are a couple of ways to do this. Right now. In JSF 1.1, you
    could use an application scoped PhaseListener that has an awareness of
    the meaning of each viewId in your app. You could have this
    PhaseListener take action on the beforePhase of the
    PhaseId.RENDER_RESPONSE phase. When beforePhase happens, you could
    examine the viewId of the current UIViewRoot on the FacesContext and
    take action accordingly. Of course, this causes an undesirable coupling
    between the PhaseListener and your viewIds, but this can be mitigated
    somewhat.

    Another approach is to place a simple managed bean get at the top of
    the page that returns the empty string, something like this:

    <h:outputText value="#{lifecycleBean.start}" />

    This is something of a hack, but if you put this as the first thing
    in your f:view it's guaranteed to be evaluated before anything else in
    the page. You could then use the getStart() method to kick off any
    per-page initialization.

    On a related note, one thing I want to push for JSF 1.2 is the use of
    @PostConstruct and @PreDestroy annotations on managed beans. Any no
    argument managed bean method annotated with @PostConstruct will be
    called after the bean is instantiated, but before it is placed in
    service. Likewise, any no argument managed bean method annotated with
    @PreDestroy will be called before the bean goes out of scope. This
    isn't guaranteed to be in 1.2 yet, but I'm hoping it will be.

    Ed

    JSR-252 spec co lead.
  12. ... should JSF support this innately?

    Yes it should. In current JSF, tag
    <h:dataTable var="row" value="#{list}">
    makes alias "row" for the current element of "list". Why not introduce general alias tag.

    IMO, we need better parameterization in JSF/JSP in many areas:

    1. We have already discussed alias variables.

    2. Allow runtime expressions in all attribute values. For instance "id" and "for" attributes are static. If you want to put some JSF in a JSP fragment and use it many times, then static attributes make it impossible (even with alias variables). This is major limitation of using very nice JSP 2.0 tag files feature.

    3. Parameters in action methods.

    Nebojsa
  13. Daniel Hinojosa has asked the JSF spec leads to allow custom managed beans for a given page in JSF, to allow developers to create sort of page hierarchy where different types of beans are passed to a given JSP page and rendered appropriately.
    I like JSF, but there are too many times where I violate the DRY (Don't redo yourself) principle. One such case is when using JSPs in JSF. The JSPs in JSF are too tightly coupled with the managed beans specified in the faces-config.xml. You must always explicitly set a bean into the JSP to be able to use it. If you want a page that is identical to one that you have just created, except that you want it to use a different bean, you can copy and paste your code into the identical page and then go back and set the bean so that it refers to an entirely different bean. But, in Object Oriented Programming, copy and paste can be a bad thing, and should always throw up a red flag.
    What do you think? One comment suggests the MyFaces "aliasBean" component; should JSF support this innately?

    JSF promises a new vision for Java web developers. However, I have never used JSF for my web projects, but Struts, or my own frameworks in stead. You may wonder why? Simple... It could support developers better than the others only when there is a drag-n-drop development tool like ASP.NET, I think.