Older blog entries for waffel (starting at number 16)

how to use EL from java in a JSF 1.2 environment


There are not much examples, how to use a ELExpression from your java code. The most examples I found, are focussing on “implement your own ELResolver”. The best documentation comes from SUN in form of tutorials and package/javadoc.

Now I will provide some tips how to deal with EL expressions from java. I have tested and implemented this in a JSF 1.2 web application, where I have access to the FacesContext.

In JSF 1.2 you have access to expression factory:


// get application from faces context
Application app = FacesContext.getInstance().getApplication();
ExpressionFactory exprFactory = app.getExpressionFactory();

Now you can use the expression factory to get a MethodExpression or ValueExpression. In my projects we need very often ValueExpressions.

But first you need also an ELContext. There are many implementations available of such context (for JSP, Faces and so on) and enough documentation how to create your own context.
You can access such context again from the faces context:


// getting the ELContext from faces context
ELContext elContext = FacesContext.getInstance().getELContext();
// creating value expression with the help of the expression factory and the ELContext
ValueExpression valExpr = exprFactory.createValueExpression(elContext, "#{devBean.devMode}", Boolean.class);

In this example I will use the boolean value from a “devBean” to work later with this value. Of course, you can inject the value expression, required class type and so on.
The last needed thing is to assign the value to a local variable:


Boolean developmentMode = (Boolean) valExpr.getValue(elContext);

Thats it!

Posted in java, JSF, software   Tagged: EL, ELContext, JSF, JSF1.2   

Syndicated 2008-11-28 19:47:09 from waffel's Weblog

updating mediawiki is easy


I have updated some homepages to the brand new mediawiki version 1.13.2 which was very easy. They have a very good description what you have to do, if you update to a new version and a very nice update script which works also for very old wiki versions (I have tested this with the 1.4.5 version).

