Schlagwörter: JSF Kommentarverlauf ein-/ausschalten | Tastaturkürzel

  • Andreas Höhmann 17:59 am Friday, 27. August 2010 Permalink |
    Tags: Checkbox, JSF, Renderer,   

    Fix for Tomahawk checkbox with disabled SelectItems 

    Today I will publish a little bugfix for tomahawk <t:checkbox/> issue  1436.

    I’m using tomahawk 1.1.7 the current development version is 1.1.9, the  issue „t:checkbox disregards disabled property“ is still unresolved.

    So here is the solution …

    I wrote my own HtmlCheckboxRenderer:

    /**
     * Fix for issue https://issues.apache.org/jira/browse/TOMAHAWK-1436.
     * The renderer should evaluate the "disabled" state for a each {@link SelectItem} too.
     */
    public class HtmlCheckboxRendererFix1436 extends HtmlCheckboxRenderer {
    
     @Override
     protected void renderSingleCheckbox(final FacesContext facesContext,
                                         final HtmlCheckbox checkbox) throws IOException {
       // copied from original
       final String forAttr = checkbox.getFor();
       if (forAttr == null) {
          throw new IllegalStateException("mandatory attribute 'for'");
       }
       final int index = checkbox.getIndex();
       if (index < 0) {
          throw new IllegalStateException("positive index must be given");
       }
       final UIComponent uiComponent = checkbox.findComponent(forAttr);
       if (uiComponent == null) {
          throw new IllegalStateException("Could not find component '" + forAttr
          + "' (calling findComponent on component '"
          + checkbox.getClientId(facesContext) + "')");
       }
       if (!(uiComponent instanceof UISelectMany)) {
          throw new IllegalStateException("UISelectMany expected");
       }
       final UISelectMany uiSelectMany = (UISelectMany) uiComponent;
       final Converter converter = getConverter(facesContext, uiSelectMany);
       final List selectItemList = RendererUtils.getSelectItemList(uiSelectMany);
       if (index >= selectItemList.size()) {
         throw new IndexOutOfBoundsException("index " + index + " >= " + selectItemList.size());
       }
       final SelectItem selectItem = (SelectItem) selectItemList.get(index);
       final Object itemValue = selectItem.getValue();
       final String itemStrValue = getItemStringValue(facesContext, uiSelectMany, converter, itemValue);
       final Set lookupSet = RendererUtils.getSelectedValuesAsSet(facesContext, uiComponent, converter, uiSelectMany);
       final ResponseWriter writer = facesContext.getResponseWriter();
       writer.startElement(HTML.LABEL_ELEM, uiSelectMany);
    
       // FIX 1436 isDisabled should check selectitem too!
       //          || selectItem.isDisabled()
       renderCheckbox(facesContext, uiSelectMany, itemStrValue, selectItem.getLabel(),
                      isDisabled(facesContext, uiSelectMany) || selectItem.isDisabled(),
                      lookupSet.contains(itemStrValue), false, index);
       // FIX 1436 isDisabled should check selectitem too!
    
       writer.endElement(HTML.LABEL_ELEM);
     }
    }
    

    and put it in my faces-config.xml:

    <render-kit>
      <render-kit-id>HTML_BASIC</render-kit-id>
      <renderer>
        <!-- fixed org.apache.myfaces.renderkit.html.ext.HtmlCheckboxRenderer issue 1436 -->
        <component-family>org.apache.myfaces.Checkbox</component-family>
        <renderer-type>org.apache.myfaces.Checkbox</renderer-type>
        <renderer-class>org.apache.myfaces.renderkit.html.ext.HtmlCheckboxRendererFix1436</renderer-class>
      </renderer>
    </render-kit>
    

    With this changes the following example will work:

    <a4j:form>
     <t:selectManyCheckbox id="name" layout="spread">
       <f:selectItem itemValue="0" itemLabel="foo"        itemDisabled="true"/>
       <f:selectItem itemValue="1" itemLabel="bar"        />
       <f:selectItem itemValue="2" itemLabel="hustensaft" />
     </t:selectManyCheckbox>
     <h:panelGrid>
       <t:checkbox for="name" index="0"  />
       <t:checkbox for="name" index="1"  />
       <t:checkbox for="name" index="2"  />
     </h:panelGrid>
    </a4j:form>
    

    The first checkbox should be disabled:

    That’s it 😀

     
  • Andreas Höhmann 15:50 am Friday, 6. November 2009 Permalink |
    Tags: backspace, disable, , javascript, , JSF,   

    Disable backspace key in a Richfaces application 

    If you want disable the Backspace key in your JSF Richfaces application put this in your view:

    <rich:hotKey key="backspace" handler="return false;" disableInInput="true"/>
    

    This will register a jQuery Hotkey handler for the document. The handler is not reqistered for input elements because in input fields you need the backspace ;-). Tested for FF3 and IE6.

    Then I found out that the following snippet doesn’t work:

    <rich:hotKey key="backspace"
                 disableInInput="true"
                 handler="alert('Backspace is disabled'); return false;" />
    

    The Browser open the alert box and go to the previous page (in background?!). But there is a fix for that:

    <rich:hotKey key="backspace"
                 disableInInput="true"
                 handler="alert('Backspace is disabled'); event.stopPropagation(); event.preventDefault(); return false;" />
    

    The event variable is available in the handler function (see org.richfaces.renderkit.html.HotKeyRenderer method doEncodeEnd).

     
  • Andreas Höhmann 9:55 am Monday, 7. September 2009 Permalink |
    Tags: , JSF, JSF 2, , ViewExpiredException   

    ViewExpiredException in JSF 1 and 2 

    Ed Burns beschreibt in seinem Blog wie man in JSF 2 selbst eine ViewExpiredException’s behandeln kann.

    Momentan (JSF < 2) kann die Standard-Fehlerbehandlung natürlich auch angepasst werden, z.B. durch Festlegung einer bestimmten Location pro Exception-Typ:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      ...
      <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/pages/error/sessionexpired.xhtml</location>
      </error-page>
      ...
    

    In der von Ed vorgestellten Lösung wird ein eigener ViewExpiredExceptionHandler registriert, welcher den ursprünglichen Handler kapselt. In der dort überschriebenen void handle() wir eine ViewExpiredException mit einem Redirect (via Navigation-Handler) auf eine Fehlerseite beantwortet. In der Fehlerseite können Variable, die im Handler gesetzt wurden, für eine sinnvolle Fehlerbeschreibung verwendet werden.

    Beim Einsatz von Richfaces kann man diese Art von Fehler auch auf der Clientseite behandeln, beschrieben wird dies im Detail hier. Das Ganze ist mit zwei Erweiterungen machbar:

    1. die Funktion für den Client aktivieren

    <context-param>
      <param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name>
      <param-value>true</param-value>
    </context-param>
    

    2. den Javascript-Code für die Behandlung zur Verfügung stellen:

    if (typeof(A4J) !== 'undefined' && typeof(A4J.AJAX) !== 'undefined'){
       // richfaces is available
       A4J.AJAX.onExpired = function(loc,expiredMsg) {
          var confirmMsg = 'Session expired.\n\nReload?';
          if (confirm(confirmMsg)) {
             window.location.reload();
          }
          // return false to inform "link-commands", that the user doesn't want to reload the page
          return false;
       };
    };
    
     
  • Andreas Höhmann 15:20 am Wednesday, 29. July 2009 Permalink |
    Tags: JSF, value binding   

    JSF value binding 

    Today i will explain three types of value binding:

    • „direct“ value binding (one setter / getter for each value)
    • „list based“ value binding (one setter / getter for a list of values)
    • „map based“ value binding (one setter / getter for a map of values)

    Direct value binding

    This is the classic usage of value binding in jsf, the following facelets-snippet is self-explanatory:

    <h:inputText value="#{bean.foo}"/>
    <h:inputText value="#{bean.bar}"/>
    

    Our bean have a setter and a getter for foo and bar:

    class Bean {
      private String foo, bar;
      public String getFoo() ...
      public void setFoo(String) ...
      public String getBar() ...  
      public void setBar(String) ...
    }
    

    List based value binding

    I use this to avoid setter and getter for similar values/properties, i.e.

    <h:inputText value="#{bean.product[0]}"/>
    <h:inputText value="#{bean.product[1]}"/>
    <h:inputText value="#{bean.product[2]}"/>
    ...
    

    With the „classic“ value binding i have to write a lot of getter/setter (product0, product1, product2,…). But with list based value binding its much easier.

    class Bean {
      private static final int MAX_NUMBER_OF_PRODUCTS = 5;
      private final Product[] products = new Product[MAX_NUMBER_OF_PRODUCTS];
      public Bean () {
        for (int i = 0; i < MAX_NUMBER_OF_PRODUCTS; i++) {
        products[i] = null;
      }
     }
     public List<Product> getProduct() {
       return Arrays.asList(Product);
     }
    }
    

    The initialization of the internal array/list is necessary for correct working! During runtime jsf will access each value via index (0, 1, 2, …), a uninitialized list will throw a IndexOutOfBounds Exception.

    Map based value binding

    I used this type of value binding in a generic „CRUD list“ view to implement filtering in a rich:dataTable. I want a selectbox for each „filterable“ column:

    <rich:column>
     <f:facet name="header">
       <h:selectOneMenu value="#{bean.filterValue['foo']}">
          <f:selectItems value="#{bean.filterValues['foo']}" />
       </h:selectOneMenu>
     </f:facet>
     ...
    </rich:column>
    
    <rich:column>
     <f:facet name="header">
       <h:selectOneMenu value="#{bean.filterValue['bar']}">
         <f:selectItems value="#{bean.filterValues['bar']}" />
       </h:selectOneMenu>
     </f:facet>
     ...
     </rich:column>
    

    To get this to work we need a „customized“ map implementation:

    class ArrayMap<K, T> extends HashMap<K, T> {
       
       private static final long serialVersionUID = -5766406097936988242L;
       
       @Override
       public T get(final Object theKey) {
          if (!containsKey(theKey)) {
           // to avoid typos in the ui we throw a exception if a "unknown" value-name is used
            throw new IllegalArgumentException(String.format("The given value-name '%s' is not available", theKey));
          }
          return super.get(theKey);
       }
       public void put(final K key, final T value) {
          super.put(key, value);
       }
     }
    

    This ArrayMap have a getter and a setter (the „normal“ Map have only get and put), for jsf value binding we need a set and a get.

    Here is the final filter – bean:

    class FilterBean {
    
      /**
       * Contain all available filter-values for each supported filter-name.
       */
       private final Map<String, List<SelectItem>> filterValues = new ArrayMap<String, List<SelectItem>>();
    
       /**
        * Contain the current filter-value for each supported filter-name.
        */
       private final ArrayMap<String, Object> filterValue = new ArrayMap<String, Object>();
    
       public FilterBean() {
          initFilterValue();
       }
    
       /**
        * @return a map of lists with {@link SelectItem}s
        */
       public Map<String, List<SelectItem>> getFilterValues() {
         return filterValues;
       }
    
       /**
        * @return the map of filter values
        */
       public ArrayMap<String, Object> getFilterValue() {
         return filterValue;
       }
    
       /**
        * Prepare <tt>filterValue</tt>, add all supported filter-names to the list.
        */
        private void initFilterValue() {
          filterValue.set("foo", null);
          filterValue.set("bar", null);
        }
    
       /**
        * Prepare <tt>filterValues</tt>, the given list contains all rows for the datatable. 
        * Each filter-selectbox must show a unique list of available filter-values 
        * (per supported filter column).
        */
       public synchronized void initFilterValues(final List<T> theInitialFilterList) {
         filterValues.clear();
         filterValues.put("foo", getFilterSelectItemsFoo(theInitialFilterList));
         filterValues.put("bar", getFilterSelectItemsBar(theInitialFilterList));}
       }
    }
    

    The method initFilterValues(final List<T>) will be triggered from a external bean. Then the filter-bean can create a list of SelectItems for each filter-column.

    If the User select a value from such a filter-list the value binding will call our ArrayMap.set method.

    Try it 😀

     
  • Andreas Höhmann 17:13 am Monday, 22. June 2009 Permalink |
    Tags: Input, JSF, , Reset,   

    Clear JSF Input Components 

    Beim Implementieren einer einfachen CRUD Anwendung mit Hilfe von Richfaces Datatable und ModalPanel bin ich über ein „Problem“ mit validierten (leeren) Eingabefeldern gestolpert.

    Das Problem ist eigentlich kein richtiges Problem, sondern das Standardverhalten von JSF 🙂 Unschön wird es wenn man einen rich:modalPanel als Edit-Dialog einsetzt und diesen wiederverwendet.

    Der grobe Aufbau:

    • eine DataTable zeigt eine Liste von Entities (z.B. mit Hilfe eine DAOs geladen)
    • jedes Entity hat eine eindeutige ID (z.B. PrimaryKey aus JPA)
    • pro Tabellenzeile gibt es einen „Edit“-CommandLink der eine rich:modalPanel für das Editieren eines Entity öffnet
    • vor jedem Edit muss die gewünschte Entity in einen CrudManager (Session-Scoped Bean) gelangen, aus der sich der Edit-Dialog mit Daten versorgen kann und mit dessen Hilfe die eigentliche Edit-Aktion durchgeführt wird

    Nun sollen bestimmte Eingabefelder im Edit-Dialog validiert werden (z.B. mit einer @NotEmpty Annotation an den ensprechenden Properties der Entitiy-Klasse). Wenn man nun den Dialog für eine Entity mir der ID ‚1‘ öffnet und eine Validierungsfehler auslöst, z.B. durch das Abschicken mit leeren Eingabefeldern, wird dieser Fehler ausgegeben … soweit so gut. Der Dialog kann dann geschlossen werden. Soll nun Entity mit der ID ‚2‘ mit dem gleichen Dialog editiert werden, sind die Eingabefelder immer noch leer und nicht wie gewünscht mit den Werten aus Entity-2 gefüllt. Warum?!

    Nach einer kurzen Googlesuche landete ich auf der Seite http://wiki.apache.org/myfaces/ClearInputComponents die den Effekt beschreibt. Der Grund für das Verhalten ist die Zwischenspeicherung von „SubmitedValues“ in den jeweiligen UIComponents (z.B. h:inputText). Die werden den eigentlichen Modeldaten vorgezogen.

    Will man nun einen immer aktuellen Edit-Dialog haben, gibt es verschiedene Möglichkeiten (siehe MyFaces). Ich habe mich für die „radikal einfache“ Lösung entschieden … lösche alle Elemente innerhalb des Edit-Dialogs und lasse sie immer neu erzeugen.

    Die Entity-Liste besteht aus einer rich:dataTable, pro Zeile ein a4j:commandButton:

    
    <rich:dataTable value="#{tableManager.model}" var="dataItem">
    
    <!-- Edit-Command Column -->
    <rich:column sortable="false">
    <a4j:commandButton ajaxSingle="true" limitToList="true"
    reRender="foobar_editPanel"
    oncomplete="Richfaces.showModalPanel('foobar_editPanel')"
     actionListener="#{crudManager.onEdit}">
     <f:attribute name="onEditClearTarget" value="foobar_editPanel"/>
     <f:setPropertyActionListener value="#{dataItem}" target="#{crudManager.currentEntity}" />
    </a4j:commandButton>
    
    <!-- more Columns ... -->
    </rich:dataTable>
    
    

    Der tableManager liefert die Entity-Daten, also eine Liste von Entity-Beans, jede Bean hat eine eindeutige ID. Der crudManager enthält stellt die gesamte CRUD Funktionalität zur Verfügung. Für eine Edit muss er mit einer Entity „initialisiert“ werden, dies geschieht via f:setPropertyActionListener. Das reRender bewirkt, dass der Edit-Dialog aktuallisiert wird.

    Der Edit-Dialog wird mit Hilfe von rich:modalPanel erzeugt (foobar_editPanel) und enthält eine Reihe von h:inputText Elementen. Diese sind wiederum an den crudManager gebunden.

    Der Code für das Zurücksetzen der Inputelemente im Edit-Dialog ist ebenfalls im crudManager verborgen und sieht folgendermaßen aus:

    
    public abstract class AbstractCrudManager {
    
    public static final String ONEDIT_ATTRIBUTE_CLEARTARGET = "onEditClearTarget"; //$NON-NLS-1$
    
    /**
    <ul>
    <li>Event-handler will be triggered on <tt>edit</tt>. This method is used as a</li>
    <li>{@link ActionListener} and will be called before a <tt>edit-view</tt> is</li>
    <li>shown. So here we can do some "initializations" for the edit-view, i.e.</li>
    <li>reset input-fields.</li>
    <li></li>
    <li></li>
    <li>This base implementation will call {@link #clearEditTarget(UIComponent)}.</li>
    <li></li>
    <li></li>
    <li>@param aEvent</li>
    </ul>
    
    
     *          is never <code>null</code>
     */
    public void onEdit(final ActionEvent aEvent) {
    clearEditTarget(aEvent.getComponent());
     }
    
    /**
    <ul>
    <li>This method handle a edit-form-clear. Per default the command-button which delegates to the</li>
    <li>edit-view could have a attribute {@link #ONEDIT_ATTRIBUTE_CLEARTARGET}.</li>
    <li></li>
    <li>@param theSourceComponent</li>
    </ul>
    
    
     *          is never <code>null</code>
     */
     protected void clearEditTarget(final UIComponent theSourceComponent) {
     final String onEditTarget = (String) theSourceComponent.getAttributes().get(ONEDIT_ATTRIBUTE_CLEARTARGET);
     if (onEditTarget == null) {
     return;
     }
     final UIComponent editTarget = FacesContext.getCurrentInstance().getViewRoot().findComponent(onEditTarget);
     if (editTarget == null) {
     return;
     }
     editTarget.getChildren().clear();
     }
    
    ...
    
    }
    
    

    Damit ist auch klar was das <f:attribute name=“onEditClearTarget“ value=“#{id}_editPanel“/> bewirkt … es definiert die UI-Komponente die vor dem Öffnen des Dialogs zurückgesetzt werden soll.

    Damit wird bei jedem Klick auf „Edit“ ein Ajax-Request zum Server geschickt, dort wird die aktuelle Entity in den crudManager hinterlegt, es wird onEdit aufgerufen und damit der Inhalt des Edit-Dialogs gelöscht. JSF sorgt dann beim RenderResponse wieder dafür, dass alle UI Componenten korrekt erzeugt werden. Da dann alle Eingabeelement noch vollkommen „neu“ sind, zeigen diese auch die Werte aus dem Modell an.

     
  • Andreas Höhmann 12:30 am Monday, 27. April 2009 Permalink |
    Tags: , Example, , JSF, Realworld,   

    Realworld JSF Application Story 

    Vielleicht hatte ich es in einem früheren Posting schonmal erwähnt, ich arbeite momentan für einen großen dt. Firma an einem Web 2.0 Projekt und das ist jetzt fertig 😀

    Ich konnte dabei all die wunderbaren „neuen“ Technologien einsetzen, u.a. JSF und damit eine funktionsfähige (also den Anforderungen des Kunden voll entsprechende) und zugleich performante „Web 2.0“ Applikation bauen.

    Die Applikation nimmt sich dem Thema „Sicherheitstechnik“ (für die Auskenner: ISO 13849-1 und IEC 62061) an.

    Mal kurz zu den verwendeten „Technologien/Frameworks/Tools/Ideen“:

    • Daten ziehen wir aus einer SAP Knowledgebase und aus einer Datenbank via OpenJPA
    • Services/Manager sind „normale“ Javaklassen (Stichwort Design-Pattern),
      als Kleber verwenden wir Spring (Stichwort Dependency Injection)
    • UI mit JBoss Richfaces (Stichwort Ajax), JSF + Facelets (Stichwort Xhtml-Template), jQuery, CSS, etc.
    • Buildsystem, Projektseiten mit Maven2
    • Continues Integration via TeamCity und Maven2
    • Tests hauptsächlich mit TestNG aber teilweise auch mit JUnit
    • Laden/Speichern von Benutzerdaten via XStream (FileupLoad via Tomahawk), das alles noch Versionskompatibel, d.h. selbsgestrickte XML-Transformationskette für DomainModell-Updates
    • PDF Reportgenerierung mit iText
    • Anbindung an ein „Single Sign On“ System via Spring Security, Webservices

    Im Rückblick kann ich sagen, dass eigentlich alles ohne größere Probleme miteinander funktioniert hat
    … so soll es sein 😀

     
  • Andreas Höhmann 8:35 am Thursday, 4. September 2008 Permalink |
    Tags: Component, Custom, JDeveloper, JSF   

    JDeveloper Declarative JSF Components 

    Auf dieser Seite findet sich ein Screencast in dem Shay Shmeltzer vom Oracle JDeveloper Team die Anwendung von Declarativen JSF Komponenten zeigt. Er hat zwei Projekte, in dem einen definiere er CustomerComponenten (Ähnlichkeiten zu Faclets) in dem anderen benutzt er diese.

     
  • Andreas Höhmann 15:08 am Tuesday, 19. August 2008 Permalink |
    Tags: JSF, Masked Input,   

    Masked Input with Richfaces 

    I would like to define a input-mask for a inputfield, e.g. for a telefonnumber or number in scientific notation (1.23 E-10). A nice way could be the usage of a special „css-class“ to mark the masked-input-elements and the usage of the alt-attribute to define the mask-format. Here is my solution:

    First of all we need a little bit Javascript, i use the Masked Input Component from Jonas Raoni Soares Silva:

    
    addEvent = function(o, e, f, s){
    var r = o[r = "_" + (e = "on" + e)] = o[r] || (o[e] ? [[o[e], o]] : []), a, c, d;
    r[r.length] = [f, s || o], o[e] = function(e){
    try{
    (e = e || (window.event ? (arguments = [].slice.call(arguments)).unshift(e = event) || 1 &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; e : {})).preventDefault || (e.preventDefault = function(){e.returnValue = false;});
    e.stopPropagation || (e.stopPropagation = function(){e.cancelBubble = true;});
    e.target || (e.target = e.srcElement || null);
    e.key = (e.which + 1 || e.keyCode + 1) - 1 || 0;
    }catch(f){}
    for(d = 1, f = r.length; f; r[--f] &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; (a = r[f][0], o = r[f][1], a.apply ? c = a.apply(o, arguments) : (o._ = a, c = o._(e), o._ = null), d &amp;amp;amp;amp;amp;amp;amp;amp;amp;= c !== false));
    return e = null, !!d;
    }
    };
    removeEvent = function(o, e, f, s){
    for(var i = (e = o["_on" + e] || []).length; i;)
    if(e[--i] &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; e[i][0] == f &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; (s || o) == e[i][1])
    return delete e[i];
    return false;
    };
    MaskInput = function(f, m){
    function mask(e){
    var patterns = {"1": /[A-Z]/i, "2": /[0-9]/, "4": /[\xC0-\xFF]/i, "8": /./ },
    rules = { "a": 3, "A": 7, "9": 2, "C":5, "c": 1, "*": 8};
    function accept(c, rule){
    for(var i = 1, r = rules[rule] || 0; i &amp;amp;amp;amp;amp;amp;amp;amp;lt;= r; i&amp;amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;amp;lt;=1)
    if(r &amp;amp;amp;amp;amp;amp;amp;amp;amp; i &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; patterns[i].test(c))
    break;
    return i &amp;amp;amp;amp;amp;amp;amp;amp;lt;= r || c == rule;
    }
    var k, mC, r, c = String.fromCharCode(k = e.key), l = f.value.length;
    (!k || k == 8 ? 1 : (r = /^(.)\^(.*)$/.exec(m)) &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; (r[0] = r[2].indexOf(c) + 1) + 1 ?
    r[1] == "O" ? r[0] : r[1] == "E" ? !r[0] : accept(c, r[1]) || r[0]
    : (l = (f.value += m.substr(l, (r = /[A|9|C|\*]/i.exec(m.substr(l))) ?
    r.index : l)).length) &amp;amp;amp;amp;amp;amp;amp;amp;lt; m.length &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; accept(c, m.charAt(l))) || e.preventDefault();
    };
    for(var i in !/^(.)\^(.*)$/.test(m) &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; (f.maxLength = m.length), {keypress: 0, keyup: 1})
    addEvent(f, i, mask);
    };
    

    then we define the inputfield:

    <h:inputText styleClass="maskedInput" alt="9,99 E-99"/>
    

    and last a little bit JS-Code which decorates the current formulare after each rerender, but it at the end of your page:

    <a4j:outputPanel ajaxRendered="true">
      <script type="text/javascript">
       var maskedInput=$$(".maskedInput");
       if (Object.isArray(maskedInput)){
         maskedInput.each(function (elm){
         // input-mask is defined in the alt element
         var maskPattern = Element.readAttribute(elm, "alt");
         MaskInput(elm, maskPattern);
         });
       }
      </script>
    </a4j:outputPanel>
    

    That’s it 🙂 Every time A4J rerenders the page the decorator search all marked elements and creates a MaskInput object for the elements.

    Try it!

     
  • Andreas Höhmann 17:00 am Friday, 25. April 2008 Permalink |
    Tags: Converter, Enum, JSF   

    EnumConverter 

    Today i found a very simple solution for using a Enumeration with a converter in JSF. Other than Rick Hightowers or Dave Brondsena i used the hidden javax.faces.convert.EnumConverter. Why hidden? I can’t find no reference in the JSF 1.2 documentation. But both implementations MyFaces and SunRI contains such a class. And the class is not depreacated. So … let’s use it 🙂

    public enum EnumType {
       A1, A2, A3, A4,
    }
    public class EnumTypeConverter extends EnumConverter {
      public EnumTypeConverter() {
        super(EnumType.class);
      }
    }
    
      <converter>
        <converter-id>ENUM</converter-id>
        <converter-class>de.ahoehma.jsf.converter.EnumTypeConverter</converter-class>
      </converter>
    
    <h:selectOneMenu id="type" value="#{bean.type}">
      <f:converter converterId="ENUM"/>
      <f:selectItem itemLabel="Type A1" itemValue="A1"/>
      <f:selectItem itemLabel="Type A2" itemValue="A2"/>
      <f:selectItem itemLabel="Type A3" itemValue="A3"/>
      <f:selectItem itemLabel="Type A4" itemValue="A4"/>
    </h:selectOneMenu>
    
     
  • Andreas Höhmann 14:43 am Monday, 31. March 2008 Permalink |
    Tags: , , File Download, JSF, MyFaces,   

    JSF, Ajax and file download 

    Today I show you a example which combines Ajax (Richfaces) and a „normal“ download in a JSF application.

    Here is the bean with the download-code:

    import java.io.File;
    import java.io.IOException;
    import javax.faces.context.FacesContext;
    import javax.faces.event.ActionEvent;
    import javax.servlet.http.HttpServletResponse;
    
    public class DownloadBean {
    
      // actionListener="#{bean.execute}"
      public void execute (ActionEvent event) {
       download();
      }
    
      // action="#{bean.download}"
      public String download() {
        final FacesContext facesContext = FacesContext.getCurrentInstance();
        // XXX create temp. filecontent ... resultFile
        writeOutContent(getServletResponse(), new File(this.resultFile), "file.xml");
        facesContext.responseComplete();
        // dont use jsf-navigation-rules
        return null;
      }
    
      void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
        if (content == null)
          return;
        try {
          res.setHeader("Pragma", "no-cache");
          res.setDateHeader("Expires", 0);
          res.setContentType("text/xml");
          res.setHeader("Content-disposition", "attachment; filename=" + theFilename);
          fastChannelCopy(Channels.newChannel(new FileInputStream(content)), Channels.newChannel(res.getOutputStream()));
        } catch (final IOException e) {
          // TODO produce a error message 🙂
        }
      }
    
      void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
        final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
        while (src.read(buffer) != -1) {
          buffer.flip();
          dest.write(buffer);
          buffer.compact();
        }
        buffer.flip();
        while (buffer.hasRemaining()){
          dest.write(buffer);
        }
      }
    }
    

    Now the facelets snipplets: Not Working – Javascript Error 😦

    <h:form>
     <h:commandLink actionListener="#{command.execute}" value="Download"/>
     <h:commandLink action="#{command.download}" value="Download"/>
    </h:form>
    

    Not Working – Download is shown in the current page – the ajax page will replaced with the download-content 😦

    <a4j:form>
      <a4j:commandLink actionListener="#{command.execute}" value="Download"/>
      <a4j:commandLink action="#{command.download}" value="Download"/>
    </a4j:form>
    

    Working 🙂

    <a4j:form>
     <a4j:htmlCommandLink actionListener="#{command.execute}" value="Download"/>
     <a4j:htmlCommandLink action="#{command.download}" value="Download"/>
    </a4j:form>
    
    <h:form>
     <a4j:htmlCommandLink actionListener="#{command.execute}" value="Download"/>
     <a4j:htmlCommandLink action="#{command.download}" value="Download"/>
    </h:form>
    

    The a4j:htmlCommandLink was made for this szenario.

    Notice: the fast channel copy routine was introduced by waffel.

     
    • walthersoft 13:51 am Freitag, 11. Juli 2008 Permalink | Zum Antworten anmelden

      Nice, was looking for something like this. However, it doesn’t compile, where do you get ‚getServletResponse()‘ in your download() method from ?

    • Andreas Höhmann 7:48 am Donnerstag, 31. Juli 2008 Permalink | Zum Antworten anmelden

      Its a private method wich return the current HttpServletResponse, i haven’t posted because the code is very easy

    • Dummal 15:38 am Mittwoch, 23. Dezember 2009 Permalink | Zum Antworten anmelden

      You saved my day… man!

      thanx a bunchh!

    • ajayjiit 13:42 am Donnerstag, 8. Juli 2010 Permalink | Zum Antworten anmelden

      Hi can you list down the which packages classes ti be imported and zars required.
      iam not able to run it

c
Neuen Beitrag erstellen
j
nächster Beitrag/nächster Kommentar
k
vorheriger Beitrag/vorheriger Kommentar
r
Antworten
e
Bearbeiten
o
zeige/verstecke Kommentare
t
Zum Anfang gehen
l
zum Login
h
Zeige/Verberge Hilfe
Shift + ESC
Abbrechen