April 12, 2008

Google Guice and Apache MyFaces 1.2.x

With the advent of Apache MyFaces 1.2.2 it is possible to use Google Guice for managing your backing beans dependencies (see MYFACES-1747).

Dennis blogged about it already before he actually went ahead and created an ELResolver for MyFaces. His solution still needs some work:

  • register the GuiceResolver in your project’s faces-config.xml file
  • create a ServletContextListener to have your modules available

The approach in the is OK so far, but you need to rewrite the Listener for every project. The good news is, that when you use Java6, you can use ServiceLoader class to load the Guice modules (see here as well). So… we could use a more generic ServletContextListener for the “guice support”.


/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package net.wessendorf.jsf.guice;

import java.util.ServiceLoader;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.myfaces.el.unified.resolver.GuiceResolver;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;

/**
* <b>This class requires Java6</b><br/>
* <p/>A <code>ServletContextListener</code> to use MyFaces 1.2.2's <code>GuiceResolver</code>.
*
* <p/>Put your custom Guice Modules to <code>WEB-INF/services/com.google.inject.Module</code>.
*
* @author Dennis Byrne
* @author Matthias Wessendorf
*
*/
public class GuiceServletContextListener implements ServletContextListener
{
public void contextInitialized(ServletContextEvent event)
{
ServletContext ctx = event.getServletContext();
ServiceLoader<Module> modules = ServiceLoader.load(com.google.inject.Module.class);
Injector injector = Guice.createInjector(modules);
ctx.setAttribute(GuiceResolver.KEY, injector);
}

public void contextDestroyed(ServletContextEvent event)
{
ServletContext ctx = event.getServletContext();
ctx.removeAttribute(GuiceResolver.KEY);
}
}

I think I’ll put that class to a SVN folder soon (perhaps the new commons MyFaces module). But so far… you can already enjoy it!

BTW. in Trinidad we have a similar facility like ServiceLoader, once that is factored out to a util, I guess we can make the listener part of MyFaces Core.

March 28, 2008

New Facesgoodies download

Today I added a new download for my little Facesgoodies project. This kickstart template is JSF 1.1 based and contains the latest greates Trinidad release (1.0.7) and some more things, such as Facelet components, based on Dojo Toolkit, which I demonstrated at AjaxWorld New York. On the business layer I did no modification, I am still happy with Orchestra 1.1 :-)

This extra download is just for convenience, since some told me they want an extra download instead of getting the stuff via SVN.

Hope that helps!

March 26, 2008

AjaxWorld East 2008 (in New York City)

Last week I was attending the AjaxWorld East conference to speak about Apache MyFaces Trinidad and how to integrate it with some other open source projects, such as Facelets, Dojo or Yahoo! UI. I think the talk went very well and I uploaded the slides today. The demo is not downloadable (yet), but you can get the source (via SVN). Simple do a checkout of my Facesgoodies project and you’ll get everything that I was demonstrating in NYC.

Have fun

March 14, 2008

Steve Bug playing in New York

Ha! Doing some “researches” for my tomorrow trip to New York (b/c of AjaxWorld conference) I figured out that Steve Bug is playing on 20th of March in New York City (at Cielo).

I just printed the ticket! Since my plane is leaving kind of late afternoon on 21st I bet it will be a very good final of my trip to NYC 8-)

March 14, 2008

JSFDays 2008 in Vienna

The JSFDays conference was a very good conference! It was (to my opinion) perfectly organized! Credits to Martin, Thomas and team. The conference was really an international conference, since it had visitors from Europe (Austria, Germany, Netherlands and Switzerland) and from the US.

Very interesting sessions and good discussions afterwards and during the coffee/lunch breaks. Everywhere you heard words like “Seam”, “Orchestra” or “Facelets” from all the geeks ;-). Which is indeed a very good sign!

It is also very funny to mention, that Ed Burns is really good in speaking German! He obviously enjoyed talking German on the breaks and the evening events.

I am really really looking forward for the next JSFDays conference in Vienna!

March 11, 2008

Dynamic tables and Orchestra’s conversation scope

Very very often you have to have tables that display data based on a search result (like customers by city or similar). In one (or more) of the entries you are interested in continuing your work. In Trinidad you can use the inputListOfValues component to trigger a dialog, that contains the search engine:


<tr:inputListOfValues label="customer id"
   action="dialog:search" windowHeight="300"
