Monday, June 28, 2010

Submitted value, local value, model value ...

There are 4 places where the value is stored during JSF lifecycle.
  1. The typed value comes with a request and is placed into request parameter map.
  2. Then the "submitted value" of component will be set.
  3. The "submitted value" is checked against the converter and only if it's OK the "local value" is updated and the "submitted value" is cleaned up.
  4. Then, only if validation und update phases are passed successfully, the "model value" (e.g. #{foo.bar}) is updated and the "local value" is cleaned up.

Assume, the user enters a wrong date. The page after reload should show the value user entered, but not the old one from the model. Therefore, the algorithmus in the render response phase is the following:
- if a submitted value is not empty, grab it and show.
- otherwise, if a local value is not null, show it.
- otherwise, call a getter of the model value and show it.

Unfortunately, but some JSF component libraries forget this fact. I use PrimeFaces - a great, JSF 2 "ready", rapidly evolving component library and more. I didn't check all components, but at least two components don't consider submitted values in the current release 1.0.2 / 2.0.2. That are: PickList and Calendar. I had to write a customizing code during markup encoding because it's important e.g. for failed validation or wizard like functionality.

PickListRenderer
DualListModel model;
Object submittedValue = pickList.getSubmittedValue();
if (submittedValue != null) {
    model = (DualListModel) getConvertedValue(facesContext, pickList, submittedValue);
} else {
    model = (DualListModel) pickList.getValue();
}
CalendarRenderer
String valueAsString;
if (calendar.getSubmittedValue() != null) {
   valueAsString = (String) calendar.getSubmittedValue();
} else {
   valueAsString = CalendarUtils.getValueAsString(facesContext, calendar);
}

How to configure Apache Jackrabbit for binary content search?

The configuration file repository.xml is described in detail by Apache Jackrabbit. The section for workspace and versioning configuration must be extended to support binary content search as follows:
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
    <param name="path" value="${wsp.home}/index"/>
    <param name="extractorPoolSize" value="2"/>
    <param name="supportHighlighting" value="true"/>
    <param name="textFilterClasses"
      value="org.apache.jackrabbit.extractor.PlainTextExtractor,
      org.apache.jackrabbit.extractor.MsWordTextExtractor,
      org.apache.jackrabbit.extractor.MsExcelTextExtractor,
      org.apache.jackrabbit.extractor.MsPowerPointTextExtractor,
      org.apache.jackrabbit.extractor.PdfTextExtractor,
      org.apache.jackrabbit.extractor.OpenOfficeTextExtractor,
      org.apache.jackrabbit.extractor.RTFTextExtractor,
      org.apache.jackrabbit.extractor.HTMLTextExtractor,
      org.apache.jackrabbit.extractor.XMLTextExtractor"/>
</SearchIndex>
Content of following document types can be full text searchable with this configuration
  • Plain Text
  • MS Word
  • MS Excel
  • MS Powerpoint
  • PDF
  • OpenOffice
  • RTF
  • HTML
  • XML
There are two points to be considered: Content repository needs some time after document adding to parse documents content and extract needed informations. In my tests I had to wait ca. 7 sek.
// add document and save changes
....

// sleep 7 sek. to allow the content of document be indexed
try {
    Thread.sleep(7000);
} catch (InterruptedException e) {
    ;
}

// do full text search
....
The second point is related to the configuration of node types. The full text search works if you use quite normally node type nt:file which contains a sub node jcr:content of type nt:resource. If you use custom node types you must ensure that the node type describing binary content has at least two properties: jcr:data (content is stored here) and jcr:mimeType. The second property for mime type is very important. Without the mime type there isn't text extraction (consequential, isn't it?). Here is an example in XML notation:
<nodeType name="cssns:resource"
          isMixin="false"
          hasOrderableChildNodes="false"
          primaryItemName="jcr:data">
    <supertypes>
        <supertype>nt:base</supertype>
        <supertype>mix:referenceable</supertype>
    </supertypes>
    <propertyDefinition name="jcr:mimeType"
                        requiredType="String"
                        autoCreated="false"
                        mandatory="true"
                        onParentVersion="COPY"
                        protected="false"
                        multiple="false">
    </propertyDefinition>
    <propertyDefinition name="jcr:data"
                        requiredType="Binary"
                        autoCreated="false"
                        mandatory="true"
                        onParentVersion="COPY"
                        protected="false"
                        multiple="false">
    </propertyDefinition>
</nodeType>

<nodeType name="cssns:file"
          isMixin="false"
          hasOrderableChildNodes="false"
          primaryItemName="jcr:content">
    <supertypes>
        <supertype>mix:versionable</supertype>
        <supertype>cssns:hierarchyNode</supertype>
    </supertypes>
    <propertyDefinition name="cssns:size"
                        requiredType="Long"
                        autoCreated="true"
                        mandatory="true"
                        onParentVersion="COPY"
                        protected="false"
                        multiple="false">
        <defaultValues>
            <defaultValue>-1</defaultValue>
        </defaultValues>
    <childNodeDefinition name="jcr:content"
                          defaultPrimaryType=""
                         autoCreated="false"
                         mandatory="true"
                          onParentVersion="COPY"
                          protected="false"
                          sameNameSiblings="false">
     <requiredPrimaryTypes>
         <requiredPrimaryType>cssns:resource</requiredPrimaryType>
     </requiredPrimaryTypes>
    </childNodeDefinition>
</nodeType>

Friday, June 25, 2010

How to make a fixed padding in HTML buttons?

If you have an input button in your HTML you maybe want to have a fixed padding around its label (text inside button). The padding is normally dependent on the label length and can look inordinate. These two buttons have for instance different spaces between labels and button borders.
<input type="button" value="OK">
<input type="button" value="Cancel">
The same padding is a simple task for most used browsers except Internet Explorer. Use the following workaround for IE:
/* All browsers */
input {
    padding: 0 7px 0 7px;
}

/* IE only */
* input {
    width: auto;
    overflow: visible;
}
By the way, the star hack (here * input) is only understood by IE and ignored by other browsers. I've tested this working trick for IE 6-8.