Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden

Grails Liferay Portlets und GORM

Wie in mei­nem letz­ten Beitrag ange­kün­digt, wollte ich mich tie­fer­ge­hend mit den Möglichkeiten des Grails Portlet Plugins beschäf­ti­gen. Da die Dokumentation nicht beson­ders aus­sa­ge­kräf­tig ist, galt es zunächst her­aus­zu­fin­den, ob man nicht nur Deskriptoren und Portlet Views gene­rie­ren son­dern auch Domain-Objekte im Portlet ver­wen­den kann.

Dafür habe ich zu Testzwecken ein Domainobjekt mit dem Namen Blogpost erstellt:

grails create-domain-class de.communardo.liferay.grails.portlet.Blogpost

Die Domain Klasse Blogpost bekam schnell ein paar Properties:

package de.communardo.liferay.grails.portlet
class Blogpost {
    String title
    String author
    String content
}

Danach fix die Views gene­riert, als Vorlage für den Portlet View:

grails generate-portlet-views de.communardo.liferay.grails.portlet.Blogpost

Den fol­gen­den Teil habe ich in die view.gsp für das Portlet übernommen:

<h1>Blogpost List</h1>
<div class="list">
	<table>
		<thead>
			<tr>
				<g:sortableColumn property="id" title="Id" />
				<g:sortableColumn property="author" title="Author" />
				<g:sortableColumn property="content" title="Content" />
				<g:sortableColumn property="title" title="Title" />
			</tr>
		</thead>
		<tbody>
		<g:each in="${blogpostInstanceList}" status="i" var="blogpostInstance">
			<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
				<td><g:link action="show" id="${blogpostInstance.id}">${fieldValue(bean:blogpostInstance, field:'id')}</g:link></td>
				<td>${fieldValue(bean:blogpostInstance, field:'author')}</td>
				<td>${fieldValue(bean:blogpostInstance, field:'content')}</td>
				<td>${fieldValue(bean:blogpostInstance, field:'title')}</td>
			</tr>
		</g:each>
		</tbody>
	</table>
</div>

Danach habe ich die Liste mit Blogposts in der renderView Closure der Portlet Klasse mit den vor­han­de­nen Blogposts befüllt:

def renderView = {
    [ blogpostInstanceList: Blogpost.list()]
}

Für die Testdaten kam die bootstrap.groovy wie gerufen:

class BootStrap {
    def init = { servletContext ->
        new Blogpost(author:"Ralf Borchers",title:"Lifray Potlets mit Grails", content:"Es geht...").save()
    }
    ...
}

Dadurch wer­den die Daten beim Starten der Anwendung stan­dard­mä­ßig in einer HSQL DB gespeichert.

Damit war die Vorbreitung schon abge­schlos­sen und mein Portlet konnte rede­ployed werden:

grails war

Daraufhin war das Portlet kaputt und warf eine IllegalstateException:


java.lang.IllegalStateException: Root context attribute is not of type WebApplicationContext: com.liferay.portal.spring.context.PortalApplicationContext@10e35d5: display name [Root WebApplic
ationContext];

Ursache dafür scheint zu sein, dass das Hot Deployment von Spring Portlets nicht so rich­tig sau­ber funk­tio­niert. Siehe auch hier. Nach dem Neustart star­tete das Portlet feh­ler­frei und ich konnte stolz mei­nen Test-Blogposts im Portlet betrachten.

Zusammenfassend lässt sich sagen, dass man für kom­ple­xere Portlets eine Realisierung in Form eines Grails Portlets in Erwägung zie­hen sollte. Man pro­fi­tiert von vie­len Features des Grails Frameworks und kann die Produktivität bei der Portletentwicklung sicher enorm steigern.

Related Posts

1 Kommentar

Mein erstell­tes Portlet wird sobald ich ver­su­che eine DB Verbindung ein­zu­bauen nicht mehr deployed:

INFO: Deploying web app­li­ca­tion direc­tory KontaktePortletGrails‑0.1
05.03.2012 12:02:50 org.apache.catalina.core.StandardContext start
SCHWERWIEGEND: Error listenerStart
05.03.2012 12:02:50 org.apache.catalina.core.StandardContext start
SCHWERWIEGEND: Context [/KontaktePortletGrails‑0.1] startup fai­led due to pre­vious errors
05.03.2012 12:02:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web app­li­ca­tion [/KontaktePortletGrails‑0.1] appears to have star­ted a thread named [Timer‑3] but has fai­led to stop it. This is very likely to create a memory leak.
05.03.2012 12:02:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web app­li­ca­tion [/KontaktePortletGrails‑0.1] appears to have star­ted a thread named [net.sf.ehcache.CacheManager@18735f1] but has fai­led to stop it. This is very likely to create a memory leak.
05.03.2012 12:02:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web app­li­ca­tion [/KontaktePortletGrails‑0.1] appears to have star­ted a thread named [org.hibernate.cache.UpdateTimestampsCache.data] but has fai­led to stop it. This is very likely to create a memory leak.
05.03.2012 12:02:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web app­li­ca­tion [/KontaktePortletGrails‑0.1] appears to have star­ted a thread named [org.hibernate.cache.StandardQueryCache.data] but has fai­led to stop it. This is very likely to create a memory leak.
05.03.2012 12:02:54 org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web app­li­ca­tion direc­tory vaadin-controlpanel-for-liferay

Comments are closed.

Pin It on Pinterest