Forums

Home » Liferay Portal » Deutsch

Combination View Flat View Tree View
Threads [ Previous | Next ]
toggle
Rüdiger Kowalski
Liferay Web Content mit eigenem JSF-Portlet anzeigen
August 16, 2011 5:10 AM
Answer

Rüdiger Kowalski

Rank: New Member

Posts: 22

Join Date: August 16, 2011

Recent Posts

Ich habe ein Portlet mit einer mehrseitigen Wizard-Komponente (PrimeFaces-Wizard) entwickelt. Die erste Seite des Wizards soll diverse Informationen (Text, Grafik, etc.), anzeigen, die von einem Administrator individuell gepflegt werden. Für die Pflege dieser Informationen ist der Liferay Web Content angedacht. Die erste Seite des Wizards soll aus meinem JSF-Portlet (XHTML-Datei) versorgt werden.

Kann man Web Content überhaupt mittels JSF lesen? Falls ja, kann jemand beschreiben, wie es funktioniert?

----------------------------------------------------------------------------------------------------------------------------------------------------
Liferay 6.0.6, Mojarra 2.0.3, Primefaces 3.0.M3-SNAPSHOT, Tomcat 6.0.29, Eclipse Helios SR2, IE 9, Firefox 5
Morad Ahmad
RE: Liferay Web Content mit eigenem JSF-Portlet anzeigen
August 16, 2011 11:26 AM
Answer

Morad Ahmad

Rank: Junior Member

Posts: 37

Join Date: June 16, 2010

Recent Posts

Hallo,

ich versuche dasselbe zu tun. Leider ist es nicht so schön. Ich mache folgendes:


Structure:

<root>
<dynamic-element name='title' type='text' index-type='text'
repeatable='false'></dynamic-element>
<dynamic-element name='abstract' type='text_area'
index-type='' repeatable='false'></dynamic-element>
<dynamic-element name='html' type='text_area'
index-type='' repeatable='false'></dynamic-element>
<dynamic-element name='image1' type='image' index-type=''
repeatable='false'></dynamic-element>
</root>


/**
* Super class for all Journal beans
*
*
* @author Administrator
*
*/
public abstract class BaseJournalBean implements Serializable {

private static final long serialVersionUID = -2975276307859233410L;

protected JournalArticle ja;

public BaseJournalBean(JournalArticle ja) {
super();
this.ja = ja;
}

/**
* @return fields of structure
*/
public abstract String[] getFields();

public abstract String getStructureId();

public abstract void setValue(String field, String value);

/**
* @return true if the bean has all its required values.
*/
public abstract boolean hasvalidValues();

public abstract ContentBeanInfo getBeanInfo();

public long getGroupId() {
return ja.getGroupId();
}

public long getCompanyId() {
return ja.getCompanyId();
}

public String getUserName() {
return ja.getUserName();
}

public Date getCreateDate() {
return ja.getCreateDate();
}

public String getArticleId() {
return ja.getArticleId();
}

public String getTitle() {
return ja.getTitle();
}

public String getDescription() {
return ja.getDescription();
}

public boolean getSmallImage() {
return ja.getSmallImage();
}

}



/**
* Eine Meldung im CMS.
*
* @author Administrator
*
*/
@ContentBean(structure = "STR_MELDUNG")
public class Meldung extends BaseJournalBean implements Serializable {

/**
*
*/
private static final long serialVersionUID = 7589363148185610410L;

public static final String[] fields = { "title", "abstract", "html", "image1" };

public static final String STRUCTURE_ID = "STR_MELDUNG";

public static final String DISPLAY_TEMPLATE = "TEMPLATE_MELDUNG";

public static final String LIST_TEMPLATE = "TEMPLATE_MELDUNG";

@ContentField(name = "title", type = "String")
private String title;

@ContentField(name = "abstract", type = "String")
private String anabstract;

@ContentField(name = "html", type = "String")
private String html;

@ContentField(name = "image1", type = "String")
private String image1;

private BeanInfoImpl beanInfo;

public Meldung(JournalArticle ja) {
super(ja);
}

public String getAnabstract() {
return anabstract;
}

@Override
public String[] getFields() {
return fields;
}

public String getHtml() {
return html;
}

public String getImage1() {
return image1;
}

@Override
public String getStructureId() {
return STRUCTURE_ID;
}

public String getTitle() {
return title;
}

@Override
public boolean hasvalidValues() {
return true;
}

public void setAnabstract(String anabstract) {
this.anabstract = anabstract;
}

public void setHtml(String html) {
this.html = html;
}

public void setImage1(String image1) {
this.image1 = image1;
}

public void setTitle(String title) {
this.title = title;
}

@Override
public void setValue(String field, String value) {
if (fields[0].equalsIgnoreCase(field))
setTitle(value);
else if (fields[1].equalsIgnoreCase(field))
setAnabstract(value);
else if (fields[2].equalsIgnoreCase(field))
setHtml(value);
else if (fields[3].equalsIgnoreCase(field))
setImage1(value);

// ignore value:

}

@Override
public String toString() {
return "Meldung [title=" + title + ", anabstract=" + anabstract + ", html=" + html + ", image1=" + image1 + "]";
}

@Override
public ContentBeanInfo getBeanInfo() {
if (this.beanInfo == null) {
this.beanInfo = new BeanInfoImpl(fields);
for (String f : fields)
this.beanInfo.setType(f, "String");
}
return this.beanInfo;
}

}