But there ara small problems with own skin (for example on http://www.buzztard.org). The skin have to be fixed per hand. Hopfully ensonic can do this the next days.

Posted in administration, software   Tagged: mediawiki, upgrade   

Syndicated 2008-11-13 12:33:10 from waffel's Weblog

fun with h:dataTable and a4j:form


I have some facelet components and want to use them in a h:dataTable. My components containing some form elements like h:inputText, command buttons and so on. To avoid scrolling, I have placed them into a a4j:form.

Now in my h:dataTable loop I call these facelet components and want to have a list of inputText components for example. But every time, I typed in something, only the last input field called correct my setValue() method. All other input components dosn’t call the setter.

Here a very small example to imagine the problem:

The datatable


<h:dataTable value="myBackingBean.list" var="currentItem">
  <h:column>
    <waffel:input item="#{currentItem}"/>
  </h:column>
</h:dataTable>

The facelet component:


  ...
  <a4j:form>
    <h:inputText size="30" value="#{item.value}"/>
    <a4j:commandButton value="ok" action="#{item.applyValue}"/>
  </a4j:form>
  ...

To get this to work you have to place a a4j:region around the a4j:form!


  ...
  <a4j:region>
    <a4j:form>
      <h:inputText size="30" value="#{item.value}"/>
      <a4j:commandButton value="ok" action="#{item.applyValue}"/>
    </a4j:form>
  </a4j:region>
  ...

Now it works fine.

Posted in JSF   Tagged: a4j, dataTable, Facelets, JSF   

Syndicated 2008-10-07 09:41:05 from waffel's Weblog

expanding richfaces tree on datamodel changes


Sometimes you will select a tree node in a richfaces tree, triggered by your datamodel. There are several hints how to do this with a tree state advisor, but I have found another way to do this.

My main problem was, that I do not have a relation between my datamodel and the richfaces UITree components (nodes). This problem was introduced because I use the recursiveTreeAdaptor. I have not found a way to get a TreeRowData object from the UITree for my datamodel object.

I have searched in the richfaces implementation, if there is another way to work with my datamodel which have to expand the tree, if the datamodel is changed.

Lets clearify what I want to do: I have a datamodel with some root nodes and “normal” nodes in a tree like structure. I have also (in my TreeManager) a parameter which holds a selectedNode. A node can selected from the UI (the user clicks on a tree node and causes a node selection event) or from my datamodel, which calls a method in the TreeManager to select a specific tree node.

The tree manager contains a method to select a specific node like this:


public void select(final Node nextStepNode) {
  this.selectedNode = nextStepNode;

}

To expand the tree to the selected node, I have changed to select method:


public void select(final Node nextStepNode) {
  this.selectedNode = nextStepNode;
  try {
      // walk over the tree which expands the tree and uses a complete tree
      // range
      tree.walk(FacesContext.getCurrentInstance(), expandingDataVisitor, new CompleteTreeRange(), null, null);
    } catch (final IOException e) {
      if (LOG.isErrorEnabled()) {
        LOG.error(String.format("problem %s", e.getMessage()));
      }
    }
}

The tree walk method walks over the tree using my own data visitor and tree range. The tree range implementation tolds the tree to walk also over hidden nodes. You remember? The tree should expand all nodes to the selected node, also if the selected node is hidden.

The tree range implementation looks like:


public class CompleteTreeRange implements TreeRange {

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  public boolean processChildren(final TreeRowKey rowKey) {
    return true;
  }

  /**
   * {@inheritDoc}
   */
  @SuppressWarnings("unchecked")
  public boolean processNode(final TreeRowKey rowKey) {
    return true;
  }

Now comes the hard stuff on my solution, the expandingDataVisitor:


public class ExpandingDataVisitor implements DataVisitor {
  public void process(final FacesContext theContext, final Object theRowKey, final Object theArgument)
      throws IOException {
    if (selectedNode.equals(tree.getRowData(theRowKey))) {
      tree.queueNodeExpand((TreeRowKey) tree.getParentRowKey(theRowKey));
    }
}

You can queue node expanding with a tree rowKey to the node, which you want to expand. You don’t need to queue all nodes on the path. The queueNodeExpand method works fine with one rowkey. The row describes itself the complete path to the node. If you use standard jsf ID’s, a possible treeRowKey looks like “jsp123:jsp124:jsp125″ wich is the complete path to your node (row key).

You have to know, that you don’t want expand the selected node (this is in most cases a leafe). You want to expand the tree to the parent of the selected node.

Syndicated 2008-09-09 12:19:13 from waffel's Weblog

Reuse facelets xhtml files and taglibs from jar archives


I have asked myself, if it is possible to use facelets xhtml files and taglibs from a jar file instead from the whole web application.

The short anwser: Yes, it is possible ;-)

The facelets documentation gives a hint how to use the tag lib from a jar file. But you cannot found in the documentation, if it is possible also to use a xhtml file (referenced from the taglib for example). Of course facelets uses the same approach to load xhtml files from a jar file as for the tag library.

Example:
The follow tag lib definition is placed in my JAR project under /META-INF/myProject.taglib.xml


<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib>

    <namespace>http://thomaswabner.wordpress.com/waffel</namespace>

    <tag>
        <tag-name>select</tag-name>
        <source>components/select.xhtml</source>
    </tag>

</facelet-taglib>

The select.xhtml file is placed in the same project under /META-INF/components/select.xhml and contains some facelets definitions (ui component with a selectbox fo example). The point is, that facelets searches the jar archive under the /META-INF directory for the xhtml file.

Now you can simple use the tag in you web application. You only need to include the jar file with the tag library and xhtml file in you web application classpath.


<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:waffel="http://thomaswabner.wordpress.com/waffel"
          version="2.0">
  <ui:component>
     <waffel:select/>
  </ui:component>
</jsp:root>

Syndicated 2008-06-25 14:47:15 from waffel's Weblog

Disable live site with apache rewrite rules


Any times I have to work on a live site like http://www.capella-fidicinia.de or http://www.cryo-tekk.de. All these sites are Joomla instances and Joomla doe’s not allow to disbale the site complete. You can only put the site “offline” with a setting in the administration module. After putting such site into the offline mode, nobody can anymore change the content and the user got a inforation bar on the site.

But often I will change complete the layout (testing new skin, working on the existing skin and so on). But the user should not see my changes because it is very ugly if you browse to a side and with every click the layout changes.

My Joomla instances running behind a apache2 webserver as a virtual host. To put the site complete offline and inform the user about maintainance you can put the follow into you virtual host configuration:


RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^194.136.37.140$
RewriteRule .* /var/www/domains/www.cryo-tekk.de/htdocs/maintainance.html [L]

With such entry only the IP adress 194.136.37.140 can see the site. All other IP adresses, which try to access the site are foreward to the maintainance.html site.

For more information about rewrite rules you can have a look here.

Syndicated 2008-06-19 10:52:28 from waffel's Weblog

getting node data from rich tree on user selection


I have had the problem to get node data from a richfaces tree, if the user selects a node. I have used a recursive tree adapter:


<rich:tree switchType="server"
           stateAdvisor="#{treeStateAdvisor}"
           nodeSelectListener="#{treeMgrt.onSelect}">

   <rich:recursiveTreeNodesAdaptor roots="#{treeMgrt.roots}" var="item" nodes=" {item.nodes}">

     <rich:treeNode>
         <h:outputText value="#{item}"/>
     </rich:treeNode> 

  </rich:recursiveTreeNodesAdaptor>
</rich:tree>  

The method in my tree manager onSelect(…) looks like this:


public void onSelect(final NodeSelectedEvent event) {
  final UITree theTree = this.getTree(event);
  if (null == theTree) {
    return;
  }
  final Object rowKey = theTree.getRowKey();
  // this works better
  final Object rowData = theTree.getRowData(rowKey);
  if (rowData instanceof ProductNode) {
    this.selectedNode = (ProductNode) rowData;
  }
}

Normally you can use theTree.getTreeNode(); but with a recursive tree model which method returns alway null. Instead of this I have used the getRowData() method which works for me.
I have filed a bug for richfaces. Hope the problem becomes shortly a solution.

Syndicated 2008-06-13 13:33:13 from waffel's Weblog

place a div element always bottom


A while ago I have searched for a solution to place a <div> element inside another <div> element always bottom. There are many solutions to put the div bottom from the whole html site but rar solutions to put it in the container div bottom.

Now here comes my solution …

I have one div container (calling it simple container) with a height of 100% (this container itself is placed for example in another parent container which has a height of 400px). And I have my div which should placed bottom of the container:


<div id="container" style="height:100%; position:relative;">
  <div id="bottom_div" style="height:10%; position:absolute; bottom:0px;"/>
</div>

The trick is to give the container div a position relative and then you can use the position absolute in the bottom div element. If the container div has no position style atribute it will not work.

Syndicated 2008-06-10 09:35:26 from waffel's Weblog

Holiday in Usedom Koserow


And here comes the story (sorry only in german) about my holiday with friends in Koserow (Germany, Usedom).

Am 29.12.2007 angekommen haben wir natürlich erstmal unser tolles Feriendomiziel begutachtet und dann nach ca. 6h Fahrt unseren Schlüssel bekommen. Die Empfangsdame war etwas eigenartig und wir wurden unvorhergesehen gleich mal um 230,- EUR ärmer gemacht, da diverse Dinge im Voraus zu bezahlen waren, was nicht wirklich klar war. So richtig geschockt hatte uns dann aber der Schlafraum für 2 Personen, welcher von der Küche lediglich durch eine Glaswand! abgetrennt war. Dieser Raum ist auch gleichzeitig das Wohnzimmer und für ein Pärchen, wie man sich vorstellen kann, denkbar ungüstig. Also mal wieder nicht richtig in der Beschreibung angegeben und damit durchgefallen. Zum Glück hatten wir 2 Ferienwohnungen und haben dann intern ein wenig umdisponiert was die Sache aber auch für einige von uns etwas teurer machte. Aber besser so als anders.

Abends dachten wir uns dann, dass man an der Ostsee, wenn dann denn auch mal Fisch essen sollte. Also haben wir uns zum Glück schnell mal per Internet informiert und rumgesucht, was es denn in diesem feinen Ort alles so an Fischrestaurants gibt. Nachdem wir bei 3 Gaststätten angerufen hatten (entweder schon ausgebucht, oder die Nummer stimmte nicht -> man beachte dass diese Nummer von der offiziellen Internetpräsenz des Ortes stammt, also wir Bürger bezahlen fleißig für den Quatsch) haben wir uns entschieden, einfach per Fuß nach einem geeigneten Lokal Ausschau zu halten. Letzenendes haben wir dann auch einen Platz in einer sogenannten Fischgaststätte erhalten. Den Fisch den wir bestellt hatten, konnte man aber nicht essen. Total viel Fett und Butter dran und das an jedem der Essen, welches bei 6 Personen schon sehr unterschiedlich war. Sehr “nett” dann auch die Bediehnung, welche auf die Frage “Wieviel ist denn auf so einer Fischplatte für 2 Personen” antwortete “das werden Sie schon sehen” oder auf die Frage “Schmeckt die Knoblauchsuppe sehr nach Knoblauch” mit “das kommt drauf an” antwortete. Eigentlich müsste man dann aufstehen und gehen, aber da man ja hier kaum einen Platz in einer Gaststätte bekommt, haben wir uns das ganze für einen netten Preis dann doch angetan. Das Restaurant heisst übrigens “Hansel Kogge” und ist nicht zu empfehlen.

Am 30.12.2007 sind wir dann nach einem leckeren selbst gemachten Frühstück (danke Höhmi ;-)) raus in die Natur. Hier zeigte sich, dass auch eine ausfürhliche Internetrecherge nicht wirklich ausreicht, um sinnvolle Wanderwege zu finden. Aus jetztiger Sicht also die Empfehlung: Vorher ne Karte besorgen, sonst klappts nicht. Wir sind dann an der Steilküste entlang gewandert und wollten eigenlich eine kleine Tour nach Kölpinsee und dann über Loddin zum Achterwasser machen. Bis nach Kölpinsee sind wir gekommen. Dort gab es auch eine kleine leckere Fischräucherrei, gleich an dem gleichnahmigen See. Dann wollten wir den ausgeschilderten Naturrundweg bewandern, was sich aber nach einigen Kilometern als sinnlos herausstellte, da man keinerlei Beschilderung fand und am Ende an der viel befahrenen B111 entlang laufen musste. Also haben wir das ganze abgebrochen und sind in Kolpinsee in ein sehr eigenartiges Cafee am Strassenrand “Stadt Usedom” eingekehrt um eigentlich Kaffee und Kuchen zu uns zu nehmen. Hier war die Bediehnung mehr als prasslig, da sie weder unsere Bestellung aufnehmen konnte, noch ordentlich bedienen konnte. So kam z.B. eine Kellnerin mit einem Eis (ich hatte mit Schwarzwälder Kirsch bestellt) und meinte “hier habe ich was heisses mit Eis”. Ich meinte dann (da ich der einzige mit einem Eis war) “das müsste meins sein”. Daraufhin fragte Sven die Kellnerin “Sie wissen wohl nicht was das für ein Eis ist?” und diese meinte “Nein, das habe ich ja nicht selber gemacht. Da müssen Sie einfach mal probieren”. So toll kann das sein. Hinzu kam dann noch der Preis und das man sich (man halte sich fest) bei der Endabrechnung bei Höhmi gleich mal um 10 EUR verrechnet hat. Die sollten für 2 Kaffe und ein Stück Kuchen 20 EUR bezahlen! Und die verdummte Bedienung hat nichmal gemerkt dass da was faul ist, sondern reagierte erst auf Nachfragen.

Abends hatte uns dann Gee eingeladen. Hier ging es dann zum Fischessen in die Bernsteinhexe. Dem einzigen dem es nicht schmeckte, war meine Frau Madeleine.

31.12.2007 Da wir noch einkaufen mussten, sind wir ungewohnterweise sehr früh aufgestanden und nach einem leckeren Frühstück in den Nettomarkt dieses Ortes gefahren. Naja … wie man sich einen Netto am Silversterabend eben vorstellt: Total runtergekommen, alles ausverkauft und das ganze Ding mit Massen an Menschen überfüllt. Aber wir haben trotzdem fast alles bekommen, was wir haben wollten und sind dann ab in die Bernsteintherme. Hier fanden wir das Parken sehr interessant, da man 3,50 EUR bezahlen musste, wo man dann als Besucher der Therme 1,50 EUR als Essensgutschein hatte. Auch ne Idee Geld zu verdienen ;-) … die Therme selber hat mir und meiner Frau nicht so gefallen, da schon ziemlich alt und renovierungsbedürftig.