windowWidth="400"/>

A click on the “search” icon (provided by the component) will launch a dialog, that contains the mentioned search engine. The search page may look like:


<tr:form defaultCommand="search">
  <tr:panelFormLayout>
    <tr:inputText label="Name:" value="#{search.query}" />
    <tr:commandButton id="search" text="Search..."
       action="#{search.search}"/>
  </tr:panelFormLayout>

  <tr:panelPage rendered="#{not empty search.result}" >
    <tr:table id="results" rowSelection="single"
        value="#{search.result}" var="customer">
      <tr:column>
        <f:facet name="header">
          <tr:outputText value="Name"/>
        </f:facet>
        <tr:outputText value="#{customer.name}"/>
      </tr:column>
      ...
    </tr:table>
    <tr:panelButtonBar>
      <tr:commandButton text="Cancel" immediate="true"
                        action="#{search.cancel}"/>
      <tr:commandButton text="Select"
                        action="#{search.select}"/>
    </tr:panelButtonBar>
  </tr:panelPage>
</tr:form>

The big problem here is the search bean. What scope to use for that bean?

Request scope?

Doesn’t work. When doing the query, you get a list of results (when query was successfully…) but next action (the selection of a customer) you’ll notice, that the underlying selection data (in Trinidad done with table.getSelectedRowKeys()) is not present.

Session scope?

Well… the selection now of course works, but when you launch the dialog again, the previews result is still visible… You can work around that by doing some (bogus) clean ups… well, are you really interested in doing that ?

The solution?

A scope that is between request and session and this is what MyFaces Orchestra provides with its Conversation Scope Features. Using such a scope simply gives you the clean solution that you want. No bogus clean-ups / workarounds are needed. Just declare the scope of the bean like:


<bean id="search"
    class="net.wessendorf...SearchController"
    scope="conversation.access"
    p:dao-ref="myDaoImpl" />

Now you are good to go! The SearchController bean is straight forward. No extra annotations, interfaces or abstracts classes are required. It just works! An other cool feature of Orchestra is the “ConversationBindingListener” interface. When you implement it, your bean get’s notified when it was added to the new scope (or removed). But this is totally optional.Even if you don’t need all bits of Orchestra at least I strongly recommend to use the new additional scopes since they really make the life of a web application developer more easy!

Well… I also have one rant… Orchestra shouldn’t have to offer such a extra scope. It should be part of the JavaEE specs. Not only for JSF this scope is useful. It should be part of the Servlet Spec. Perhaps Servlet 3.0 will address this ? But until that happens, Orchestra is a good friend!

Have fun!

February 29, 2008

Custom JSF components with Facelets

There are several reasons to use Facelets, like:

  • Problems in JSF 1.1 “Content Interweaving”
  • lightweight Templating Framwork (XHTML-based templates)
  • very friendly to designers (similar to Tapestry)
  • performance
  • JSF 1.2 w/o JavaEE 5 Container

Another is the very easy way of creating custom JSF components. In plain JSF you need these artifacts:

  • a lot of Java (Component, Renderer, JSP-Tag Class)
  • some XML (faces-config, TLD)

With Facelets, it is this:

  • XHTML file
  • Facelets Taglib XML file (very simple syntax)

With Facelets it is very easy to create sexy components, using 3rd party JavaScript libraries, such as Dojo Toolkit. The XHTML file contains all the markup want. The “taglib” is the glue code between the XHTML file and the user’s page, where a page author is using the (new) component.

The Dojo Toolkit contains lot of cool “components”, such as an accordion. It is not hard to make your layout (<div> elements) become a “AccordionContainer”, that contains several “AccordionPane” components, as the previews link shows. But every time reusing this, you repeat your self. So… you finally want a (jsf) component. Easy with Facelets.

All you need is two XHTML files (one for the container and one for the pane) and a little bit of XML to wire the two tags to the new components.

The container xhtml:


<div
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets">

  <link rel="stylesheet" type="text/css"
     href="dtk/dijit/themes/tundra/tundra.css" />
  <script type="text/javascript"
    src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
    djConfig="parseOnLoad: true"></script>
  <script type="text/javascript">
    dojo.require("dojo.parser");
    dojo.require("dijit.layout.AccordionContainer");
   </script>

    <div dojoType="dijit.layout.AccordionContainer"
         duration="#{duration}" style="#{style}">

     <ui:insert/>

    </div>
