Eclipse Stuff

Just another WordPress.com weblog

Archiv für die Kategorie ‘allgemein’

About Text in einer Properties-Datei

Verfasst von splitshade am März 28, 2009

Es gibt manche Dinge, die vergisst man aus unerfindlichen Gründen immer wieder.

Bei mir gehört das Laden eines About-Textes aus einer Properties-Datei dazu… Deswegen hier für immer und alle Zeit:

properties

Dann einfach im Workspace eine Datei plugin.properties anlegen und in dieser u.a. die Property

aboutText mit dem entsprechenden Wert angeben.

Zusätzlich in der plugin-xml für die Product-Definition die Property angeben:

<property
name=“aboutText“
value=“%aboutText“/>

Vergess ich immer wieder… echt strange.

Btw. weitere interessante Properties, die ich gerne vergesse sind:

<property
name=“aboutImage“
value=“myimage.gif“/>

<property
name=“preferenceCustomization“
value=“plugin_customization.ini“>

Veröffentlicht in allgemein | Kommentar schreiben »

Java Annotation Processing

Verfasst von splitshade am Februar 25, 2009

Kürzlich habe ich aus einer Laune heraus den Java6-Annotation Processor angeworfen. Hier steht wie´s funktioniert (was für ein cooles Teil!)

Die Definition einer Annotation ist hierbei denkbar einfach (@interface statt interface),

Methoden können Return-Values von primitives, Strings, Class und Enum haben.

public @interface Expensive {

int amount();
boolean rare();
}

Wo und wann Annotations eingesetzt werden können dürfte mittlerweile bekannt sein. Die Verwendung der soeben deklarierten Annotation könnte wie folgt aussehen (Das JDT greift zu diesem Zeitpunkt schon)

@Expensive(amount=5,rare=true)
public class Mantel implements Artikel{

private String description;
private int prize;

public Mantel(String desc, int prize){
this.description = desc;
this.prize = prize;
}

@Override
public String getDescription() {
return description;
}
@Override
public int getPrize() {
return prize;
}
}

Per Default wird ein Wert, wenn er der einzige ist, mit Value bezeichnet (Convention).

public @interface Artikeltyp {
String value();
}

Das hat den Vorteil, dass man das „=“ vernachlässigen kann.

@Artikeltyp(„Winter“)

Das Annotation-Framework bietet Meta-Annotations

@RetentionPolicy

annotations

@Retention(RetentionPolicy.RUNTIME) heißt, dass die Annotations zur Runtime ausgewertet werden (und auch verfügbar sein sollen)

@Retention(RetentionPolicy.CLASS) heißt, dass die Annotations in der Klasse verfügbar sein sollen, aber nicht zur Laufzeit

@Retention(RetentionPolicy.SOURCE) heißt, dass der Compiler die Annotations rausschmeißt.

annotations2

@Target(ElementType.METHOD) sagtaus, dass nur Methoden annotiert werden können (etc..)

Das ganze kann jetzt ganz einfach über Reflection ausgelesen werden.

Class<?> clazz = Class.forName(„Mantel“);
for(Method m : clazz.getMethods()){
if(m.isAnnotationPresent(Expensive.class)){
System.out.println(„Annotated“);
Expensive annotation = m.getAnnotation(Expensive.class);
System.out.println(annotation.amount());
}
}

Weitere interessante Annotation-Typen sind

@SupportedAnnotationTypes(value = { „de.md.*“ })

@SupportedSourceVersion(SourceVersion.RELEASE_6)

Noch interessanter ist die Verwendung der Klasse Processor.

@SupportedAnnotationTypes({„de.md.annotations.Artikel“})
public class ArtikelProcessor extends AbstractProcessor{

@Override
public boolean process(Set<? extends TypeElement> arg0,
RoundEnvironment env) {
Set set =  env.getRootElements();
return false;
}
}

Der Processor kriegt ein Set vom Typ TypeElement und ein Element vom Typ RoundEnvironment in der Methode process(..)unbenannt-6annots3

