Mittwoch, 23. Mai 2012


Artikel

Juli 2009 | Artikel

Hands on: Portlet-Kommunikation und RichFaces-Komponenten

(Link zum Artikel: http://www.entwickler.de/jaxenter//002432)

ECM-On-TOP mit Alfresco, Liferay und RichFaces - Teil 2

Text: Sebastian Wenzky
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Im ersten Artikel lag der Fokus auf der Vorstellung wesentlicher Grundlagen zum aktuellen Stand von Portlet-Anbindungen nach den neuesten Standardisierungen. Darauf aufbauend führten wir mittels Alfresco den praktischen Teil des Kapitels ein, indem wir die (Web-Service-)Anbindung an das ECM-System im FileFolderService programmierten. Erste JSR-286-Implementierungen wie das Resource Handling sind in Folge der Einrichtung eines Proxies notwendig gewesen. Aufbauend darauf, wird in diesem zweiten Artikel die Kommunikation zwischen verschiedenen Portlets genauer betrachtet werden. Eine anschließende Vorstellung der notwendigen RichFaces-Komponenten sowie eine kritische Betrachtung des umgesetzten Beispiels schließen diesen zweiten Artikel ab.
Teil 1   Teil 2   Teil 3   

Standardisiertes Event Handling zwischen Portlets

In unserem Beispiel ist eine Dokumentenliste zwischen den zwei verschiedenen Portlets auszutauschen. Hierzu stellt ebenfalls die JSR-286-Spezifikation eine passende Möglichkeit bereit: das Event Handling. Die Definition der Events erfolgt über QNames. In unserem Beispiel erfolgt zunächst die Definition in der XML-Datei portlet.xml:

  1. <event-definition>
  2. <qname xmlns:x="http:de.dmc.alfresco/events">x:DocumentList</qname>
  3. <value-type>java.util.LinkedList</value-type>
  4. </event-definition>
Listing 1: Definition eines Events nach JSR-286

Nach der Definition gilt es zu bestimmen, welches Portlet ein solches Event senden und empfangen kann.

  1. <portlet>
  2. <portlet-name>AlfrescoSpaceBrowser</portlet-name>
  3. ...
  4. <supported-publishing-event>
  5. <qname xmlns:x="http:de.dmc.alfresco/events">x:DocumentList
  6. </qname>
  7. </supported-publishing-event>
  8. </portlet>
  9. ...
  10. <portlet>
  11. <portlet-name>AlfrescoDocumentBrowser</portlet-name>
  12. ...
  13. <supported-processing-event>
  14. <qname xmlns:x="http:de.dmc.alfresco/events">x:DocumentList
  15. </qname>
  16. </supported-processing-event>
  17. </portlet>
Listing 2: Das Alfresco-Portlet verschickt(publishing) eine Dokumentenliste mittels Events. Liferay liefert dieses Event an die Portlets aus, die sich hierauf registrieren(processing).

Die Nutzung von Events geht einher mit einem javax.portlet.ActionRequest. Dieser Request auf das Navigations-Portlet ist notwendig, um Informationen zwischen Portlets austauschen zu können. Ein JSF-Button oder JSF-Link bspw. generiert einen solchen ActionRequest. In diesem Beispiel implementieren wir eine Methode, die aufgerufen wird, sobald ein Benutzer ein Dokument im Portlet Repository Space Browser auswählt. Anschließend erfolgt das Auslesen der vorhandenen Dateien in diesem ausgewählten Space nach Listing 3. Über den ActionResponse-Mechanismus schicken wir die Liste auf die Reise. Portlets auf der aktuellen Seite (damit ist eine aggregierte Portlet-Seite gemeint), die dieses Event verarbeiten können (Listing 2), stellen das Ziel der Aufrufe von Liferay dar.

  1. public void processNodeUUID(ActionEvent actionEvent){
  2. ActionResponse response = (ActionResponse) FacesContext
  3. .getCurrentInstance().getExternalContext().getResponse();
  4. ActionRequest request = (ActionRequest)FacesContext
  5. .getCurrentInstance().getExternalContext().getRequest();
  6. List<TreeDocument> files = this.fileFolderWebService .getDocumentsByParentFolderUUID(request.getParameter("nodeUUID"));
  7. AbstractTreeNode[] nodes = sortNodes(files);
  8. response.setEvent(new QName("http:de.dmc.alfresco/events", "DocumentList"), ( Serializable) Arrays.asList(nodes));
  9. }
Listing 3: Ist einmal ein bestimmter Space im "Space Browser" ausgewählt, so werden mittels Aufruf der Methode processNodeUUID die entsprechenden Unterspaces ausgelesen

Das Überschreiben der Methode javax.portlet.EventPortlet.processEvent ist eine zwingende Vorrausetzung für den Empfang und die Verarbeitung von Events. Der Aufruf dieser Methode erfolgt nach dem Aufruf von processAction() und vor der Verarbeitung der Render-Phase. Hierzu muss, wie schon in Listing 7 gezeigt, das GenericFacesPortlet im Portlet Resource Browser erweitert werden.

  1. public void processEvent(EventRequest request, EventResponse response)
  2. throws PortletException, IOException {
  3. request.getPortletSession().setAttribute("documents", request.getEvent().getValue());
  4. }
Listing 4: Das Ablegen der überlieferten Dokumentenliste im „Document Browser“-Portlet erfolgt in der Portlet-Session.

Leider verfügen wir innerhalb der processEvent-Methode über keinen Zugriff auf einen validen FacesContext. Dieser wird sowohl vor als auch nach dem Aufruf dieser Methode neu aufgebaut. Aus diesem Grund muss das Ergebnis auf eine andere Weise zur späteren Verwendung zwischengespeichert werden. Die Nutzung der PortletSession zur direkten Ablage als Attribut oder in einer vorhandenen SessionBean ist hierfür am besten geeignet. Das Ablegen der Liste als Attribut des ActionRequests funktioniert dagegen nicht, da das aktuelle Portlet anschließend einen "neuen" RenderRequest aufbaut (das Portlet Document Browser löste selbst keinen ActionRequest aus).

Teil 1   Teil 2   Teil 3   

Kommentare