</div>

Simply import the required CSS and JavaScript files and make the <div> element a “AccordionContainer” by using the dojoType attribute. The value for the attributes duration and style is provided with a ValueExpression. The user of the accordionContainer tag has to specify the correct value. Inside the <div> element there is a <ui:insert />. This allows us to nest other content (such as the later described pane component) inside the accordion.The pane xhtml:


<div xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  dojoType="dijit.layout.AccordionPane"
  title="#{title}">

  <ui:insert/>

</div>

This one is very simple, just a <div> that is representing the AccordionPane and a <ui:insert/> to nest content. Please note that this “component” doesn’t need to import CSS or JavaScript files. Why? Because it is only used inside the accordion which is already loading the needed files.The XML for the “taglib”:


<facelet-taglib>
  <namespace>
    http://wessendorf.net/kickstart
  </namespace>
  <tag>
    <tag-name>accordionContainer</tag-name>
    <source>facelets/components/accordionContainer.xhtml</source>
  </tag>
  <tag>
    <tag-name>accordionPane</tag-name>
    <source>facelets/components/accordionPane.xhtml</source>
  </tag>
</facelet-taglib>

The taglib file is pretty trivial. It just contains a bunch of tags and points to the source code of the component, the location of the XHTML files.The finally result (the page, that uses these new components) looks like:


<mw:accordionContainer duration="250"
style="margin-right: 30px; width: 400px; height: 300px; overflow: hidden">
  <mw:accordionPane title="html content">
    <p>Hello</p>
  </mw:accordionPane>
  <mw:accordionPane title="some more html content">
    <ul>
      <li>hey!</li>
    </ul>
  </mw:accordionPane>
  <mw:accordionPane title="JSF component content">
    <tr:inputDate />
  </mw:accordionPane>
</mw:accordionContainer>

It is possible to mix content such as regular HTML or some other JSF components, like the <tr:inputDate> component from Trinidad.Very easy and straightforward to add to your project!I updated FacesGoodies to ship this example (only via SVN).

February 20, 2008

Extending Trinidad’s default renderers

Once in a while there is a question on the MyFaces user/dev list about how to extend the default rendering of the components, like decorating <tr:inputText /> (for instance).

It’s not hard, but it requires some steps, like creating renderer class(es) and registering these new renderers with the Trinidad renderkit. This demonstrates a very simple example on extending the <tr:inputText />. This tag has a attribute for short descriptions (shortDesc=”blah”), now imagine you need to decorate that inside the renderer, so that the page developer can’t change the extra text (for what ever reason…).

For that you need two Java classes (b/c of extending a <tr:inputXyz/> or <tr:selectXzy />). One is for extending the InputTextRenderer class, which is registered with the Trinidad internal RenderKit. The other one is kind of an internal renderer, that is used to render the component’s content.

The extension of the InputTextRenderer looks like this:


package net.wessendorf.trinidad;

import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.component.core.input.CoreInputText;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.FormInputRenderer;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.InputTextRenderer;

public class CustomInputTextRenderer extends InputTextRenderer
{
  public CustomInputTextRenderer()
  {
    super(CoreInputText.TYPE);
  } 

  protected CustomInputTextRenderer(FacesBean.Type type)
  {
    super(type);
  }

  @Override
  protected FormInputRenderer getFormInputRenderer()
  {
    return new CustomSimpleInputTextRenderer();
  }
}

In Trinidad the *layout* of the <tr:inputXyz/> is done by these renderers (those, that extend the InputLabelAndMessageRenderer class). The custom code isn’t really hard. It is only interesting to see how to create the internal renderer (CustomSimpleInputTextRenderer), which actually renders the content (which we want to decorate):


package net.wessendorf.trinidad;

import javax.faces.context.FacesContext;

import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.component.core.input.CoreInputText;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SimpleInputTextRenderer;

public class CustomSimpleInputTextRenderer extends SimpleInputTextRenderer
{
  public CustomSimpleInputTextRenderer()
  {
    this(CoreInputText.TYPE);
  }

  public CustomSimpleInputTextRenderer(FacesBean.Type type)
  {
    super(type);
  }
  @Override
  protected String getShortDesc(FacesBean bean)
  {
    return super.getShortDesc (bean) + " what ever you want to decorate";
  }
}

