{"id":4268,"date":"2012-03-27T13:15:22","date_gmt":"2012-03-27T11:15:22","guid":{"rendered":"http:\/\/blog.dutchworks.nl\/?p=4268"},"modified":"2012-03-27T13:15:22","modified_gmt":"2012-03-27T11:15:22","slug":"vaadin-portlets-with-add-ons-in-liferay","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/","title":{"rendered":"Vaadin portlets with add-ons in Liferay"},"content":{"rendered":"<p>The <a href=\"https:\/\/vaadin.com\/home\">Vaadin<\/a> web framework has been around for quite some time now, and for a couple of years it also supports portlet development. This is particularly the case for the Liferay portal, where some integration work has already been done for you. Using Vaadin to build Liferay portlets is rather nice, because until you actually become dependent on the Liferay API, your Vaadin project can still run stand-alone, giving you quick feedback during development without having to redeploy the portlet.<\/p>\n<p>Working with Liferay is, like most things in Vaadin, well documented in the \u201cBook of Vaadin\u201d, in <a href=\"https:\/\/vaadin.com\/book\/-\/page\/portal.html\">chapter 13<\/a>, but there are some complications. As Vaadin uses <a href=\"https:\/\/code.google.com\/webtoolkit\/\">GWT<\/a> under the hood, an application needs a GWT widget set. If you just use standard Vaadin components, the widget set is prepackaged in the war file, but if you start using Vaadin add-ons or custom built components, you need to recompile the widget set. A limitation of running Vaadin portlets is that the widget set needs to be available centrally in the Liferay web application and is shared by all Vaadin portlets. This means that you\u2019ll have to update this widget set in Liferay while your project grows.<\/p>\n<p>The bits of information needed to put this all together are available on the web, but sadly scattered over reference manuals, wikis, blogs and forum posts. In this blog I&#8217;ll go through it incrementally. Probably you know most of the steps already, but then again, if you knew them all you wouldn\u2019t be here \ud83d\ude09<\/p>\n<p><!--more--><\/p>\n<h2>Creating a basic Vaadin application<\/h2>\n<p>Setting up a basic Vaadin application is of course quite easy. I don\u2019t know any another framework that needs such little configuration.<\/p>\n<p>Firstly, create a basic maven web project. Add the latest Vaadin dependency to your pom.xml.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;project xmlns=&quot;http:\/\/maven.apache.org\/POM\/4.0.0&quot;\n         xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;\n         xsi:schemaLocation=&quot;http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd&quot;&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n\n    &lt;groupId&gt;nl.dutchworks.demo&lt;\/groupId&gt;\n    &lt;artifactId&gt;vaadin-demo-portlet&lt;\/artifactId&gt;\n    &lt;version&gt;1.0&lt;\/version&gt;\n    &lt;packaging&gt;war&lt;\/packaging&gt;\n\n    &lt;properties&gt;\n        &lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\n    &lt;\/properties&gt;\n\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.vaadin&lt;\/groupId&gt;\n            &lt;artifactId&gt;vaadin&lt;\/artifactId&gt;\n            &lt;version&gt;6.7.5&lt;\/version&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n    &lt;build&gt;\n        &lt;plugins&gt;\n            &lt;plugin&gt;\n                &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\n                &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\n                &lt;version&gt;2.3.2&lt;\/version&gt;\n                &lt;configuration&gt;\n                    &lt;source&gt;1.6&lt;\/source&gt;\n                    &lt;target&gt;1.6&lt;\/target&gt;\n                &lt;\/configuration&gt;\n            &lt;\/plugin&gt;\n        &lt;\/plugins&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;\n<\/pre>\n<p>Now create a basic Vaadin \u201cHello world\u201d type of application; extend the com.vaadin.Application class and override the init() method.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npackage nl.dutchworks.demo;\n\nimport com.vaadin.Application;\nimport com.vaadin.ui.Label;\nimport com.vaadin.ui.Window;\n\npublic class DemoApplication extends Application {\n    @Override\n    public void init() {\n        Window mainWindow = new Window(&quot;Vaadin Demo Application&quot;);\n        Label label = new Label(&quot;Hello Vaadin!&quot;);\n        mainWindow.addComponent(label);\n        setMainWindow(mainWindow);\n    }\n}\n<\/pre>\n<p>Like most Java web frameworks, Vaadin supplies a servlet as the starting point for the web application. The fully qualified class name of your subclassed application goes in the \u201capplication\u201d init-param. The web.xml should look like this:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;web-app id=&quot;WebApp_ID&quot; version=&quot;2.4&quot; xmlns=&quot;http:\/\/java.sun.com\/xml\/ns\/j2ee&quot;\n         xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot;\n         xsi:schemaLocation=&quot;http:\/\/java.sun.com\/xml\/ns\/j2ee http:\/\/java.sun.com\/xml\/ns\/j2ee\/web-app_2_4.xsd&quot;&gt;\n    &lt;display-name&gt;Vaadin Demo Application&lt;\/display-name&gt;\n    &lt;context-param&gt;\n        &lt;description&gt;Vaadin production mode&lt;\/description&gt;\n        &lt;param-name&gt;productionMode&lt;\/param-name&gt;\n        &lt;param-value&gt;false&lt;\/param-value&gt;\n    &lt;\/context-param&gt;\n    &lt;servlet&gt;\n        &lt;servlet-name&gt;vaadin servlet&lt;\/servlet-name&gt;\n        &lt;servlet-class&gt;com.vaadin.terminal.gwt.server.ApplicationServlet&lt;\/servlet-class&gt;\n        &lt;init-param&gt;\n            &lt;description&gt;Vaadin Application&lt;\/description&gt;\n            &lt;param-name&gt;application&lt;\/param-name&gt;\n            &lt;param-value&gt;nl.dutchworks.demo.DemoApplication&lt;\/param-value&gt;\n        &lt;\/init-param&gt;\n    &lt;\/servlet&gt;\n    &lt;servlet-mapping&gt;\n        &lt;servlet-name&gt;vaadin servlet&lt;\/servlet-name&gt;\n        &lt;url-pattern&gt;\/*&lt;\/url-pattern&gt;\n    &lt;\/servlet-mapping&gt;\n&lt;\/web-app&gt;\n<\/pre>\n<p>Your project directory structure should be looking something like this:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-simple-project\/\" rel=\"attachment wp-att-4273\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4273\" title=\"vaadin-simple-project\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png\" alt=\"\" width=\"402\" height=\"324\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-simple-project.png 402w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-simple-project-300x242.png 300w\" sizes=\"auto, (max-width: 402px) 100vw, 402px\" \/><\/a><\/p>\n<p>When you build your project with maven and run it on a tomcat configured in your IDE, the output is, unsurprisingly, this:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-hello-world\/\" rel=\"attachment wp-att-4276\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4276\" title=\"vaadin-hello-world\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-hello-world.png\" alt=\"\" width=\"568\" height=\"212\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-hello-world.png 568w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-hello-world-300x112.png 300w\" sizes=\"auto, (max-width: 568px) 100vw, 568px\" \/><\/a><\/p>\n<h2>Using a Vaadin add-on<\/h2>\n<p>Now, to add a vaadin add-on let\u2019s take the Event Timeline component.<\/p>\n<p>Firstly, we add the dependency to the pom.xml file:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n   &lt;groupId&gt;org.vaadin.addons&lt;\/groupId&gt;\n   &lt;artifactId&gt;event-timeline&lt;\/artifactId&gt;\n   &lt;version&gt;0.5.1&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/pre>\n<p>Don\u2019t forget to add the Vaadin add-on maven repository to your artifactory, settings.xml or pom.xml:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;repository&gt;\n   &lt;id&gt;vaadin-addons&lt;\/id&gt;\n   &lt;url&gt;http:\/\/maven.vaadin.com\/vaadin-addons&lt;\/url&gt;\n&lt;\/repository&gt;\n<\/pre>\n<p>Now, i use the example code provided on the Event Timeline add-on page in the application:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class DemoApplication extends Application {\n    @Override\n    public void init() {\n        Window mainWindow = new Window(&quot;Vaadin Demo Application&quot;);\n        \/\/Label label = new Label(&quot;Hello Vaadin!&quot;);\n        \/\/mainWindow.addComponent(label);\n        setMainWindow(mainWindow);\n\n        EventTimeline timeline = new EventTimeline(&quot;Our event timeline&quot;);\n        timeline.setHeight(&quot;500px&quot;);\n        timeline.setWidth(&quot;100%&quot;);\n\n        \/\/ set the visible time range\n        Calendar cal = Calendar.getInstance();\n        Date start = cal.getTime();\n        cal.add(Calendar.HOUR_OF_DAY, 24);\n        Date end = cal.getTime();\n        timeline.setVisibleDateRange(start, end);\n\n        \/\/ add our data sources\n        timeline.addEventBand(&quot;Band&quot;, createEventProvider(end));\n\n        \/\/ Add some zoom levels\n        timeline.addZoomLevel(&quot;Hour&quot;, 60 * 60 * 1000L);\n        timeline.addZoomLevel(&quot;Day&quot;, 86400000L);\n\n        mainWindow.addComponent(timeline);\n    }\n\n    public TimelineEventProvider createEventProvider(final Date end) {\n        BasicEventProvider provider = new BasicEventProvider();\n\n        \/\/ get events for a whole day\n        Calendar cal = Calendar.getInstance();\n        cal.add(Calendar.HOUR, 1);\n        int idx = 0;\n        while (cal.getTime().before(end)) {\n            \/\/ create a simple event\n            BasicEvent event = new BasicEvent();\n            event.setEventId(String.valueOf(idx));\n\n            \/\/ set the timestamp property\n            event.setStart(cal.getTime());\n            cal.add(Calendar.MINUTE, 10);\n            event.setEnd(cal.getTime());\n            \/\/ set the caption\n            event.setCaption(&quot;Event&quot;);\n            \/\/ style the event\n            event.setStyleName(&quot;color1&quot;);\n\n            provider.addEvent(event);\n            cal.add(Calendar.MINUTE, 30);\n            idx++;\n        }\n\n        return provider;\n    }\n}\n<\/pre>\n<p>Of course, running this doesn\u2019t work yet:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-timeline-broken\/\" rel=\"attachment wp-att-4277\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4277\" title=\"vaadin-timeline-broken\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-timeline-broken.png\" alt=\"\" width=\"590\" height=\"333\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-timeline-broken.png 590w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-timeline-broken-300x169.png 300w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/a><\/p>\n<h2>Recompiling the widget set<\/h2>\n<p>We can fix this by recomping the widget set. For this, we need a couple of steps. The pom.xml file needs quite some additions: We need the gwt-user dependency:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n            &lt;groupId&gt;com.google.gwt&lt;\/groupId&gt;\n            &lt;artifactId&gt;gwt-user&lt;\/artifactId&gt;\n            &lt;version&gt;2.3.0&lt;\/version&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n<\/pre>\n<p>And then we need to add some plugins.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;plugin&gt;\n                &lt;groupId&gt;com.vaadin&lt;\/groupId&gt;\n                &lt;artifactId&gt;vaadin-maven-plugin&lt;\/artifactId&gt;\n                &lt;version&gt;1.0.2&lt;\/version&gt;\n                &lt;executions&gt;\n                    &lt;execution&gt;\n                        &lt;phase&gt;generate-resources&lt;\/phase&gt;\n                        &lt;configuration&gt;\n                            &lt;!-- if you don't specify any modules, the plugin will find them --&gt;\n                            &lt;!-- &lt;modules&gt; &lt;module&gt;${package}.gwt.MyWidgetSet&lt;\/module&gt; &lt;\/modules&gt; --&gt;\n                        &lt;\/configuration&gt;\n                        &lt;goals&gt;\n                            &lt;goal&gt;update-widgetset&lt;\/goal&gt;\n                        &lt;\/goals&gt;\n                    &lt;\/execution&gt;\n                &lt;\/executions&gt;\n            &lt;\/plugin&gt;\n            &lt;!-- Compiles your custom GWT components with the GWT compiler --&gt;\n            &lt;plugin&gt;\n                &lt;groupId&gt;org.codehaus.mojo&lt;\/groupId&gt;\n                &lt;artifactId&gt;gwt-maven-plugin&lt;\/artifactId&gt;\n                &lt;version&gt;2.3.0-1&lt;\/version&gt;\n                &lt;configuration&gt;\n                    &lt;!-- if you don't specify any modules, the plugin will find them --&gt;\n                     &lt;webappDirectory&gt;src\/main\/webapp\/VAADIN\/widgetsets&lt;\/webappDirectory&gt;\n                    &lt;extraJvmArgs&gt;-Xmx512M -Xss1024k&lt;\/extraJvmArgs&gt;\n                    &lt;runTarget&gt;clean&lt;\/runTarget&gt;\n                    &lt;hostedWebapp&gt;${project.build.directory}\/${project.build.finalName}&lt;\/hostedWebapp&gt;\n                    &lt;noServer&gt;true&lt;\/noServer&gt;\n                    &lt;port&gt;8080&lt;\/port&gt;\n                &lt;\/configuration&gt;\n                &lt;executions&gt;\n                    &lt;execution&gt;\n                        &lt;phase&gt;generate-resources&lt;\/phase&gt;\n                        &lt;goals&gt;\n                            &lt;goal&gt;resources&lt;\/goal&gt;\n                            &lt;goal&gt;compile&lt;\/goal&gt;\n                        &lt;\/goals&gt;\n                    &lt;\/execution&gt;\n                &lt;\/executions&gt;\n            &lt;\/plugin&gt;\n<\/pre>\n<p>Then we add a widget set file called VaadinDemoWidgetSet.gwt.xml to our resources directory:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-demo-project-widgetset\/\" rel=\"attachment wp-att-4278\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4278\" title=\"vaadin-demo-project-widgetset\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-demo-project-widgetset.png\" alt=\"\" width=\"406\" height=\"345\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-demo-project-widgetset.png 406w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-demo-project-widgetset-300x255.png 300w\" sizes=\"auto, (max-width: 406px) 100vw, 406px\" \/><\/a><\/p>\n<p>The widgetfile will contain a reference to the default widget set and to the widget set of the add-on (this can be found by inspecting the dependency jar of the add-on).<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;!DOCTYPE module PUBLIC\n        &quot;-\/\/Google Inc.\/\/DTD Google Web Toolkit 2.3.0\/\/EN&quot;\n        &quot;http:\/\/google-web-toolkit.googlecode.com\/svn\/tags\/2.3.0\/distro-source\/core\/src\/gwt-module.dtd&quot;&gt;\n&lt;module&gt;\n    &lt;inherits name=&quot;com.vaadin.terminal.gwt.DefaultWidgetSet&quot;\/&gt;\n    &lt;inherits name=&quot;com.spaceapplications.vaadin.addon.eventtimeline.gwt.EventTimelineWidgetSet&quot; \/&gt;\n&lt;\/module&gt;\n<\/pre>\n<p>Now all that remains to be done is tell Vaadin to actually use the newly generated widget set for this application. This is done by adding an init-param to the servlet definition in the web.xml file:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;servlet&gt;\n        &lt;servlet-name&gt;vaadin servlet&lt;\/servlet-name&gt;\n        &lt;servlet-class&gt;com.vaadin.terminal.gwt.server.ApplicationServlet&lt;\/servlet-class&gt;\n        &lt;init-param&gt;\n            &lt;description&gt;Vaadin Application&lt;\/description&gt;\n            &lt;param-name&gt;application&lt;\/param-name&gt;\n            &lt;param-value&gt;nl.dutchworks.demo.DemoApplication&lt;\/param-value&gt;\n        &lt;\/init-param&gt;\n        &lt;init-param&gt;\n            &lt;param-name&gt;widgetset&lt;\/param-name&gt;\n            &lt;param-value&gt;nl.dutchworks.demo.VaadinDemoWidgetSet&lt;\/param-value&gt;\n        &lt;\/init-param&gt;\n    &lt;\/servlet&gt;\n<\/pre>\n<p>Building the project with maven and running it now produces the desired result:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-screenshot-timeline\/\" rel=\"attachment wp-att-4279\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4279\" title=\"vaadin-screenshot-timeline\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-screenshot-timeline.png\" alt=\"\" width=\"588\" height=\"472\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-screenshot-timeline.png 588w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-screenshot-timeline-300x241.png 300w\" sizes=\"auto, (max-width: 588px) 100vw, 588px\" \/><\/a><\/p>\n<h2>Preparing Liferay<\/h2>\n<p>The next step is to turn this project into a portlet. For that, we first need to prepare our Liferay instance. Because of the shared nature of widget sets by multiple portlets, the preferred way to use Vaadin in Liferay is with a centralised vaadin.jar and all add-on jar files in the \/\/webapps\/ROOT\/WEB-INF\/lib dir.<br \/>\nTo get all the right files in there, and to be able to compile the widget set for the portal, the easiest way is to download and install the <a href=\"http:\/\/vaadin.com\/directory#addon\/vaadin-control-panel-for-liferay\">Vaadin control panel for Liferay<\/a>. This portlet installs like all other portlets in liferay.<\/p>\n<ul>\n<li>Drop the vaadin control panel war file in your Liferay deploy directory<\/li>\n<li>Once deployed, drag the panel onto a page. The settings panel will look like this:<\/li>\n<\/ul>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-control-panel-upgrade\/\" rel=\"attachment wp-att-4280\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-4280\" title=\"vaadin-control-panel-upgrade\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-control-panel-upgrade.png\" alt=\"\" width=\"578\" height=\"238\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-control-panel-upgrade.png 722w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-control-panel-upgrade-300x124.png 300w\" sizes=\"auto, (max-width: 578px) 100vw, 578px\" \/><\/a><\/p>\n<ul>\n<li>The portlet will show which version of Vaadin is in your Liferay, and what\u2019s the latest version out there. Click \u201cUpgrade\u201d; it will download and install the latest Vaadin jar and the GWT jars needed to compile the widget set.<\/li>\n<li>Now find the jar file of the add-on, in this case event-timeline-0.5.1.jar (for instance from your .m2\/repository directory) and copy it to \/\/webapps\/ROOT\/WEB-INF\/lib.<\/li>\n<li>If you click \u201cre-scan\u201d in the control panel it will pick up the add-on jars and allow you to select which ones you want added to the widget set.<\/li>\n<li>Now Click the \u201cCompile Widget Set\u201d button. It will compile and put the widget set in the correct place (\/\/webapps\/ROOT\/html\/VAADIN\/widgetsets).<\/li>\n<\/ul>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-control-panel-compiled-widgetset\/\" rel=\"attachment wp-att-4281\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-4281\" title=\"vaadin-control-panel-compiled-widgetset\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-control-panel-compiled-widgetset.png\" alt=\"\" width=\"577\" height=\"615\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-control-panel-compiled-widgetset.png 721w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-control-panel-compiled-widgetset-281x300.png 281w\" sizes=\"auto, (max-width: 577px) 100vw, 577px\" \/><\/a><\/p>\n<p>Your Liferay instance should now be correctly configured to deploy your application.<\/p>\n<h2>Add portlet descriptors to the project<\/h2>\n<p>To turn the web project into a portlet project, we need to add a couple of descriptors to the project in \/src\/main\/webapp\/WEB-INF. These are the standard portlet.xml and Liferay descriptors. In these Liferay descriptors, the value portlet-name from portlet.xml is used as the portlet id. Further names, titles and descriptions are used by Liferay in various places in the portal GUI (bonus points can be won by finding which ones are used where).<\/p>\n<h3>portlet.xml<\/h3>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;\n&lt;portlet-app xmlns=&quot;http:\/\/java.sun.com\/xml\/ns\/portlet\/portlet-app_2_0.xsd&quot; xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; version=&quot;2.0&quot; xsi:schemaLocation=&quot;http:\/\/java.sun.com\/xml\/ns\/portlet\/portlet-app_2_0.xsd http:\/\/java.sun.com\/xml\/ns\/portlet\/portlet-app_2_0.xsd&quot;&gt;\n\n    &lt;portlet&gt;\n        &lt;portlet-name&gt;Vaadin Demo Portlet&lt;\/portlet-name&gt;\n        &lt;display-name&gt;Vaadin Demo Portlet (portlet.xml display-name)&lt;\/display-name&gt;\n\n        &lt;portlet-class&gt;com.vaadin.terminal.gwt.server.ApplicationPortlet2&lt;\/portlet-class&gt;\n        &lt;init-param&gt;\n            &lt;name&gt;application&lt;\/name&gt;\n            &lt;value&gt;nl.dutchworks.demo.DemoApplication&lt;\/value&gt;\n        &lt;\/init-param&gt;\n        &lt;!-- Supported portlet modes and content types. --&gt;\n        &lt;supports&gt;\n            &lt;mime-type&gt;text\/html&lt;\/mime-type&gt;\n            &lt;portlet-mode&gt;view&lt;\/portlet-mode&gt;\n         &lt;\/supports&gt;\n\n        &lt;!-- Not always required but Liferay uses these. --&gt;\n        &lt;portlet-info&gt;\n            &lt;title&gt;Vaadin Demo Portlet title&lt;\/title&gt;\n            &lt;short-title&gt;vaadin-demo-portlet-short-title&lt;\/short-title&gt;\n        &lt;\/portlet-info&gt;\n    &lt;\/portlet&gt;\n&lt;\/portlet-app&gt;\n<\/pre>\n<h3>liferay-portlet.xml<\/h3>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;\n&lt;!DOCTYPE liferay-portlet-app PUBLIC &quot;-\/\/Liferay\/\/DTD Portlet Application 6.1.0\/\/EN&quot; &quot;http:\/\/www.liferay.com\/dtd\/liferay-portlet-app_6_1_0.dtd&quot;&gt;\n&lt;liferay-portlet-app&gt;\n    &lt;portlet&gt;\n        &lt;!-- Matches definition in portlet.xml. --&gt;\n        &lt;!-- Note: Must not be the same as servlet name. --&gt;\n        &lt;portlet-name&gt;Vaadin Demo Portlet&lt;\/portlet-name&gt;\n        &lt;instanceable&gt;true&lt;\/instanceable&gt;\n        &lt;ajaxable&gt;false&lt;\/ajaxable&gt;\n    &lt;\/portlet&gt;\n&lt;\/liferay-portlet-app&gt;\n<\/pre>\n<h3>liferay-plugin-package.properties<\/h3>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nname=Vaadin Demo Portlet\nshort-description=Vaadin Demo Portlet short description\nmodule-group-id=Vaadin\nmodule-incremental-version=1\n#change-log=\n#page-uri=\n#author=\nlicense=Proprietary\nportal-dependency-jars=\\\n    vaadin.jar\n<\/pre>\n<h3>liferay-display.xml<\/h3>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;\n&lt;!DOCTYPE display PUBLIC &quot;-\/\/Liferay\/\/DTD Display 6.1.0\/\/EN&quot; &quot;http:\/\/www.liferay.com\/dtd\/liferay-display_6_1_0.dtd&quot;&gt;\n&lt;display&gt;\n    &lt;category name=&quot;Vaadin Portlets&quot;&gt;\n        &lt;portlet id=&quot;Vaadin Demo Portlet&quot;\/&gt;\n    &lt;\/category&gt;\n&lt;\/display&gt;\n<\/pre>\n<p>Your project should look like this:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-project-portlet-descriptors\/\" rel=\"attachment wp-att-4282\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4282\" title=\"vaadin-project-portlet-descriptors\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-project-portlet-descriptors.png\" alt=\"\" width=\"405\" height=\"435\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-project-portlet-descriptors.png 405w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-project-portlet-descriptors-279x300.png 279w\" sizes=\"auto, (max-width: 405px) 100vw, 405px\" \/><\/a><\/p>\n<p>Now, build the project with maven and drop the war file in the Liferay deploy directory. When it\u2019s deployed, you\u2019ll see it appear in the \u201cAdd\/More&#8230;\u201d pop-up in Liferay:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-add-portlet-popin\/\" rel=\"attachment wp-att-4283\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4283\" title=\"vaadin-add-portlet-popin\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-add-portlet-popin.png\" alt=\"\" width=\"241\" height=\"91\" \/><\/a><\/p>\n<p>Adding the portlet to the page should now render our portlet correctly:<\/p>\n<p><a href=\"http:\/\/blog.orange11.nl\/2012\/03\/27\/vaadin-portlets-with-add-ons-in-liferay\/vaadin-portlet-final\/\" rel=\"attachment wp-att-4284\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-4284\" title=\"vaadin-portlet-final\" src=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-portlet-final.png\" alt=\"\" width=\"600\" height=\"484\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-portlet-final.png 750w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2012\/03\/vaadin-portlet-final-300x242.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/a><\/p>\n<h2>Conclusion<\/h2>\n<p>We&#8217;ve now got a Vaadin application project with a Vaadin add-on that will run both as a webapp for ease of development and as a portlet in Liferay.<\/p>\n<h2>References<\/h2>\n<ul>\n<li>The Book of Vaadin, an excellent resource. If only other projects would take documentation this seriously: <a href=\"https:\/\/vaadin.com\/book\/-\/page\/preface.html\">https:\/\/vaadin.com\/book\/-\/page\/preface.html<\/a><\/li>\n<li>The Vaadin control panel for Liferay: <a href=\"http:\/\/vaadin.com\/directory#addon\/vaadin-control-panel-for-liferay\">http:\/\/vaadin.com\/directory#addon\/vaadin-control-panel-for-liferay<\/a><\/li>\n<li>Joram Barrez uses a Vaadin archetype to do some of this and takes it a bit further, by isolating widget set compilation to a maven profile: <a href=\"http:\/\/www.jorambarrez.be\/blog\/2011\/04\/28\/howto-vaadin-addon-maven\/\">http:\/\/www.jorambarrez.be\/blog\/2011\/04\/28\/howto-vaadin-addon-maven\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The Vaadin web framework has been around for quite some time now, and for a couple of years it also supports portlet development. This is particularly the case for the Liferay portal, where some integration work has already been done for you. Using Vaadin to build Liferay portlets is rather nice, because until you actually [&hellip;]<\/p>\n","protected":false},"author":32,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[283],"tags":[282,286],"class_list":["post-4268","post","type-post","status-publish","format-standard","hentry","category-liferay-cms-2","tag-liferay","tag-vaadin"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Vaadin portlets with add-ons in Liferay - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Vaadin portlets with add-ons in Liferay - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"The Vaadin web framework has been around for quite some time now, and for a couple of years it also supports portlet development. This is particularly the case for the Liferay portal, where some integration work has already been done for you. Using Vaadin to build Liferay portlets is rather nice, because until you actually [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2012-03-27T11:15:22+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png\" \/>\n<meta name=\"author\" content=\"David Caron\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"David Caron\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/\",\"url\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/\",\"name\":\"Vaadin portlets with add-ons in Liferay - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png\",\"datePublished\":\"2012-03-27T11:15:22+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/82d355a992e5874920b6b6c6ef012388\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage\",\"url\":\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png\",\"contentUrl\":\"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Vaadin portlets with add-ons in Liferay\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/82d355a992e5874920b6b6c6ef012388\",\"name\":\"David Caron\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/0fc75b43d91f2a2eeba48af1453edb6e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/0fc75b43d91f2a2eeba48af1453edb6e?s=96&d=mm&r=g\",\"caption\":\"David Caron\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/david\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Vaadin portlets with add-ons in Liferay - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/","og_locale":"en_US","og_type":"article","og_title":"Vaadin portlets with add-ons in Liferay - Trifork Blog","og_description":"The Vaadin web framework has been around for quite some time now, and for a couple of years it also supports portlet development. This is particularly the case for the Liferay portal, where some integration work has already been done for you. Using Vaadin to build Liferay portlets is rather nice, because until you actually [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/","og_site_name":"Trifork Blog","article_published_time":"2012-03-27T11:15:22+00:00","og_image":[{"url":"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png","type":"","width":"","height":""}],"author":"David Caron","twitter_card":"summary_large_image","twitter_misc":{"Written by":"David Caron","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/","url":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/","name":"Vaadin portlets with add-ons in Liferay - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage"},"thumbnailUrl":"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png","datePublished":"2012-03-27T11:15:22+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/82d355a992e5874920b6b6c6ef012388"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#primaryimage","url":"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png","contentUrl":"http:\/\/blog.dutchworks.nl\/wp-content\/uploads\/2012\/03\/vaadin-simple-project.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/vaadin-portlets-with-add-ons-in-liferay\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Vaadin portlets with add-ons in Liferay"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/82d355a992e5874920b6b6c6ef012388","name":"David Caron","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/0fc75b43d91f2a2eeba48af1453edb6e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/0fc75b43d91f2a2eeba48af1453edb6e?s=96&d=mm&r=g","caption":"David Caron"},"url":"https:\/\/trifork.nl\/blog\/author\/david\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/4268","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=4268"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/4268\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=4268"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=4268"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=4268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}