Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden
+49 (0) 351/8 33 82-0

Grails Liferay Portlets und GORM

Wie in meinem letzten Beitrag angekündigt, wollte ich mich tiefergehend mit den Möglichkeiten des Grails Portlet Plugins beschäftigen. Da die Dokumentation nicht besonders aussagekräftig ist, galt es zunächst herauszufinden, ob man nicht nur Deskriptoren und Portlet Views generieren sondern auch Domain-Objekte im Portlet verwenden 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 generiert, als Vorlage für den Portlet View:

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

Den folgenden 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 vorhandenen 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 werden die Daten beim Starten der Anwendung standardmäßig in einer HSQL DB gespeichert.

Damit war die Vorbreitung schon abgeschlossen und mein Portlet konnte redeployed 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 richtig sauber funktioniert. Siehe auch hier. Nach dem Neustart startete das Portlet fehlerfrei und ich konnte stolz meinen Test-Blogposts im Portlet betrachten.

Zusammenfassend lässt sich sagen, dass man für komplexere Portlets eine Realisierung in Form eines Grails Portlets in Erwägung ziehen sollte. Man profitiert von vielen Features des Grails Frameworks und kann die Produktivität bei der Portletentwicklung sicher enorm steigern.

1 Kommentar

Mein erstelltes Portlet wird sobald ich versuche eine DB Verbindung einzubauen nicht mehr deployed:

INFO: Deploying web application directory 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 failed due to previous errors
05.03.2012 12:02:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web application [/KontaktePortletGrails-0.1] appears to have started a thread named [Timer-3] but has failed 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 application [/KontaktePortletGrails-0.1] appears to have started a thread named [net.sf.ehcache.CacheManager@18735f1] but has failed 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 application [/KontaktePortletGrails-0.1] appears to have started a thread named [org.hibernate.cache.UpdateTimestampsCache.data] but has failed 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 application [/KontaktePortletGrails-0.1] appears to have started a thread named [org.hibernate.cache.StandardQueryCache.data] but has failed 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 application directory vaadin-controlpanel-for-liferay

Kommentar hinterlassen


Pin It on Pinterest