public interface BeanFactory {

public BaseJournalBean newInstance(JournalArticle ja);

}

/**
* @author Administrator
*
*/
public abstract class BaseContentJSFBean implements Serializable {


private static final long serialVersionUID = 6820357155903009906L;

private List<BaseJournalBean> content;

protected BaseJournalBean selectedArticle;

public List<BaseJournalBean> getContent() {
if (content == null)
load();
return content;
}

private void load() {
LiferayFacesContext liferayFacesContext = LiferayFacesContext.getInstance();
Layout layout = liferayFacesContext.getLayout();
long communityId = LiferayUtils.getCommunityId(layout);
if (communityId > 0) {
try {
content = CMSBeanUtils.loadContent(communityId, getStructureId(), getBeanFactory());
} catch (SystemException e) {
e.printStackTrace();
} catch (PortalException e) {
e.printStackTrace();
}
}
}

protected abstract BeanFactory getBeanFactory();

protected abstract String getStructureId();

public BaseJournalBean getSelectedArticle() {
return selectedArticle;
}

public void setSelectedArticle(BaseJournalBean selectedArticle) {
this.selectedArticle = selectedArticle;
}

}

Das eigentliche JSF-Bean:

@Named("meldungenBean")
@Scope("session")
public class MeldungenBean extends BaseContentJSFBean {

private static final long serialVersionUID = -1630942351958472122L;

@Override
protected BeanFactory getBeanFactory() {
return new BeanFactory() {
@Override
public BaseJournalBean newInstance(JournalArticle ja) {
return new Meldung(ja);
}
};
}

@Override
protected String getStructureId() {
return Meldung.STRUCTURE_ID;
}

}


Und die utils Klasse:


/**
* Liferay CMS helper utils
*
* @author Administrator
*
*/
public class CMSBeanUtils {

// add methods for extracting beans according to catigories, tags, date, etc.

public static List<BaseJournalBean> loadContent(long communityId, String structureId, BeanFactory factory) throws SystemException,
PortalException {
List<BaseJournalBean> content = new ArrayList<BaseJournalBean>();
List<JournalArticle> _articles = JournalArticleLocalServiceUtil.getStructureArticles(communityId, structureId);
for (JournalArticle ja : _articles) {
String articleId = ja.getArticleId();
double lastVersion = JournalArticleLocalServiceUtil.getLatestVersion(communityId, articleId);
// only last version of journal article
if (ja.isApproved() && ja.getVersion() == lastVersion) {
BaseJournalBean cmsBean = factory.newInstance(ja);
CMSBeanUtils.setFields(ja, cmsBean);
if (cmsBean != null && cmsBean.hasvalidValues())
content.add(cmsBean);
}
}
return content;
}

/**
* Set Journal Article fields to a content bean.
*
* @param ja
* @param cmsBean
*/
public static void setFields(JournalArticle ja, BaseJournalBean cmsBean) {
Document document;
try {
LiferayFacesContext liferayFacesContext = LiferayFacesContext.getInstance();
Locale selectedLocale = liferayFacesContext.getLocale();
String content = ja.getContentByLocale(selectedLocale.getISO3Language());
if (content == null)
content = ja.getContentByLocale(ja.getDefaultLocale());
if (content != null) {
document = SAXReaderUtil.read(content);
Node fieldNode = null;
for (String field : cmsBean.getFields()) {
// TODO implement different methods according to type etc.
// and multi values properties as lists.
fieldNode = document.selectSingleNode("/root/dynamic-element[@name='" + field + "']/dynamic-content");
cmsBean.setValue(field, fieldNode.getText());
}
}
} catch (Exception e) {
;
}
}

}

und die XHTML-Dateien:

Zum Auflisten (meldungen.xhtml):

<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head></h:head>
<h:form id="articesList01">
<h:dataTable var="article" value="#{meldungenBean.content}" border="0">

<h:column>
<img src="#{article.image1}" />
</h:column>

<h:column>
<h6>
<h:outputText value="#{article.title}" />
</h6>