Das RoundEnvironment bietet ZUgriff auf den Vorgang es prozessierens und hierfür Methoden wie getElementsAnnotatedWith(..) und processingOver().

Das war eine erste kleine Einführung, mehr zum Thema mit einem sinnvollen Beispiel folgt demnächst.

(ein einfaches Beispiel für die Verwendung eines Processors findet sich z.B. bei Kai Toedter für den OSGI DS Annotation Processor, danke Kai!!)

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
null, null, null);
Iterable<? extends JavaFileObject> compilationUnits1 = fileManager
.getJavaFileObjects(testFileDirectory + filename);
CompilationTask task = compiler.getTask(null, fileManager, null, null,
null, compilationUnits1);
LinkedList<AbstractProcessor> processors = new LinkedList<AbstractProcessor>();

Processor processor = new Processor();
processor.setOutputDir(„OSGI-INF“);
processors.add(processor);
task.setProcessors(processors);
return task.call();

Veröffentlicht in allgemein | Kommentar schreiben »

The Mysterious Table Viewer

Verfasst von splitshade am Februar 18, 2009

Heute soll es um meinen speziellen Freund, den „TableViewer“ gehen, speziell darum, wie man einen TableViewer implementiert, der unter Umständen etwas komplexer ist (mit Comboboxen etc…).

Witzigerweise ist es nämlich wie mit beinahe allem, es gibt hierzu keine brauchbaren Tutorials, also muss man sich selbst helfen und die try-and-error-Variante fahren.

Da ich mich eine Zeitlang wirklich enorm über dieses Thema geärgert habe, habe ich beschlossen, dieses Thema in einem kleinen Eintrag zu erläutern (nicht zuletzt für mich selbst, damit ich beim nächsten Mal weiß wo ich nachzuschauen habe).

Als Beispiel implementieren wir einfach mal einen TableViewer, der einer Liste einer bestimmten Person aus einer Liste eine bestimmte Rolle zuordnen kann.

Hierzu bauen wir uns zuerst wieder das typische Personen-Modell zusammen:

Klasse Person:

public class Person {

private String name;

private Rolle rolle;

public Person(String name, Rolle rolle) {

super();

this.name = name;

this.rolle = rolle;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Rolle getRolle() {

return rolle;

}

public void setRolle(Rolle rolle) {

this.rolle = rolle;

}

public String toString() {

return getName() + getRolle().toString();

}}

Enum Rolle:

public enum Rolle {

ADMIN, CUSTOMER, USER

}

Klasse PersonService:

public class PersonService implements IPersonService {

private static PersonService service = new PersonService();

private IObservableList persons = new WritableList();

public PersonService() {

persons.add(new Person(„Hans“, Rolle.ADMIN));

persons.add(new Person(„Fritz“, Rolle.CUSTOMER));

persons.add(new Person(„Gerhard“, Rolle.USER));

persons.add(new Person(„Harald“, Rolle.ADMIN));

}

@SuppressWarnings(„unchecked“)

public List<Person> getPersons() {

return (List<Person>) Collections.checkedList(persons, Person.class);

}

public IObservableList observePersons() {

return persons;

}

public void addPerson(Person person) {

persons.add(person);

}

public static PersonService getInstance() {

return service;

}

public List<Rolle> getRollen() {

return Arrays.asList(Rolle.values());

}

}

Zusätzlich bauen wir einen View, der eine Tabelle bereitstellt, die:

