Problema:vorreste poter aggiungere degli attributi custom alle vostre entità a runtime, ma non sapete come fare.
Soluzione:usate le expando tables di Liferay! ;)
Per farlo dovete procedere in questo modo:
- Registrare l'entità perchè utilizzi il framework delle expando
- Predisporre la JSPper mostrare i campi expando
- Predisporre la action per salvare i campi expando
Per registrare un'entità custom al fine di poterla "collegare" alle tabelle expando, dobbiamo creare una classe che estenda com.liferay.portlet.expando.model.BaseCustomAttributesDisplay
Questa classe, infatti, contiene tutta la logica che serve per poter gestire l'interfaccia nel pannello di controllo sulla parte dei custom fields.
Questa è l'implementazione della nostra classe:
package it.dvel.stupid.custom.display;
import it.dvel.stupid.custom.model.*;
import com.liferay.portal.theme.*;
import com.liferay.portlet.expando.model.*;
public class SimpleTableCustomAttributesDisplay extends
BaseCustomAttributesDisplay {
public static final String CLASS_NAME =
SimpleTable.class.getName();
// Qui gli diciamo come si chiama la nostra classe
public String getClassName() {
return CLASS_NAME;
}
// Qui gli diciamo dove trovare l'icona che deve
//usare per la nostra entità
public String getIconPath(ThemeDisplay themeDisplay) {
return themeDisplay.getPathThemeImages() +
"/common/user_icon.png";
}
}
Una volta creata la nostra classe, dobbiamo dire a Liferay di caricarla quando installiamo il nostro portlet.
Come sempre, dobbiamo andarla a mappare nel liferay-portlet.xml
dentro a WEB-INF
<portlet>
<portlet-name>helloworldportlet</portlet-name>
<icon>/icon.png</icon>
...
<custom-attributes-display>
it.dvel.stupid.custom.display.SimpleTableCustomAttributesDisplay
</custom-attributes-display>
...
</portlet>
Ok: a questo punto siamo pronti per mostrare nella nostra pagina i campi. Tenete presente che quello che stiamo per fare serve solamente per estrarre gli attributi. Non stupitevi quando, provando, non li vedrete: se non andate prima nel pannello di controllo ad inserire i campi custom, è normale che poi non li vediate.. ;)
Comunque, andate nella vostra JSP e incollate questo codice:
<h3><liferay-ui:message key="custom-fields" /></h3>
<aui:fieldset>
<liferay-ui:custom-attribute-list
className="it.dvel.stupid.custom.model.SimpleTable"
classPK="<%= (myEntity != null)?myEntity.getPrimaryKey():0 %>"
editable="<%= true %>"
label="<%= true %>"
/>
</aui:fieldset>
Ovviamente questo va all'interno di un campo form, perche' dopo i valori che l'utente immetterà dovranno essere passati in post alla nostra action.
Non commento la tag library perchè mi pare sia self explanatory.. ;)
Interessante notare, tuttavia, che posso scegliere di mostrare la lista degli attributi editabile o meno; in questo modo, mettendo true
o false
, posso scegliere come il componente deve renderizzare i miei campi.
Molto bene! A questo punto siamo pronti per salvare i valori immessi dagli utenti sull'interfaccia generata dalla nostra JSP.
Bene, tenetevi forte amici, perchè è qui che si vede tutta la potenza di un framework applicativo come Liferay! ;)
Questo è il codice che salva i valori immessi nel database:
// Ovviamente sono all'interno di un metodo di tipo processAction()..
//
Per prima cosa mi serve una istanza di ServiceContext
ServiceContext serviceContext =
ServiceContextFactory.getInstance(
SimpleTable.class.getName(), actionRequest);
SimpleTable table =
SimpleTableLocalServiceUtil.createSimpleTable(
CounterLocalServiceUtil.increment(SimpleTable.class.getName()));
// Faccio tutte le mie set sulla mia entità
...
// Ed ecco dove accade la magia! ;)
table.setExpandoBridgeAttributes(serviceContext);
// Poi faccio la insert
SimpleTableLocalServiceUtil.updateSimpleTable(table, false);
That's it!:)
Abbiamo salvato i valori che l'utente immette nella form con uno sforzo minimo! ;)
Come abbiamo fatto?!
La magia accade all'interno dell'oggetto ServiceContext
. In breve, questo oggetto è l'implementazione di un pattern che ci consente di avere delle funzionalità common a più oggetti senza avere l'onere di estendere una classe padre.
Come vedete, il framework offre delle utility per accedere ad una istanza di questo oggetto a partire da una request; questo ci offre il vantaggio di disinteressarci completamente della logica di popolamento di questo oggetto, perchè gestita direttamente dal framework, ma ci consente di beneficiare enormemente delle sue funzionalità.
Nello specifico, il serviceContext
è l'oggetto all'interno del quale io posso trovare, ad esempio, il companyId
o lo scopeGroupId
in cui l'utente stà operando.
Altra funzionalità molto importante del serviceContext
, ad esempio, è la gestione trasparente dei tags
e delle categories
che l'utente può scegliere dall'interfaccia di Liferay, ma di questo parlerò più diffusamente in un post successivo! :)
Alla prossima! :)
Referenze