<h:outputText value="#{article.createDate}" />

<h:outputText value="#{article.anabstract}" escape="false" />
<br />

<br />

<div align="right">
<h:commandLink action="meldung.xhtml" value="mehr...">
<f:setPropertyActionListener value="#{article}"
target="#{meldungenBean.selectedArticle}" />
</h:commandLink>
</div>

<br />

</h:column>
</h:dataTable>
</h:form>
</f:view>

und einzelnes Dokument anzeigen (meldung.xhtml):

<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head></h:head>

<h:form id="articesList01">

<h6>
<h:outputText value="#{meldungenBean.selectedArticle.title}" />
</h6>
<img src="#{article.image1}" />
<br />
<h:outputText value="#{meldungenBean.selectedArticle.anabstract}"
escape="false" />
<br />
<h:outputText value="#{meldungenBean.selectedArticle.html}"
escape="false" />

<h:commandLink action="list.xhtml" value="zurück" immediate="true" />

</h:form>

</f:view>


ich versuche also anhand der StructureId die Dokumente über die Liferay API zu lesen und daraus Beans zu erzeugen. Man könnte daraus eine generische Lösung erstellen wo JSF-Komponenten direkt Web-Content darstellen (Ähnlich dem AssetPublisher). Also etwa: <cms:contentList structure="XYZ"><cms:property name="title" ..>...

Ich finde überhaupt das CMS in L. nicht zufriedenstellend. Man sollte über die API viel mehr erreichen können. Etwa die Beans etwa. Meldung z.B. über Annotation erzeugen sollen (ähnlich Hippo CMS). Ich habe noch keine bessere Lösung....

Gruß,
Morad.
Rüdiger Kowalski
RE: Liferay Web Content mit eigenem JSF-Portlet anzeigen
August 17, 2011 2:37 AM
Answer

Rüdiger Kowalski

Rank: New Member

Posts: 22

Join Date: August 16, 2011

Recent Posts

Hallo Morad,
vielen Dank für Deine ausführlichen Hinweise, die mir sehr geholfen haben. Dadurch konnte ich gezielter analysieren und ich habe eine Lösung für mein Vorhaben gefunden.

Dies ist die Vorgehensweise, um den kompletten Inhalt aus einem Liferay web content zu lesen:

1. Falls noch nicht geschehen, einen Web-Content-Eintrag mit einem eindeutigen Titel anlegen.

2. In der JSF-Seite folgenden Tag verwenden.
<h:outputText value="#{backingBean.webContent}" escape="false" />

3. In der Backing-Bean folgende Methoden verwenden.
public String getWebContent()
{
return readWebContent("xxx");
}

xxx = eindeutiger Titel des Web-Content-Eintrags
private String readWebContent(final String title)
{
final FacesContext context = FacesContext.getCurrentInstance();
final ThemeDisplay themeDisplay = (ThemeDisplay) context.getExternalContext().getRequestMap().get(WebKeys.THEME_DISPLAY);
try
{
final long groupId = themeDisplay.getScopeGroupId();
final JournalArticle article = JournalArticleLocalServiceUtil.getArticleByUrlTitle(groupId, title);
final String languageKey = context.getExternalContext().getRequestLocale().toString();
final JournalArticleDisplay articleDisplay = JournalContentUtil.getDisplay(groupId, article.getArticleId(), article.getTemplateId(), languageKey, themeDisplay);
return articleDisplay.getContent();
}
catch (final Exception ex)
{
System.out.println(ex.getMessage());
return ex.getMessage();
}
}
Morad Ahmad
RE: Liferay Web Content mit eigenem JSF-Portlet anzeigen
August 17, 2011 7:14 AM
Answer

Morad Ahmad

Rank: Junior Member

Posts: 37

Join Date: June 16, 2010

Recent Posts

Hallo,

ich versuche seit langem einen generischen Ansatz. Die Klassen von eben sollen der Grundstein dazu (50%). Das wichtigste ist es eine automatische Erzeugung von Java-Beans von einem JournalArticle mit einer definierten Structure. Und eine Art QueryManager der bestimmte Queries ausführt und die Ergebnisse als beans zurückliefert.

Ein Problem bleibt das Editieren von Content. Es funktioniert zwar wunderbar, wenn ausgesuchte Autoren den Inhalt pflegen. Wenn aber jeder angemeldete Benutzer Beiträge schreiben kann dann sollte man das CMS direkt in JSF-Views editieren können irgendwie <cms:edit type="..." id="..." />

Der Ansatz von Hippo finde ich sehr schön. Es ist sehr viel Aufwand das in Lifery zu implementieren. Vielleicht hat jemand Zeit für sowas. Das wäre genial.

Morad.