Abends war dann wir immer Spieleparty mit Feuerzangenbowle und was sonst noch so dazu gehört.

Das solls erstmal gewesen sein … iss ja nun auch schon ne Weile her ;-). Photos gibts unter http://photo.hora-obscura.de/main.php?g2_itemId=13651

Syndicated 2008-02-05 11:43:48 from waffel's Weblog

Fast stream copy using java.nio channels


Many times I was asked how to copy fast and simple an input stream to an output stream. I have found a nice solution on koders.com . A programmer named Mr. Hitchens has contributed this code.

Here are my utility method which makes the real fast copy stuff:


public final class ChannelTools {
  public static void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
    final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
    while (src.read(buffer) != -1) {
      // prepare the buffer to be drained
      buffer.flip();
      // write to the channel, may block
      dest.write(buffer);
      // If partial transfer, shift remainder down
      // If buffer is empty, same as doing clear()
      buffer.compact();
    }
    // EOF will leave buffer in fill state
    buffer.flip();
    // make sure the buffer is fully drained.
    while (buffer.hasRemaining()) {
      dest.write(buffer);
    }
  }
}

And how you can use this method to copy an input stream into an output stream? Here comes the answer:


// allocate the stream ... only for example
final InputStream input = new FileInputStream(inputFile);
final OutputStream output = new FileOutputStream(outputFile);
// get an channel from the stream
final ReadableByteChannel inputChannel = Channels.newChannel(input);
final WriteableByteChannel outputChannel = Channels.newChannel(output);
// copy the channels
ChannelTools.fastChannelCopy(inputChannel, outputChannel);
// closing the channels
inputChannel.close();
outputChannel.close()

Syndicated 2007-10-09 09:21:31 from waffel's Weblog

7 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!