  1. Alle User anzeigt
  2. Die Möglichkeit bietet, die Rolle eines Users zu ändern
  3. Die Möglichkeit bietet, neue User anzulegen
  4. Mit Databinding arbeitet

Zunächst mal bearbeiten wir die createPartControl-Methode des Views, und legen einen TAbleViewer an:

final TableViewer viewer = new TableViewer(container);

viewer.getTable().setHeaderVisible(true);

viewer.getTable().setLinesVisible(true);

Der TableViewer soll 2 Columns haben (Person und Rolle):

TableViewerColumn person = new TableViewerColumn(viewer, SWT.BORDER);

person.getColumn().setText(„Person“);

person.getColumn().setWidth(100);

TableViewerColumn rolle = new TableViewerColumn(viewer, SWT.BORDER);

rolle.getColumn().setText(„Rolle“);

rolle.getColumn().setWidth(100);

Nun setzen wir den Label- und ContentProvider. Da wir mit DataBinding arbeiten, bietet sich der ObservableListContenentProvider an (der übrigens ausgezeichnet funktioniert!!)

Damit das jedoch richtig funktioniert, passen wir den PersonService folgendermaßen an:

public class PersonService implements IPersonService {

private IObservableList persons = new WritableList();

public PersonService() {

persons.add(new Person(„Hans“, Rolle.ADMIN));

persons.add(new Person(„Fritz“, Rolle.CUSTOMER));

persons.add(new Person(„Gerhard“, Rolle.USER));

persons.add(new Person(„Harald“, Rolle.ADMIN));

}

@SuppressWarnings(„unchecked“)

public List<Person> getPersons() {

return (List<Person>)Collections.checkedList(persons, Person.class);

}

public IObservableList observePersons(){

return persons;

}

public void addPerson(Person person) {

persons.add(person);

}

public static PersonService getInstance() {

return new PersonService();

}

}

Jetzt können wir die ObservableList aus dem Service direkt als Input in den TableViewer verwenden, und alle Änderungen an der PersonenListe werden sofort in der Tabelle widergespiegelt.

viewer.setLabelProvider(new LabelProvider());

viewer.setContentProvider(new ObservableListContentProvider());

viewer.setInput(PersonService.getInstance().observePersons());

Startet man die Anwendung jetzt, sieht das ungefähr so aus:

tableviewer

Zumindest ist es eine Tabelle…

Ok, wir müssen natürlich definieren, in welche Spalte welche Werte angezeigt werden sollen, das erledigt der LabelProvider, also ändern wir das folgendermaßen ab:

viewer.setLabelProvider(new ITableLabelProvider() {

@Override

public Image getColumnImage(Object element, int columnIndex) {

return null;

}

@Override

public String getColumnText(Object element, int columnIndex) {

switch (columnIndex) {

case 0:

return element.toString();

case 1:

return ((Person) element).getRolle().toString();

default:

return „“;

}

}

@Override

public void addListener(ILabelProviderListener listener) {

// TODO Auto-generated method stub

}

@Override

public void dispose() {

// TODO Auto-generated method stub

}

@Override

public boolean isLabelProperty(Object element, String property) {

// TODO Auto-generated method stub

return false;

}

@Override

public void removeListener(ILabelProviderListener listener) {

// TODO Auto-generated method stub

}

});

Noch eleganter wäre, nicht dem TableViewer an sich, sondern jeder Column einen eigenen LabelProvider zur Verfügung zu stellen.

column.setLabelProvider(new ColumnLabelProvider(){

}

Wie dem auch sei, Neuer Versuch:

tableviewer_21

Ok, was wir jetzt aber wollen, ist zum Einen, dass man den Namen der Person editieren kann (durch einfache Eingabe) und zum Anderen wollen wir die Rolle über eine ComboBox auswählen.

Jetzt wirds spannend, weil hier die Dokumentation im Web mehr als spärlich wird.

Eclipse bietet hierzu die Klasse „EditingSupport“, der JavaDoc Kommentar ist hierzu mehr als sprechend:

„EditingSupport is the abstract superclass of the support for cell editing.“

Spitze! und so zieht sich das durch, man findet kein!! ich wiederhole : KEIN wirklich brauchbares Beispiel im Web, bis heute!!

Ok, zurück zum Thema:

Was das Editieren von Columns in einer Tabelle ermöglicht sind sogenannte CellEditoren. Diese Editoren können Text-, COmbo-,Checkbox etc.. sein.

Was uns hier interessiert ist zum Einen der Texteditor zum Eingeben des Personennamens und ein Comboeditor zum Eingeben der Rolle.

Zunächst die Namenseingabe:

person

.setEditingSupport(new ObservableValueEditingSupport(viewer,

ctx) {

private TextCellEditor textEditor;

@Override

protected IObservableValue doCreateCellEditorObservable(

CellEditor cellEditor) {

return SWTObservables.observeText((Text) cellEditor

.getControl(), SWT.Modify);

}

@Override

protected IObservableValue doCreateElementObservable(

Object element, ViewerCell cell) {

return BeansObservables.observeValue(element, „name“);

}

@Override

protected CellEditor getCellEditor(Object element) {

if (textEditor == null) {

textEditor = new TextCellEditor((Composite) viewer

.getControl());

}

return textEditor;

}

});

Man sieht, im Prinzip muss man nur 2 Methoden implementieren, die jeweils ein ObservableValue für den CellEditor (also entweder ein Text oder eine Combo) bereitstellt, und eine Methode, die ein ObservableValue für das beabachtete Objekt (in diesem Fall ein Person-Objekt bereitstellt).

Klickt man jetzt auf ein Feld in der Tabelle ändert sich dieses in ein Text-Feld und man kann den Wert editieren!

tableviewer_3

Problem ist, drückt man jetzt auf Enter wird zwar der Wert im Modell geändert, nicht jedoch automatisch der Viewer refreshed, d.h. dass weiterhin der alte Wert angezeigt wird, wenn man sich nicht im Edit-Modus befindet.

Hierzu kann man folgenden Listener registrieren, der das bewerkstelligt.

viewer.getColumnViewerEditor().addEditorActivationListener(

new ColumnViewerEditorActivationListener() {

@Override

public void afterEditorActivated(

ColumnViewerEditorActivationEvent event) {

// TODO Auto-generated method stub

}

@Override

public void afterEditorDeactivated(

ColumnViewerEditorDeactivationEvent event) {

viewer.refresh();

}

@Override

public void beforeEditorActivated(

ColumnViewerEditorActivationEvent event) {

// TODO Auto-generated method stub

}

@Override

public void beforeEditorDeactivated(

ColumnViewerEditorDeactivationEvent event) {

// TODO Auto-generated method stub

}

});

So, weiter gehts mit der Rollen-Column, hier haben wir im Prinzip nochmals das Gleiche Prozedere, nur dass wir hier einen ComboViewer in einem TableViewer verbauen wollen.

rolle.setEditingSupport(new ObservableValueEditingSupport(viewer, ctx) {

private ComboBoxViewerCellEditor cellEditor;

@Override

protected IObservableValue doCreateCellEditorObservable(

CellEditor cellEditor) {

return ViewersObservables

.observeSingleSelection(((ComboBoxViewerCellEditor) cellEditor)

.getViewer());

}

@Override

protected IObservableValue doCreateElementObservable(

Object element, ViewerCell cell) {

return BeansObservables.observeValue(element, „rolle“);

}

@Override

protected CellEditor getCellEditor(Object element) {

if (cellEditor == null) {

cellEditor = new ComboBoxViewerCellEditor(

(Composite) viewer.getControl());

cellEditor.setContenProvider(new ArrayContentProvider());

cellEditor.setLabelProvider(new LabelProvider());

cellEditor.setInput(Rolle.values());

}

return cellEditor;

}

});

tb4

Ok, zuletzt brauchen wir noch die FUnktionalität, eine neue Person anzulegen.

Hierzu hätte ich gerne ein Contextmenü. DAs ist ganz einfach realisiert:

private void initContextMenu() {

MenuManager manager = new MenuManager();

viewer.getControl().setMenu(

manager.createContextMenu(viewer.getControl()));

manager.add(new Action(„Person hinzufügen“) {

@Override

public void run() {

PersonService.getInstance().addPerson(

new Person(„“, Rolle.USER));

viewer.refresh();

}

});

}

tb51

By the way, es hindert uns hier auch nichts daran, dieses Context Menü über das Menüframework zu erweitern.

Hierzu müssen wir lediglich das Menü über die ViewSite registrieren, damit wir global darauf zugreifen können.

getSite().registerContextMenu(mgr,null);

Zu beachten ist hier lediglich, dass innerhalb eines Parts jedes ContextMenu unter der ID des Parts registriert wird.

Um das Context Menü deklarativ zu bevölkern braucht man jetzt nur noch etwas wie:

<menuContribution
locationURI=“popup:de.md.commands.menuview“>
<command
commandId=“de.md.commands.helloworld“
label=“Hallo Popup“
style=“push“>
</command>
</menuContribution>


Mit einem Viewer, der den EditorSupport verwendeet, hat man das Problem, dass dieser voraussetzt, dass
der TableViewer mit dem Flag „SWT.FULL_SELECTION“ erzeugt wurde.
Oft ist es aber nicht erwünscht, dass man die ganze Zeile selektiert, sondern oft möchte man nur eine einzelne
Zelle selektieren (am besten noch so wenig wie möglich mit der Maus sondern per Tastatur).
Hier stösst man schnell an die Grenzen des mit dem normalen Tableviewer machbaren.

Doch wie so oft gibt es hier einige mehr als nützliche Klassen, die ich im folgenden mal kurz dokumentieren möchte.

final TableViewerFocusCellManager focusCellMgr = new TableViewerFocusCellManager(
viewer, new FocusCellOwnerDrawHighlighter(viewer));

Der TableViewerFocusCellManager bietet die Möglichkeit, das Highlighting der Zellen anzupassen, damit nicht immer
die gesamte Zeile markiert ist, sondern nur diejenige, die wir gerade auch wirklich selektiert haben. Das macht der
FocusCellOwnerDrawHighlighter für uns. Die genauere Funktionsweise dahinter braucht uns zunächst nicht zu interessieren,
da diese Zeile schon alles macht, was wir brauchen.

Weiter gehts:
ColumnViewerEditorActivationStrategy actStrategy = new ColumnViewerEditorActivationStrategy(
viewer) {
protected boolean isEditorActivationEvent(
ColumnViewerEditorActivationEvent event) {
return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_CLICK_SELECTION
|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED);
}

};

Hier wirds dann interessant, denn oft hat man von Fachbereichen die Anforderung, ich möchte aber, dass wenn ich hier auf Enter drücke (oder hoch, oder runter, oder was ganz anderes), dass dann die Combobox aufgeht….
Hierfür gibts so etwas wie eine ColumnViewerEditorActivationStrategy.
Die hat eine CallbackMethode isEditorActivationEvent, die im Prinzip bei jeder User-Interaktion überprüft, ist das Event gewünscht um den Viewer
zu triggern? Wenn ja, CellEditor aktivieren, wenn nein… weiter.
Im obigen Beispiel verwenden wir das Durchlaufen mit Tab (Traversal), MouseEvents und KeyEvents als Activation Events für den Celleditor.

Das ganze binden wir jetzt noch an unseren TableViewer

TableViewerEditor.create(viewer, focusCellMgr, actStrategy,
ColumnViewerEditor.TABBING_HORIZONTAL
| ColumnViewerEditorActivationEvent.TRAVERSAL
| ColumnViewerEditor.KEYBOARD_ACTIVATION);

Hier hat man zusätzlich noch die Möglichkeit, über Flags zu konfigurieren, wie die einzelnen Zellen durchlaufen werden sollen.

ColumnViewerEditor.TABBING_HORIZONTAL
Bei durchlaufen mit Tab soll immer eine Zelle horizontal weitergesprungen werden.

ColumnViewerEditor.KEYBOARD_ACTIVATION
KeyboardActivation einschalten

ColumnViewerEditorActivationEvent.TRAVERSAL
CellAktivierung beim Durchlaufen einschalten.

Das ist so einfach!! und funktioniert wunderbar, nur ein Problem gibts damit. Wenn man das Horizontale Tabbing einschaltet, dann kommt man
mit Tab nie wieder aus dem TableEditor heraus. Wenn jemand hierfür eine brauchbare Lösung hat, bitte immer her damit!!

Veröffentlicht in allgemein, cool eclipse | 13 Kommentare »

Portlet-Kurzreferenz

Verfasst von splitshade am Oktober 16, 2008

Ich habe mir kürzlich mal einige NOtizen zu Portlets gemacht, da dieser Blog mir als Notizblock dient, hier die Notizen

Portlet-Konfiguration

Portlets haben einen eigenen Deployment-Deskriptor – portlet.xml.

Dieser befindet sich im Verzeichnis WEB-INF.

Eine typische Konfiguration sieht so aus:

<portlet-app

xmlns=„http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd“

version=„1.0″ xmlns:xsi=„http://www.w3.org/2001/XMLSchema-instance“

xsi:schemaLocation=„http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd“>

<portlet id=„Pentasys_Login_Portlet“>

<portlet-name>PLoginPortlet</portlet-name>

<display-name>PENTASYS Login Portlet</display-name>

<portlet-class>

com.sun.faces.portlet.FacesPortlet

</portlet-class>

<!– <portlet-class>de.pentasys.myfaces.portlet.MyFacesGenericPortlet</portlet-class> –>

<init-param>

<name>default-view</name>

<value>/pages/index.jsp</value>

</init-param>

<init-param>

<description></description> <name>com.sun.faces.portlet.INIT_VIEW</name>

<value>/pages/index.jsp</value>

</init-param>

<init-param>

<description></description> <name>com.sun.faces.portlet.INIT_EDIT</name>

<value>/pages/edit.jsp</value>

</init-param>

<supports>

<mime-type>text/html</mime-type>

<portlet-mode>VIEW</portlet-mode>

</supports>

<portlet-info>

<title>Pentasys Login Portlet</title>

<short-title>Pentasys Login Portlet</short-title>

<keywords>Pentasys Login Portlet</keywords>

</portlet-info>

</portlet>

</portlet-app>

Interessant hierbei ist der Tag <Portlet-Info>, da hier Meta-Informationen wie Titel etc.. angegeben werden können.

§ Der Tag <Portlet-Class> gibt die jeweilige Portlet-Klasse an (in diesem Fall ein BridgePortlet zur Verwendung von JSF)

§ Der Tag <init-param> kann benutzt werden, um init-Parameter an das Portlet zu übergeben.

§ Soll ein Resource-Bundle genutzt werden, kann dies mit dem Tag
<resource-bundle>com.foo.myApp.QuotePortlet</resource-bundle> geschehen.

Portlet-URL

Es gibt 2 URL-Typen – ActionURL und RenderURL.

Hiermit wird eine URL erzeugt, die den Portlet-Container entweder veranlasst, die processAction… oder die render.. Methoden aufzurufen. Um eine URL zu erstellen kann die create<..>URL – Methoden eines renderResponse-Objektes genutzt werden.

Innerhalb einer URL kann ebenfalls der PortletMode und die WindowState-Parameter gesetzt werden.

Standard-Portlet-Modes sind VIEW, EDIT und HELP. Eigene Modes können implementiert werden.

Welche Modi ein Portlet unterstützt wird im Deployment-Deskriptor festgelegt, mit Hilfe des Tags

<supports>

<mime-type>text/html</mime-type>

<portlet-mode>VIEW</portlet-mode>

</supports>

Unterstütze Window States sind NORMAL, MAXIMIZED und MINIMIZED.

Portal-Context

Jedes Portlet hat einen eigenen Context. Daten eines PortletContextes werden im ServletContext gespeichert, d.h. Portlets haben Zugriff auf Servlet-Daten und umgekehrt.

Portlet-Request

Über den Portlet-Request lassen sich Sicherheitsinformationen erfragen:

getAuthType()

getRemoteUser()

getUserPrincipal()

isUserInRole()

isSecure()

- Die Methode getAuthType liefert einen der möglichen Werte (BASIC_AUTH, DIGEST_AUTH, CERT_AUTH and FORM_AUTH)

- Die Methode getRemoteUser liefert den UserNamen des Benutzers der den Request abgesetzt hat.

- getUserPrincipal liefert ein Objekt vom Typ java.security.Principal mit dem Namen des Benutzers.

Portlet-Response

Über den Response kann ein Redirect veranlasst werden, mit der Methode „sendRedirect()“.

Preferences

Zum Verwalten von Preferences bietet ein Portlet die Klasse „PortletPreferences“.

Bsp:

PortletPreferences prefs = req.getPreferences();

String[] symbols =

prefs.getValues(”preferredStockSymbols”,

new String[]{”ACME”,”FOO”});

String 5 url = prefs.getValue(”quotesFeedURL”,null);

int refreshInterval =

Integer.parseInt(prefs.getValue(”refresh”,”10”));

Der Zusätliche Parameter jeweils ist ein Default-Value der zurückgegeben wird, wenn der angeforderte Wert nicht vorhanden ist.

Preferences sind Benutzerspezifisch und sollten nicht zwischen Benutzersessions geteilt werden.

Es ist möglich, für Preferences Default-Values im Deployment-Deskriptor zu übergeben.

<portlet-preferences>

<preference>

<name>PreferredStockSymbols</name>

<value>FOO</value>

<value>XYZ</value>

<read-only>true</read-only>

</preference>

<preference>

<name>quotesFeedURL</name>

<value>http://www.foomarket.com/quotes</value>

</preference>

</portlet-preferences>

</portlet>

Preferences können validiert werden, hierfür muss eine Klasse vom Typ PreferencesValidator implementiert werden und anschliessend im DeploymentDeskriptor registriert werden.

<portlet-preferences>

<preferences-validator>

com.foo.portlets.XYZValidator

</preferences-validator>

</portlet-preferences>

Sessions

Für das Session-Management bei Portlets gibt es 2 Scopes (APPLICATION- und SESSION-SCOPE).

Attribute im SessionScope bleiben gültig, solange man sich im gleichen PortletWindow befindet.

Dispatching

Ein Request-Dispatcher kann vom PortletContext über die Methode getRequestDispatcher(<Pfad>) erfragt werden. Der Pfad ist relativ zum Root des Contextes und muss mit einem „/“ beginnen.

Über die Methode getNamedDispatcher(<name>) kann ein Dispatcher für ein bekanntes Servlet erfragt werden.

Um ein Servlet- oder eine JSP-Seite zu inkludieren wird die Methode include(..) eines Request-Dispatchers aufgerufen.

Security

Die zuvor beschriebene Methode isUserInRole(..) kann benutzt werden, um zu prüfen ob ein user eine bestimmte Benutzerrolle innehat. Hierzu muss im Deployment-Deskriptor folgender Tag vorhanden sein.

<portlet>

<security-role-ref>

<role-name>FOO</role-name>

<role-link>manager</manager>

</security-role-ref>

</portlet>

Das Element<role-link> wird dazu benutzt, um einen Rollennamen auf eine im web.xml deployment-deskriptor angegebene rolle zu mappen. Wird dieses Element nicht angegeben, wird automatisch versucht, eine definierte Rolle mit dem im element <role-name> angegebenen value zu finden. Die hier definierten Rollen können als Argument für die Methode isUserInRole(..) genutzt werden.

Portlets können mit User-Constraints geschützt werden.

<security-constraint>

<display-name>Secure Portlets</display-name>

<portlet-collection>

<portlet-name>accountSummary</portlet-name>

</portlet-collection>

<user-data-constraint/>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

</security-constraint>

Tag-Lib

Es gibt eine TagLib zur Verwendung innerhalb von JSP-Seiten.

<%@ taglib uri=”http://java.sun.com/portlet” prefix=”p” %>

Über den Tag “<p:defineObject/>” warden nun die Objekte “renderRequest”,“renderResponse” und „portletConfig“ zur Verfügung gestellt.

Weiterhin kann über den Tag <p:actionURL/> und <p:renderURL/> eine jeweilige Action/oder RenderURL generiert werden.

Parameter für actionURL sind windowState, portletMode.

<portlet:actionURL windowState=”maximized” portletMode=”edit”>

<portlet:param name=”action” value=”editStocks”/>

</portlet:actionURL>

Veröffentlicht in allgemein, portlet | Kommentar schreiben »