As you see this adds some (bogus) text to the short description of the component. That’s it from the java side. If you really want to change the entire rendering of the <tr:inputText /> your custom “content” renderer (CustomSimpleInputTextRenderer) could also override the protected encodeAllAsElement() method.The last step is to register the new renderer in your project’s faces-config.xml file:


...
<render-kit>
  <render-kit-id>
    org.apache.myfaces.trinidadinternal.core
  </render-kit-id>
  <renderer>
    <component-family>
      org.apache.myfaces.trinidad.Input
    </component-family>
    <renderer-type>
      org.apache.myfaces.trinidad.Text
    </renderer-type>
    <renderer-class>
      net.wessendorf.trinidad.CustomInputTextRenderer
    </renderer-class>
  </renderer>
</render-kit>
...

As you see, you register the CustomInputTextRenderer and not the renderer that renders the content (CustomSimpleInputTextRenderer).Now using the <tr:inputText> in your XHTML page will decorate the short description:


<tr:inputText label="Blah" shortDesc="foo bar" ... />

It is important to note, that these classes extend internal features of Trinidad. None of these classes is part of the Trinidad API. This means that anyone subclassing the renderers has to know their code can very well break any time they move to a newer version. Another example of extending a Trinidad renderer (for <tr:message/>), I posted here.

February 19, 2008

Internet Explorer 7 and blur (with input type=file)

Today I noticed an interesting issue with IE 7 and the blur event, when using the <input type=”file”> HTML widget. A friend called me to tell me that their web app is validating the form fields, when the user is pressing the native “Browse…” button. But only in IE 7 (well, I don’t have IE6 installed). Interesting…

A simple test case for that:


<form>
  <input id="file" type="file"
    onblur="alert('blur');"
    onchange="alert('file');" />
  <br/><br/>
  <button>Blah</button>
</form>

And indeed! In IE 7, the alert(’blur’) is visible, when you hit the “Browse…” button. FF works fine. Please note that the widget was not focused before. Very annoying…But, as almost always there is a way around that ;-) This little jQuery-based hack helps to get rid of it (in the particular use case…):


<script>
$(document).ready(function(){
 $("#file").removeAttr("onblur");
});
</script>

Not a clean generic solution, but I think it does its job…

I personally haven’t noticed this bug before, but I am sure it is “known” since ages ;-)

February 16, 2008

Using Dojo and Apache Trinidad

In Trinidad there is an ExtendedRenderKitService interface, which allows you to add JavaScript to be rendered during the following request, like:


ExtendedRenderKitService service =
  Service.getRenderKitService(facesContext,
    ExtendedRenderKitService.class);
service.addScript(facesContext, "alert('hello Trinidad');");

Once the rendering is complete, you will notice a simple alert() in your browser window.Having this feature in mind, you can “call” your custom JavaScript from the server. Well, the reality is that the implementation of the interfaces (the Trinidad renderkit) adds your JavaScript call to the (ajax) response. When processing a PPR request, the XHR response will look like:


<?xml version="1.0" ?>
  <?Tr-XHR-Response-Type ?>
  <content  action="/app/faces/ajax.xhtml">
  ...
  <script><![CDATA[alert('hello Trinidad');]]></script>
  </content>

As you see the JS is added to the very end of the response and the browser simple evaluates the added JavaScript. This ExtendedRenderKitService feature offers you the possibility to easily integrate 3rd party JavaScript libraries, such as Dojo Toolkit.Imagine that your application needs to give feedback, when you created/deleted something (like a user). Using the JavaScript alert() function is fine, but well, that really doesn’t look nice! Dojo has a great Dialog component to display a notification like “User ABC has been created!”.

On the server you need to do something like:


...
extendedRenderKitService.addScript(context,
  "showDialog('" +
    newUser.getSecondname() + ", "+
    newUser.getFirstname() +
  "');");
...

The required showDialog(…) JavaScript function could look like:


function showDialog(user)
{
  var dialog = new dijit.Dialog(
{id:"dialog1", title: "New User created!"});
  var dialogContent =
"Successfully created the user: \"" + user + "\"";
  dialog.setContent(dialogContent);
  dialog.show();
}

Once the response is rendered completely, you’ll notice something like:

dojodialog.png

This way enables an easy integration of nice 3rd party JavaScript. Today I updated FacesGoodies (in SVN only) to reflect this integration.

Have fun!