AdoptOS

Assistance with Open Source adoption

ECM

Maven Madness in Liferay Land

Liferay - Sat, 02/06/2016 - 17:28
In this post I want to share how you can use Maven to do 2 important things in a Liferay project: patching and creating a deploy package.   While this way of patching is a very powerful way to modify Liferay in an automated way (no manual WAR/JAR patching) you should use it as sparingly as possible. If possible you should always try to use more conventional ways of modding Liferay, for example using a hook, when possible. But whenever that's not possible, or like me you don't really like EXT or extlets, feel free to use the methods described in this post.   While this post will be focused on using Maven as a build tool to achieve the desired result, the concepts and techniques should also apply to other build tools like Ant, Gradle or Buildr (and if you're not already using a build tool... this might be the moment to start using one).   Patching While it can produce similar results as the Liferay EE patching tool in some respects, the patching described in this section is a slightly different beast. They even can, as you'll see in the deploy package section, be used together. There are a number of different reasons to use this additional way of patching Liferay:
  • you can't use the Liferay patching tool because you're using Liferay CE
  • you can't wait for an official patch/fix and need a temporary workaround
  • you need to add or change Liferay files that you can't (or don't want to) change using a hook
  • ...
There are a lot of parts of Liferay that you might want/need to patch:
  • the portal WAR
  • the portal-service.jar
  • one of the other Liferay JARs that are contained in the portal WAR: util-java.jar, util-bridges.jar, ...
  • the most special case of all: a JAR that's included in another JAR that itself is included in the portal WAR aka 'overlay-ception'
The portal WAR Let's start with the easiest case: patching the Liferay WAR file. What makes this the easiest one is that you can simply use the well known Maven WAR plugin's overlay ability to achieve the desired result. For most file types you just need to put them in the correct directory of your module for them to be correctly overlayed:
  • src/main/java: Java classes you want to override. They'll be put in the WEB-INF/classes directory and they'll be loaded before any classes from the WEB-INF/lib directory.
  • src/main/resources: non-Java source files that you want to end up in WEB-INF/classes like log4j configuration or a JGroups configuration file to configure your cluster to use unicast instead of multicast.
  • src/main/webapp: all files here will override their counterparts their corresponding directory in the WAR (useful for overriding JSPs) or you can even use it to add new files (JS libs, images, ...). You can also add a WEB-INF subdirectory and add modified versions of web/Liferay descriptors like web.xml or liferay-portlet.xml.
The Maven XML configuration that is needed for this is pretty simple: you just reference the Liferay WAR as a dependency with a *runtime* scope. During the build Maven will unpack the WAR and then copy over (aka overlay) everything from src/main and repackage it again. <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ... <build> <finalName>portal-web</finalName> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> <configuration> <warName>${project.build.finalName}</warName> <outputFileNameMapping>@{artifactId}@.@{extension}@</outputFileNameMapping> <overlays> <overlay> <groupId>com.liferay.portal</groupId> <artifactId>portal-web</artifactId> </overlay> </overlays> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.liferay.portal</groupId> <artifactId>portal-web</artifactId> <!-- Include a specific version of Liferay with a release --> <version>${liferay.version}</version> <type>war</type> <scope>runtime</scope> </dependency> </dependencies> </project> You can even exclude some of the JARs that are already in the WEB-INF/lib directory, such as the JAI JARs, if your OS already provides them or for some other reason. Excluding a JAR dependency in the configuration section of the Maven WAR plugin and then adding a dependency to your overridden version in pom.xml will make sure your custom overlayed JAR will get added instead of the original one. If you just want to add an additional JAR then you only need to add it as a dependency, e.g. a platform specific Xuggler JAR.   The portal service JAR The next type of overlay is a JAR overlay. This is slightly more complicated, but can still be accomplished by using a pretty standard Maven plugin: the Maven Dependency plugin. The unpack goal during the prepare-package phase allows us to unpack a JAR to the target directory of our module. We then need to provide the pluging with a list of files we want to exclude so that we can override them with our own. We'll calculate this list using the Maven Groovy plugin, based on the contents of the src/main/java directory. <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ... <build> <finalName>portal-service</finalName> <plugins> <plugin> <groupId>org.codehaus.gmaven</groupId> <artifactId>gmaven-plugin</artifactId> <executions> <execution> <id>generate-patched-file-list</id> <phase>compile</phase> <goals> <goal>execute</goal> </goals> <configuration> <source>${basedir}/src/main/groovy/listfiles.groovy</source> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack</id> <phase>prepare-package</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>com.liferay.portal</groupId> <artifactId>portal-service</artifactId> <version>${liferay.version}</version> <type>jar</type> <overWrite>true</overWrite> <outputDirectory>${project.build.directory}/classes</outputDirectory> <excludes>${patched.files}</excludes> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> ... </project> The actual magic that calculates the list of exclusions happens in the listfiles.groovy file: def files = [] new File(project.build.directory).eachFileRecurse() { file -> def s = file.getPath() if (s.endsWith(".class")) { files << "**" + s.substring(s.lastIndexOf('/')) } } project.properties['patched.files'] = files.join(",") The other Liferay JAR files, like util-java.jar, util-bridges.jar, ... or basically any other JAR (e.g.: I patched the PDFBox library in Liferay like this) can be overlayed in a similar way.   Overlay-ception The third and most peculiar overlay we might need to do is related to something special Liferay does while hot deploying a WAR. Depending on the contents of the liferay-plugin-package.properties file of your portlet the Liferay deployer will copy one or more JARs (util-bridges.jar, util-java.jar, util-sl4j.jar and/or util-taglib.jar), that are embedded in the /com/liferay/portal/deploy/dependencies folder of portal-impl.jar over to the WEB-INF/lib directory of your deployed module. There are also a bunch of other files, like DTDs, in there, that you might want/need to override, that are also copied over in some cases depending on your configuration.   If you for example had to override util-taglib.jar to fix something, you will not only need to make sure your customized version gets included in the overlayed WAR file, but you'll also need to put it in the correct location in your overlayed portal-impl.jar that also needs to be included in the overlayed WAR file. For this we'll again use the Maven Dependency plugin, but instead of just 1 execution that unpacks the JAR we need to add a 2nd execution that uses the copy goal to copy all provided artifactItems (basically dependencies) to the correct location inside of the target directory. So first it will unpack the original contents of the JAR, then overlays it with any custom classes/resources and lastly it will copy over any overlayed libraries. <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> ... <build> <finalName>portal-impl</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> ... <execution> <id>copy-overlay</id> <phase>generate-sources</phase> <goals> <goal>copy</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>be.planetsizebrain.liferay</groupId> <artifactId>util-taglib-overlay</artifactId> <outputDirectory>${project.build.directory}/classes/com/liferay/portal/deploy/dependencies</outputDirectory> <destFileName>util-taglib.jar</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.liferay.portal</groupId> <artifactId>portal-impl</artifactId> </dependency> <dependency> <groupId>be.planetsizebrain.liferay</groupId> <artifactId>util-taglib-overlay</artifactId> </dependency> ... </dependencies> </project> When I finally figured out how to get the above to work I was like:    Deploy package One last special thing we'll use Maven for is to create what we call a deploy package. A deploy package is basically a ZIP file that contains everything that is needed to do a deploy on a server or even locally on a developer's machine. While currently there are alternative options for this like Docker we find that at a lot of customers this isn't always an option. Our deploy package solution will work on just about any Unix based OS as it only uses (Bash) scripting. Some nice additional functionality is possible if your servers have access to some sort of Maven repository like a Nexus or Artifactory, but it isn't needed per se. If you have access to a repository you only need to put the deploy script on the server and it will download the deploy package for you and install it. If you don't have access to a repository you'll need to first download the package yourself and transfer it to the server and then run the script.   Building the package The packaging of the ZIP is done using the Maven Assembly plugin in the deploy module. The deploy module needs to be last module in your list of modules of your root pom.xml for it to be able to correctly reference all the build artifacts. Because we want to be able to use this package, together with the script described in the next section, to be able to produce a reproduceable deploy, it really needs to contain just about everything and the kitchen sink:
  • a base Liferay Tomcat bundle
  • any hotfixes/patches/security fixes
  • the patching tool itself (if you need a newer version than available in the bundle)
  • a database driver (unless already present in the bundle above)
  • your overlayed Liferay WAR or JARs
  • all your custom portlets, hooks, themes & layouts
  • any Marketplace portlets you use (possibly overlayed using the techniques described above)
  • all the configuration files, like the portal-ext.properties, Tomcat's setenv.sh, license files, etc..., for all environments (so 1 bundle can be used)
Basically anything you can put in a Maven repository and can reference in your deploy module's pom.xml can be packaged into the deploy package. If your server environment has access to a Maven repository, some things, like the base Liferay Tomcat bundle and the patching tool, can be left out of the package as they can be downloaded just in time by the deploy script described in the next section.   This deploy module is also an excellent place to create an escrow package which is all the source code, resources and libraries that are needed to recreate a specific version of your portal. How you can do this can be found in an older blog post by me: Creating an escrow package with Maven.   How the actual package is made is defined in the assembly.xml file that is used to configure the Maven Assembly plugin. In this file we define the format of the artifact, ZIP, and where all the dependencies, defined in the module's pom.xml, need to be put in this ZIP file. In the example you'll see that:
  • using a fileSet all the configuration files, found in src/main/resources are put in the /liferay subdirectory
  • using a dependencySet all the WAR files, defined as dependencies in pom.xml, are put in the /war subdirectory
  • using a dependencySet all the ZIP files, defines as dependencies in pom/xml, are put in the /patches subdirectory 
<assembly> <id>portal-release-bundle</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>${basedir}/src/main/resources</directory> <outputDirectory>liferay</outputDirectory> <includes> <include>**/*</include> </includes> <useDefaultExcludes>true</useDefaultExcludes> <fileMode>0644</fileMode> <directoryMode>0755</directoryMode> </fileSet> </fileSets> <dependencySets> <dependencySet> <includes> <include>*:war</include> </includes> <outputDirectory>/wars</outputDirectory> <outputFileNameMapping>${artifact.artifactId}.war</outputFileNameMapping> <useProjectArtifact>false</useProjectArtifact> </dependencySet> <dependencySet> <includes> <include>*:zip</include> </includes> <outputDirectory>/patches</outputDirectory> <outputFileNameMapping>${artifact.artifactId}.zip</outputFileNameMapping> <useProjectArtifact>false</useProjectArtifact> </dependencySet> </dependencySets> </assembly> You can see that with some simple changes to the assembly.xml you could create additional/other subdirectories containing other sets of configuration files/dependencies to suit your needs.   The deploy script As this really is just a script it can basically do anything you like and can be easily modified to fit your specific needs, the server environment's constaints, etc... . The example script you can find on Github does the following actions (in order):
  • Ask for some values (that can also be provided on the commandline):
    • Which repository you want to download the package from (snapshots, releases, local)
    • Which version of the package you want to deploy (dynamically build list if not provided on command line)
    • Which environment you'll be deploying on
    • Ask which node you're deploying on in case it is a clustered environment
  • Stop the Tomcat server (and kill the process if it doesn't stop nicely)
  • Backup some files like the Lucene index or the document library
  • Remove the whole Liferay bundle
  • Download and unzip the base Liferay bundle in the correct location
  • Download and unzip the requested deploy package in a temporary location
  • Overlays our Liferay WAR overlay from the temporary location over the unzipped Liferay bundle
  • Download, unzip & configure the latest Liferay patching tool
  • Restores the backed up files
  • Cleans some Tomcat directories
  • Overlays our environment specific files over Tomcat/Liferay
  • Installs Liferay patches/hotfixes/...
  • Copies all our custom WARs to the deploy directory
  • Removes the temporary directory where we unzipped the deploy package to
  • Starts the Tomcat server again 
Depending on the actual project we've added things like Liquibase upgrades, NewRelic installation & configuration, copying additional libraries to Tomcat's lib/ext, ... or just about anything we needed because the scripting system is so flexible. While it might not be as fancy as Docker and consorts it still accomplishes (except for the OS part) about the same result: a perfectly reproduceable deploy.   Conclusion While working all this out in Maven I might have had the occasional, but typical, f*ck Maven (╯°□°)╯︵ ┻━┻ moment     but after figuring out all of this JAR & WAR monkeypatching combined with the deploy package system/script it ended up being quite flexible & powerful and made me one happy code monkey in the end!   All the example code from this post and more can be found on Github: https://github.com/planetsizebrain/monkeypatching. Jan Eerdekens 2016-02-06T22:28:32Z
Categories: CMS, ECM

How are we using Launchpad to build Launchpad Docs

Liferay - Thu, 02/04/2016 - 22:53

Back in October when we first introduced Launchpad Developer Preview, we put together a very simple documentation page for users. After seeing how people were interacting with the product we realized we needed a more robust structure.

We pushed tons of improvements but still one of the challenges for every documentation is how easy people can find the content they are looking for. That's why we decided to use Launchpad's powerful search capabilities. On this tutorial, you'll understand step by step how we solved this problem.

 

 

1. Creating a datastore in the cloud

First thing you need to do is go to liferay.io and access your account. Once you get to the dashboard, click on "Create App" (which is called "Docs" on this case) and "Create Service" (which is called "Search" on this case). Now, that we defined a namespace (/docs/search), it's time to actually create this microservice using the API Builder.

We can start with a name and description that will help other team members to maintain this API in the future. Then, we can toggle the "Data" switcher which will turn this simple endpoint into a powerful NoSQL datastore.

If you don't have an account yet, just request an invite at liferay.io  

 

2. Indexing the content

Even though our product is not open source, we wanted a very simple way for people to contribute to the documentation. That's why we decided to write everything in markdown and manage it on a public GitHub repository.

Now you might be wondering, how do we index this type of content? Well, that's the easy part.

The cool thing about Launchpad is that everything is a microservice, so we just make a HTTP POST request to that API endpoint we created earlier.

In our case, we also wrote a 5-line NodeJS script that go through these markdown files and structure them on a JSON object before sending it to Launchpad. But you can literally structure your data in whatever format you like.

 

 

3. Fetching the content

Once we have our content stored in the cloud, we need a way to fetch it too.

Fortunately, we can use the API Builder again, but this time we'll create a HTTP GET method to the same endpoint.

You can even check if your API is really working by using the API Explorer

 

 

4. Showing it in your app

We configured our datastore, we indexed our content, and we created an API to get this content. All this in like 5 minutes. Now it comes the fun part: coding!

Another cool thing about Launchpad is the API Client it provides. In our case, we want to create a search autocomplete with JavaScript so we'll just use the JavaScript API Client.

And remember, Launchpad is all about REST APIs. There are many many ways we could fetch this data, feel free to use any programming language you prefer.

If you have any questions, please leave a comment. I hope this article can help you understand the power of Launchpad. Next time you need a search engine, remember that Launchpad can help you :)

Zeno Rocha 2016-02-05T03:53:19Z
Categories: CMS, ECM

Liferay IDE 3.0 Milestone 1 Release

Liferay - Wed, 02/03/2016 - 13:57

Hello all, I apologize it has taken so long to release a new version of Liferay IDE that supports Liferay 7 development.  But today we are pleased to announce the first milestone release for Liferay IDE 3.0.  And to quote a famous first line of a movie recently released:  "This will begin to make things right."

For Eclipse Luna (4.4) and Mars (4.5), you can install from following updatesite URL:

http://releases.liferay.com/tools/ide/latest/milestone/

If you are interested in downloading a Mars.1 + Liferay IDE bundle you can find those on the Liferay IDE downloads page

New Features in Liferay IDE 3.0 M1 Liferay 7 Server Support

Now you can setup and run/debug Liferay 7 servers.  Note that this supports all Liferay 7.x bundles, including non-tomcat bundles.

Also the server publishing of modules has been improved to directly publish bundles to the module framework in Liferay portal since webapp deployment is no longer supported going forward, all modules (even wars) will be installed via the module framework.  During development if you have deployed any modules, any changes you make to the bundle, on save of the file, the bundle will be immediately rebuilt and reinstalled into the running Liferay 7 module framework.

Once you have launched Liferay 7 server, and you want to interact with OSGi runtime you can do that with the new Gogo shell integration.

Liferay 7 Module Dev Support

In Liferay 7 the new method of extending / customizing Liferay is through modules (OSGi bundles).  So in Liferay IDE we have added support for developing these modules through New Project wizards, recognizing both gradle and maven based module projects, and deploying these modules to Liferay 7.

New Liferay Module Project Wizard

In this wizard you can create new individual module projects based on different templates.  For 3.0 M1 only "gradle" type of modules can be created.  We are working on maven versions that should be ready 3.0 GA.

The 2nd page of the wizard gives you ability to customize the Java class that will be the DS Component class.

If you choose "service" as the module template then on this page you can specify which "service" you are trying to implement.  This is useful for implementing on of the many OSGi integration points for extending Liferay 7 UI.

Gradle / Maven bundle projects

We have included Gradle support through Eclipse Buildship plugin that is bundled with Liferay IDE.  Maven bundle project support is via the Eclipse m2e plugin (also available as a Liferay IDE feature).  

For a bundle project that uses gradle, you can import it with the File > Import > Gradle project.  Any gradle project that applies either the Liferay gradle plugin or bnd builder gradle plugin will be recognized as a "Liferay 7 module".

Maven projects that use either "maven-bundle-plugin" or "bnd-maven-plugin" are recognized as "Liferay 7 module" projects.  

Any project that is a "Liferay 7 bundle" can be published (deployed) to Liferay 7 server in the servers view.  And for each resource in the bundle that is modified in the IDE, the bundle will immediately be rebuilt and reinstalled into Liferay 7 module framework.

Future Blog posts

There are many new development tools related to Liferay IDE and Liferay 7 that I would like to show you but I want to split that out into a few other blog posts, call it a series... :)

  • Liferay IDE and "Workspaces"
  • Introducing blade cli tool
  • Legacy plugin sdks projects in Liferay IDE 3
  • Migration tools for Liferay 6.2 projects

As always find us on the forums if you have questions or suggestions or bugs (warning this is milestone there are going to be some!)

Gregory Amerson 2016-02-03T18:57:30Z
Categories: CMS, ECM

Liferay Single Sign-On vai Facebook-SSO

Liferay - Tue, 02/02/2016 - 07:28
Facebook (SSO) social login configuration with Liferay Portal   Facebook as social login to Liferay Portal

     At some specific requirement portals needs allow users to login with cridentails of popular social sites Like FacebookGoogle+ , Twitter  ...etc many mores social cridentails.

    For enable Facebook SSO with Liferay  Portal follow below steps,       A)  Facebook site configuration      Follow below steps,       -          Create new app from https://developers.facebook.com  site for websites.       -          Once app is created check goes to dashboard &

                  check appID and appSecret key   is created sucessfully.

     -         Goto  Settings -> advance -> configure redirect URI’s                   And configure bleow Redirect URI                            http://localhost:8080/c/login/facebook_connect_oauth                       Note: localhost:8080 change accordingly portal url.
      B)  Liferay Portal site configuration

 

   Follow below steps,

        -          Control panel -> Portal Settings -> Authentication -> Facebook tab

        -          Enable face login check box.

        -          Add appID and appSecret Key genrated from Facebook configuration.



Facebook social SSO configuration done. Now you check it works fine.        Sachin J 2016-02-02T12:28:25Z
Categories: CMS, ECM

SSO via google+

Liferay - Tue, 02/02/2016 - 07:07
Social SSO with Google + Follow below metioned steps to configure Google+ sso with liferay portal. Configuration in  developers.google.com 1. https://console.developers.google.com Login with google credentials.   2. Create new project.  
3. Add Project Name  

 

 

 

4. Click on create and go to dashboard to find activated google+ api for     the project
 5. Enable the API services    6. Find the Credentials options at left corner of dashboard

                                    

7. Create Client ID and Secrete key for app   - Note before create client ID they ask for create/configure consent screen, so configured consent screen first.          

 

8. Save the details mentioned into consent screen from like Product name, homepage URL, Policies page URL, terms Page URL, logo etc..   9. Create Client ID   -          Select Web Application -          Add Name and Redirect URI’s -          Name – project  portal Name       -          Redirect URI’s - http://localhost/c/portal/google_login?cmd=token -          Click on Create button     # Save Client Id and Secrete key that we need into Liferay configuration.   - Liferay site configuration   
  1.  Download social google login hook source code and prepare war file from   https://github.com/liferayone/LR62/tree/master/google-login-hook
  2. Or get direct war file form https://github.com/liferayone/LR62/blob/master/google-login-hook-6.2.0.1.war
  3. Once download / prepare the war for google login hook then deploy it on portal.
  4. Login with admin credentials and go to Admin (Control) panel
  5. Then authentication and check for Google tab.
  6. Enable the check box and add the required details i.e. Client ID and Secrete key and saved.
  Now we can check Google social google is enabled at Login portlet of liferay.   - Source code for google login hook is available at below link, https://github.com/liferayone/LR62 Sachin J 2016-02-02T12:07:18Z
Categories: CMS, ECM

Results: Phenomenon-based learning, Valamis and Liferay deliver a jump in learning effectiveness

Liferay - Tue, 02/02/2016 - 01:57

Digital Transformation of Learning is changing the way we learn and develop. Today, technology enables a variety of different approaches to teaching and learning. Phenomenon-based learning is one of the learning pedagogies that has recently raised a lot of discussion around the world. The results of this cutting-edge approach to education are seen as so promising that Finland is among the first countries to make phenomenon-based learning part of the 2016 national curriculum. However, what kinds of concrete results can this new approach promise?

Phenomenon-based learning engages learners with real phenomena

The idea behind phenomenon-based learning is to bring learning and teaching closer to actual practice, rather than focusing on single, disconnected subjects that do not relate to everyday life or to each other, at all. Phenomenon-based learning improves for example effectiveness, problem-solving skills, and interaction between learners. It makes learning more motivating and encourages learners to creative thinking. Case PKKY is a great example of enhancing learning results with phenomenon-based learning among PKKY students.

Studies in a new learning environment: Case PKKY 

In spring 2015 we delivered to PKKY Valamis - Learning Experience Platform, which is a social learning environment that supports phenomenon-based learning. In fall 2015, Valamis was officially launched for PKKY students, which enabled learning via phenomena instead of traditional online learning. In the renewed pedagogical model special attention was paid to technical functionalities as well as the content presentation and visual learning experience. 

Four remarkable improvements in study results over one year

If we compare the study results of PKKY students from fall 2014 to fall 2015, the results are, so far, extremely positive and encouraging. After the adoption of phenomenon-based learning pedagogy, students have for example managed to complete their online studies much faster.

Below are the four most remarkable improvements in study results enabled by phenomenon-based learning, Valamis, and other pedagogical development work.
 
1. Higher pass through rate in online courses
In fall 2014 a total of 49 percent of students successfully passed their online studies provided to PKKY students. In fall 2015, the corresponding number of passed online studies was 59 percent. In January 2016, the pass through rate of online studies was already over 70 percent. 

2. Gaining better grades
Compared to fall 2014, approximately 70 percent of students gained better grades in their studies during fall 2015. In fall 2014, a total of 81 percent of those who passed their courses gained level T1 (satisfactory) in their studies. In fall 2015, the increase in grades was notable as 78 percent of students gained either level H2 (good) or K3 (excellent).  

3. Improved essay answers
According to the feedback from teachers, the quality of essay answers has improved. Students are now able to connect the topics studied with real life, which also increases the role of personal reflection in their answers. 
 
4. Easier follow-up of study progress
In the new learning environment, following learners' study progress is easier for online teachers, learners as well as for local instructors. The Learning Record Store (LRS) together with Experience API enable detailed follow-up of the study progress and with the help of a visual concept map teachers can easily locate those parts of the studies that appear to be the most challenging for learners.

Also, in Valamis learners can follow their own study progress and give and receive feedback of their studies. In summer 2015, PKKY's management made a strategic alignment to invest in the long-term development of online pedagogy, and the decisions made after that have resulted in the positive results presented above.

Moreover, a strong focus on study guidance and development, as well as the possibility to give grades and feedback without delays in Valamis, may partially explain the positive results received in such a short period of time. Also, in the PKKY case the phenomenon-based studies have been continuously developed based on the feedback received from the learners.

Free Phenomenon-based learning Webinar

If you are interested in learning more about phenomenon-based learning, join us in a free webinar as we walk through the most important aspects of phenomenon-based learning pedagogy and how it can be utilized in organizational learning with Valamis – Learning Experience Platform.
 
Webinar | February 2, 2016 | 2 pm CET (EMEA) | Register here 
Webinar  | February 3, 2016 | 9 am PST (US) | Register here

  Janne Hietala 2016-02-02T06:57:41Z
Categories: CMS, ECM

Using custom java classes in a JSP hook - A different approach

Liferay - Sun, 01/31/2016 - 04:19

How can you access custom classes within a JSP hook? Simple answer: you can't. Period.

JSPs in a hook are running in the portal classloader, while your custom classes are running in the hook context classloader. So the JSP in the portal classloader does not know about your custom classes.

In 2013 Kan Zhang wrote a blog post about how to use custom classes in a JSP hook. However his approaches all try to get the custom class into the global classloader or use a workaround by involving custom struts actions.

I would like to give a different approach.

Move the JSP to the hook context classloader

If the mountain won't come to Muhammad, Muhammad must go to the mountain

So I suggest to get the JSP into the hook context classloader instead of trying to get the custom class into the global classloader.

A litte drawback is that you need two JSPs instead of one. 

Step 1: Include a JSP from the hook context within the JSP hook

In a JSP hook we just include a second JSP using the liferay-util:include Tag. We have to pass the servletContext of the custom hook context.

<% ServletContext hookContext = ServletContextPool.get("my-sample-hook"); if (hookContext != null) { %> <liferay-util:include page="/html/hook.jsp" servletContext="<%=hookContext%>" /> <% } %>   Step 2: Write a JSP inside your hook and use your custom class

When you write a JSP inside your hook (which is outside the directory you declare in custom-jsp-dir in your liferay-hook.xml) you have full access to the classes within your hook.

<p> Hello world from <%=MyCustomClass.getHelloWorld()%> </p> Final Remarks
  • If you need additional parameters from the original JSP you can pass them as liferay-util:param tags inside the liferay-util:include tag.
  • Request or Session attributes are still available, so you can get attributes using request.getAttribute() and so on.
  • As the second JSP now runs in the hook context classloader, you no longer have access to classes from portal-impl.jar

Happing coding!

 

 

Dominik Marks 2016-01-31T09:19:48Z
Categories: CMS, ECM

Radio Liferay Episode 54: Scott Nicklous and Neil Griffin on JSR 362 - Portlet 3.0

Liferay - Tue, 01/26/2016 - 05:03

  In this episode, recorded at Liferay's Devcon 2015 in Darmstadt/Germany, I'm talking to Scott Nicklous and Neil Griffin. Scott is the specification lead for JSR-362 - otherwise known as the Portlet Specification 3.0 - and Neil serves as Liferay's representative on the expert group.

Here are some of the topics that we talked about:

  • JSR 362 page with all the latest and current information (spec, prototype implementation and javadoc)
  • The expert group
  • JSR 286 portlets will run unchanged on JSR 362 (runtime and compiletime compatibility)
  • My repeat favourite statement about frameworks in the web world.
  • JSR 362 and its impact on UI, there's a Client-Side standard (on ECMA script) for the first time in the portlet spec
  • The big question: When will it be done? (Some time 2016)
  • Early Draft Review Spec available, ~80-90% of content is expected to be there (That's the statement from Devcon, in October 2015)
  • Reference Implementation (to prove that the spec can be implemented) and TCK still missing (again, October 2015)
  • Reference Implementation and TCK will be implemented under the Apache Pluto project, help required
  • New Features include Bean-Portlet-Approach (portlet methods specified through Annotations in any Managed Bean), portlet.xml file no longer required if Annotations used
  • specifies a JS API despite being a JSR, which covers traditionally only Java
  • Dependency to JavaEE: Minimum is JavaEE 7, e.g. Servlet 3.1 etc.
  • Portlet Spec is not part of the JavaEE, but extends some of its elements.
  • CDI
  • JSR 378: Portlet 3.0 bridge for JSF (where Neil is the spec lead), being built in parallel with JSR-362
  • Multiplatform Support, Websocket, Devices
  • The E-Mail Archive of the specification process is public - contribution and comments are very welcome

Follow @RadioLiferay on twitter for news about the latest episodes, and occasionally more.

You'll find this episode - and make sure that you don't miss any of the future episodes - by subscribing to  http://feeds.feedburner.com/RadioLiferay. You can also subscribe on itunes.: Just search for "Radio Liferay" or just "Liferay" in the podcast directory. Make sure to write a review for the podcast directory of your choice - or find everything about Radio Liferay on liferay.com/radio.

Or just download the MP3 here:

Olaf Kock 2016-01-26T10:03:47Z
Categories: CMS, ECM

Crafting Content Friendly URLs

Liferay - Fri, 01/22/2016 - 19:06
Content Friendly URL? This is one of those tidbits you get served on a platter if you're lucky enough to attend a Liferay training session. Anyway, content friendly url may not be the legit term, but what I'm referring to is a URL crafted using a Journal Article's urlTitle attribute, which is stored in every journalarticle record btw.    The standard format of such a URL is; http(s)://<sitename>/-/<article-urlTitle>

For example:

http://renegadehacker.com/-/about-the-hacker

The Setup So how do we get such a URL to become available to us? Here are the steps. For convenience, consider we have a content structure named XYZ.
  1. Create a page XYZ Detail. Check the box to hide from navigation. You do this because this page is going to serve as a sort of placeholder to pickup and serve the requested content automagically (calm down: no magic, all science).
  2. Add an Asset Publisher portlet to that XYZ Detail page.
  3. Configure that Asset Publisher portlet instance to bring back Web Content Article having subtype XYZ (this corresponds to the structure for your content).
  4. On the Display Settings tab of the Asset Publisher portlet, click the checkbox to Set as the default Asset Publisher for this page.
  5. (IMPORTANT and easy to miss) Edit each course content item, click the Display Page option on the right-hand-side. Select the XYZ Detail page as the display page. 
  Now, if you have a web content item (aka journalarticle for newbies) with a title: The Rain in Spain stays mainly in the plain, you will be able to get to it using: http://renegadehacker.com/-/the-rain-in-spain-stays-mainly-in-the-plain/   It Doesn't Work! One thing to try out (apart from ensuring you carried out the above steps) is to check the urlTitle for that journal article in the journalarticle table of your database. Good chance it is quite different than what you expected it to be. Well, that is what you have to use, and that is what the urlTitle reserved variable in velocity brings back. But why is it different?   Here is what I noticed: The very first value you give to the title gets copied into the urltitle for your article and it sticks no matter what you change the title to after that.   And that my friends, is your friendly report on content friendly URLs, if that be the friendly term for it. Javeed Chida 2016-01-23T00:06:13Z
Categories: CMS, ECM

Valamis 2.6 Enterprise Edition release - New Features Summary

Liferay - Thu, 01/21/2016 - 06:16
We are glad to announce that the new Valamis 2.6 Enterprise Edition has now been released. In this release new features have been introduced especially to the Lesson Studio. Also, importing questions from Moodle to Valamis environment is now possible.

New Features & Improvements

One of the biggest improvements in the Lesson Studio is that the Lesson Studio now enables responsive content design for three different device types: mobile, tablet, and desktop. In addition, Valamis 2.6 now has an easy-to-use content import feature, which enables content import from Moodle to Valamis. We have also made general UX improvements to the Valamis 2.6 in order to enhance the user experience.
 

Valamis 2.6 Release Notes

The official release notes give you a holistic overview of all the new and updated features of Valamis 2.6 Enterprise Edition Release. You can read the full release notes from the link below.

RELEASE NOTES


Valamis Delivery Channel

We have created our own delivery channel for Valamis releases. This allows us to provide smalle increment updates and patches faster to users. From now on, you can always get the latest, up-to-date version of Valamis - Learning Experience Platform from here: Valamis Delivery Channel. We will still continue to support Valamis Enterprise Edition via Liferay Marketplace, but this is done after Liferay Marketplace QA is passed.

Valamis - Learning Experience Platform is an advanced learning solution platform, which supports learning independent from time and place. Valamis provides organizations a solution for turning digital transformation of learning into competitive advantage. 

Interested in Valamis? If you are interested in learning how Valamis - Learning Experience Platform works in a reality, you can request a Valamis demo from the button below.

 

REQUEST A DEMO

Janne Hietala 2016-01-21T11:16:05Z
Categories: CMS, ECM

Digital Transformation of Learning as Competitive Advantage

Liferay - Wed, 01/20/2016 - 05:51

We are approaching a point in time where the rapid acceleration of technology related to education, course development, and learning has produced large amount of content and knowledge concepts. Today learners of all ages are able to reach the content simply providing that they have an access to the internet and a computer or a mobile device. Deciding when and where individuals learn is no longer time and place dependent. Thus, accelerating learning with the help of digitalization is becoming a critical success factor for organizations.

Nature of work is changing

The current change in the nature of work and digitalization are creating challenges for organizations as learning is becoming more measurable, developable, and goal-oriented. At the same time, work is becoming more spontaneous, virtual and hyperconnected. According to Gartner*, the more de-routinized nature of work has started to increase the amount of working virtually or physically in swarms. Gartner** states, that in the future many organizations are planning on investing more in IT and digital capabilities. Yet, a substantial part of organizations still lacks understanding of what digital business means and what kind of challenges it will bring to them.


How to prepare for the digital transformation of learning

By preparing for the digitalization of learning, organizations can raise their ability to transform faster and gain competitive advantage against their competitors. In our upcoming white paper we ponder the changing nature of work and organizational learning. The following key takeaways summarize how we think organizations should prepare themselves for the digital transformation of learning.

1. Launch digital workplace initiatives
Internal initiatives are in a key role when organizations prepare themselves for a smooth transition into a digital economy. In order to maximize the effectiveness of a digital workplace, it is critical to understand how the sources of motivation and engagement vary between different generations of workforce. By internally implementing digital workplace initiatives, it is easier for organizations to increase employee agility, engagement, and effectiveness in the transition. 

2. Enhance organizational capability
As work is becoming more spontaneous and hyperconnected, organizations need to develop their organizational capabilities to respond to the new operating models introduced by the digitalization. It is critical to engage people in changing their mindset and behavior to suit the new ways of working, such as working virtually in swarms. Without a proper understanding of the digitalization and the changes it brings along, it is challenging for the workforce to absorb the transforming nature of work.

3. Ensure cooperation between CIOs and HR
Organization CIOs and HR need to work closely together in order to define the technology capabilities for digital work, digital learning, and digital workforce development designed to facilitate the change. Note, that it is not enough to aim at replicating the physical world processes as the working skills required in digital domain are different.

4. Measure & analyze learning
Today learning and problem solving often happen in social and informal scenarios. Whether formal or informal, it is crucial for companies to have tools to both measure and analyze all types of learning activities. Take into account, that the ability to measure learning will be closely tied to the actual ability to execute. 

Now is the time for organizations to re-examine own learning management systems' ability to meet the new challenges brought by the digitalization. We believe that the digital transformation of learning is the next great challenge facing all organizations. And it is happening now. 

Dr. Charles Camarda, Astronaut, NASA                            
Janne Hietala, Chief Commercial Officer, Arcusys

Competitive advantage from digital transformation

We are glad to announce that our new white paper on topic Digital Transformation of learning - Why We Need Another "Apollo Effect" is now available. The paper will clarify the interconnected nature of learning and provide unique insights into the learning and problem solving at NASA. Learn more about turning the digital transformation of learning into your competitive advantage and download your copy now!

GET WHITE PAPER

* Gartner research note: Continuing Changes in the Nature of Work, 2010-2020 (2010)
** Gartner research note: Creating Your Digital Edge Through a Competency-Based Talent System (2014)

Janne Hietala 2016-01-20T10:51:37Z
Categories: CMS, ECM

Tip of the Day - Enhance Your Analytics With Hooks

Liferay - Tue, 01/19/2016 - 11:05

Liferay allows using site specific Google Analytics tracking codes to analyze the traffic inside your portal. Adding the code is simply a matter of going to the site settings and saving the code you need.

Insert your google analytics id in site settings

However, the default version of Liferay's Google Analytics code might not be enough in some cases, as it offers only the basic analytics features. While they are enough for some cases, Google is also offering you their own official plugins and also a chance to build plugins of your own. More information about plugins in Google Analytics can be found here.

Original analytics code in Liferay 6.2 EE SP13 as seen in HTML

Now that you've realised that the default Liferay way of adding the analytics code to your site is not enough, you want to enable a ga-plugin. What can you do? You could add the script itself directly to your theme, but it might not be the best option if you want your portal to be maintainable. Creating a custom portlet to do the job is a possibility as well, you could embedd it to your theme or whatever. The way we've done this at Ambientia is that we've created a google analytics hook, which overrides the default way how Liferay creates the tracking code.

Now depending on your portal version, you need to do a bit of searching to find the place where the analytics script is added to your portal. In Liferay 6.2 the code resides in a file called top_js.jspf which can be found from "html/common/themes" folder. So to enable the custom analytics plugins needed, you'll just override the file with a hook to add the plugins you want to include. Also if you have a very specific need to enable ga plugins on a site or two, you might be able to create the hook as an application adapter and enable it only on the sites you need.

Analytics plugin "displayfeatures" added via hook

There you have it, enhancing your analytics with a hook is a simple task.

Lauri Hiltunen 2016-01-19T16:05:25Z
Categories: CMS, ECM

Where am I? (how to know which cluster node you're on)

Liferay - Sun, 01/17/2016 - 15:26

When working with a cluster you pretty quickly come to a point where you want/need to know what cluster node you're on.

Liferay already has a simple way to show you this. You just need to add the following line to your portal-ext.properties and hey presto! it shows the current web server node ID in a blue box at the bottom of the page:

web.server.display.node=true

While this works perfectly it has one drawback: customers don't really want to see this in production, while we need it at times to be able to debug a problem. There are a number of ways to solve this catch 22 type of situation:

  • Leave the property turned on but hide the blue box using CSS. This allows you to check the value by using the inspect element functionality found in most browsers these days.
  • Turn off the property and add a hidden page that contains a web content display portlet that uses a simple Velocity/Freemarker template to show the same value (which according to the file Liferay uses, /html/portal/layout/view/common.jspf, is PortalUtil.getComputerName()).

I want to present a 3rd option: extend the dockbar with a new icon that allows you to display the node ID (and other cluster node specific data). For this we'll need to override /html/portlet/dockbar/view.jsp and add some code to it.

First is the button which we'll add right before the Toggle Edit Controls button:

<c:if test="<%= showEditControls %>"> <portlet:renderURL var="editLayoutURL" windowState="<%= LiferayWindowState.EXCLUSIVE.toString() %>"> <portlet:param name="struts_action" value="/dockbar/edit_layout_panel" /> <portlet:param name="closeRedirect" value="<%= PortalUtil.getLayoutURL(layout, themeDisplay) %>" /> <portlet:param name="selPlid" value="<%= String.valueOf(plid) %>" /> </portlet:renderURL> <aui:nav-item anchorId="editLayoutPanel" cssClass="page-edit-controls" data-panelURL="<%= editLayoutURL %>" href="javascript:;" iconCssClass="icon-edit" label="edit" /> </c:if> <c:if test="<%= PropsValues.WEB_SERVER_DISPLAY_NODE %>"> <aui:nav-item cssClass="toggle-cluster-link" iconCssClass="icon-map-marker" /> </c:if> <c:if test="<%= showToggleControls %>"> <aui:nav-item anchorCssClass="toggle-controls-link" cssClass="toggle-controls" iconCssClass='<%= "controls-state-icon " + (toggleControlsState.equals("visible") ? "icon-eye-open" : "icon-eye-close") %>' id="toggleControls" /> </c:if>

Secondly we'll need some CSS and Javascript (which we add to the existing aui:script tag) to be able to add an action to our new button that will show a popover with the information we want:

<style type="text/css"> .popover, .aui .popover.right .arrow { z-index: 1000 !important; } </style> <% StringBuilder nodeInfo = new StringBuilder(); nodeInfo.append("<ul>"); nodeInfo.append("<li>Host: " + PortalUtil.getComputerName() + "</li>"); nodeInfo.append("<li>ID: " + com.liferay.portal.kernel.cluster.ClusterExecutorUtil.getLocalClusterNode().getClusterNodeId() + "</li>"); nodeInfo.append("<li>IP: " + com.liferay.portal.kernel.cluster.ClusterExecutorUtil.getLocalClusterNode().getInetAddress() + "</li>"); nodeInfo.append("</ul>"); %> <aui:script position="inline" use="liferay-dockbar,aui-popover"> Liferay.Dockbar.init('#<portlet:namespace />dockbar'); var customizableColumns = A.all('.portlet-column-content.customizable'); if (customizableColumns.size() > 0) { customizableColumns.get('parentNode').addClass('customizable'); } // Add cluster node ID var trigger = A.one('.toggle-cluster-link'); if (trigger != null) { var popover = new A.Popover( { align: { node: trigger, points:[A.WidgetPositionAlign.LC, A.WidgetPositionAlign.RC] }, bodyContent: '<%= nodeInfo %>', position: 'right', visible: false } ).render(); trigger.on( 'click', function() { popover.set('visible', !popover.get('visible')); } ); A.one('body').on( 'key', function() { // http://keycode.info/ popover.set('visible', !popover.get('visible')); }, 'down:78+shift' ); } </aui:script>

The Javascript code above also adds a keyboard shortcut, SHIFT+N, to the button so that you can even show the popover without even needing to click the button. You can find the complete file here: https://gist.github.com/planetsizebrain/3f9788a78224be73d80b. This will give you the following result:

If you want something similar, but don't want to add a button to the dockbar, you could use similar code to make the existing blue bar appear/disappear when a shortcut is pressed.

Jan Eerdekens 2016-01-17T20:26:09Z
Categories: CMS, ECM

Improve your Liferay and Tomcat logging

Liferay - Sun, 01/17/2016 - 09:22

I recently started working on integrating Liferay with ElasticSearch + Logstash + Kibana, also known as ELK Stack. Every Liferay developer knows very well where to search for logs and what they exactly mean, but very few had time to look closer at the mechanism as a whole. Therefore, I decided that the first step will be to analyze current logging system in Liferay (bundled with Tomcat, as that is still the most common type of deployment) and make some improvements that will make it work smoother with Logstash - the tool responsible for parsing logs and feeding ElasticSearch with their's JSON representation.

All concepts presented in this article were tested on Liferay Portal 6.2 CE GA5 so they should work without any problems on all 6.2 releases, and with some minor changes on 6.1.

How does it work on fresh installation?

By default, Liferay/Tomcat prints all their log messages into the following files:

  • liferay-portal-6.2-ce-ga5/logs/liferay.2016-01-16.log - Standard Liferay Log4j log, configured in portal-log4j.xml from portal-impl.jar.
  • liferay-portal-6.2-ce-ga5/tomcat-7.0.62/logs/
    • catalina.out - Tomcat's stdout and stderr streams directed to this file by catalina.sh during startup.
    • catalina.2016-01-16.log - Standard Tomcat logs configured in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/logging.properties.
    • host-manager.2016-01-16.log and manager.2016-01-16.log - Tomcat's Manager webapp logs (not present in Liferay/Tomcat bundle), configured via liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/logging.properties.
    • localhost.2016-01-16.log - Another Tomcat log configured in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/logging.properties.
    • localhost_access_log.2016-01-16.txt - Tomcat access log configured in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/server.xml.

It turns out that log configuration is stored in four different places! Additionally there are two other logging-related files - log4j.properties and logging.properties in folder liferay-portal-6.2-ce-ga5/tomcat-7.0.62/webapps/ROOT/WEB-INF/classes, but they don't seem to be used anywhere.

What is wrong with default configuration?

The first problem is redundancy - all Tomcat and Liferay logs are both written to their own files and standard output. It means that all entries from catalina.2016-01-16.log and liferay.2016-01-16.log are at the same time written to catalina.out which is not rolled-over! According to what Tomcat documentation says "CATALINA_BASE/logs/catalina.out does not rotate. But it should not be an issue because nothing should be printing to standard output since you are using a logging package, right?".

The other problem is standard log format, which for Tomcat it looks like this:

Dec 08, 2015 8:19:57 PM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-bio-8080"] Dec 08, 2015 8:19:57 PM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["ajp-bio-8009"] Dec 08, 2015 8:19:57 PM org.apache.catalina.startup.Catalina load INFO: Initialization processed in 1387 ms

and for Liferay:

20:21:22,208 INFO [localhost-startStop-1][DialectDetector:71] Determine dialect for PostgreSQL 9 20:21:22,318 INFO [localhost-startStop-1][DialectDetector:136] Found dialect org.hibernate.dialect.PostgreSQLDialect 20:27:12,862 INFO [localhost-startStop-1][StartupAction:97] There are no patches installed 20:27:14,270 INFO [localhost-startStop-1][BaseDB:481] Database supports case sensitive queries 20:27:15,165 INFO [localhost-startStop-1][VerifyProcess:65] Verifying com.liferay.portal.verify.VerifyProcessSuite

Both don't provide enough information for Logstash, first will not work when locale are different than 'en' and second does not even print a full date.

How can we improve it?

There are two common improvements that can be applied either to the Tomcat server and to Liferay webapp.

  • Remove logging redundancy - turn off appenders/handlers responsible for writing messages to stdout
  • Update datetime pattern to include full date, time and timezone (if possible)

Other changes are module-specific and have been described in the next two sections.

Tomcat

Tomcat logging is configured in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/conf/logging.properties. In this case, we should take the following steps:

  • Remove java.util.logging.ConsoleHandler responsible for logging to stdout (occurs in several places in configuration).
  • Introduce new SimpleFormatter date pattern. Unfortunately I didn't manage to configure ISO8601 timezone (formatted as +0000 or +00:00), so in this case it wil be necessary to indicate proper timezone later, in Logstash settings.
  • Remove unnecessary log files for standard Tomcat webapps - manager/host-manager.

Updated logging.properties is available below (check out gist revisions to see what changes have been made to original version): 

After applying the changes, you will notice that manager.[date].loghost-manager.[date].log log files are gone and messages within catalina.[date].log, has been supplemented by full date and source sections:

[16.01.2016 12:36:40,116] INFO [org.apache.coyote.AbstractProtocol init] Initializing ProtocolHandler ["http-bio-8080"] [16.01.2016 12:36:40,138] INFO [org.apache.coyote.AbstractProtocol init] Initializing ProtocolHandler ["ajp-bio-8009"] [16.01.2016 12:36:40,142] INFO [org.apache.catalina.startup.Catalina load] Initialization processed in 876 ms [16.01.2016 12:36:40,182] INFO [org.apache.catalina.core.StandardService startInternal] Starting service Catalina [16.01.2016 12:36:40,183] INFO [org.apache.catalina.core.StandardEngine startInternal] Starting Servlet Engine: Apache Tomcat/7.0.62 Liferay

Liferay original configuration is stored in META-INF/portal-log4j.xml from liferay-portal-6.2-ce-ga5/tomcat-7.0.62/webapps/ROOT/WEB-INF/lib/portal-impl.jar. Thanks to the Liferay Logging architecture (more precisely to those lines coming from com.liferay.util.log4j.Log4JUtil), we are able to update log4j configuration without the need to repackage jar file. In order to do that, we have to create two files in liferay-portal-6.2-ce-ga5/tomcat-7.0.62/webapps/ROOT/WEB-INF/classes/META-INF/:

  • log4j.dtd copied from github or directly from portal-impl.jar/unzip://META-INF/log4j.dtd
  • Empty portal-log4j-ext.xml to which will contain all configuration settings that override these from portal-log4j.xml

As you can see in the following snippet of newly-created portal-log4j-ext, there are only two small sections of original file present:

  • File Appender which allows us to modify timedate pattern.
  • root section with <appender-ref ref="CONSOLE" /> removed.

(Again, check out gist revisions to see the exact changes)

After applying the changes, liferay logs will look as follows:

[16.01.2016 12:37:03,626 +0000] INFO [localhost-startStop-1][DialectDetector:71] Determine dialect for HSQL Database Engine 2 [16.01.2016 12:37:03,630 +0000] WARN [localhost-startStop-1][DialectDetector:86] Liferay is configured to use Hypersonic as its database. Do NOT use Hypersonic in production. Hypersonic is an embedded database useful for development and demo'ing purposes. The database settings can be changed in portal-ext.properties. [16.01.2016 12:37:03,698 +0000] INFO [localhost-startStop-1][DialectDetector:136] Found dialect org.hibernate.dialect.HSQLDialect [16.01.2016 12:42:09,041 +0000] INFO [localhost-startStop-1][StartupAction:97] There are no patches installed Note that Liferay's JVM timezone must be set to GMT (via proper parameter in setenv.sh), otherwise datetime calculations may be incorrect. Additionally, it is generally recommended that logs should be stored in GMT and then presented in local time. However, in our case it is not a problem as Kibana - the tool used for browsing logs - uses client's browser timezone. Summary

In this article I briefly described Liferay+Tomcat logging system and proposed some changes that will make it's integration with ELK stack easier. I focused on regular Tomcat and Liferay logs as they caused the most problems to Logstash. There are also two other files that I ommitted for the following reasons:

  • localhost_access_log.2016-01-16.txt - This log follows the common access-log pattern so I don't think there will be any problem for Logstash to process it correctly.
  • catalina.out - After removing console appenders from tomcat logging and liferay log4j configs, there are only few lines left in catalina.out. Furthermore, they cannot be altered withouht recompiling Liferay sources as they are printed as a result of System.out.println(...) method.

In the foreseeable future I plan to play more with Liferay / ELK integration and if I get any results worth publishing, I will put them in my next blog posts. If you want to do that on your own, I'd recommend to study resources from Eric's Chin session at Liferay North American Symposium 2015, available at his github: https://github.com/ericchin/nas2015.

Krzysztof Gołębiowski 2016-01-17T14:22:41Z
Categories: CMS, ECM

2015 Q3-Q4 Top Contributors and What Comes Next

Liferay - Thu, 01/14/2016 - 16:13
Back in 2012 we began a quarterly program to recognize those of you who have over the years contributed more to Liferay than your average open source enthusiast. Each quarter we recognize the top contributors and the last 2 quarters are no different. These individuals have contributed code, blogs, helped out on the forums, and generally improved the Liferay community during the second half of last year!   2015 Q3 Top Contributors Meera Prince Liferay & Java Sr. Technical Consultant, IAMSURAJ   Denis Signoretto Project Manager & Java Developer, Intesys S.r.l.   Lauri Hiltunen Software developer, Ambientia   2015 Q4 Top Contributors Matti Tahvonen Sr. Vaadin Expert, Vaadin   Abhishek Kumar Sr. Liferay Developer, Albero Technology   More details about each of these individuals can be found on the Liferay Developer Network's Contributors page!   Coming Soon: Liferay 7 and the Ultimate Challenge As you all know, Liferay 7 is right around the corner. If you've been participating in the Community Expedition, you'll be very familiar with the awesome changes in architecture, tools, and possibilities that are introduced with the new release, which is almost upon us. If you're not, sign up today!   Those changes I hope will also have a profound impact on our open source community, and I believe we can and should take advantage of it as much as possible. As I discussed during my community talk @ DevCon, we are working on a new program for recognizing rockstars in our community. This will essentially be a much more realtime and fine-grained way to recognize those who continue to do what they do - give a little back to the community through a variety of methods.   We'll have much more detail on this as we get closer to the release, but it will be effectively taking the place of our quarterly top contributors going forward. Participation, contribution, and the awesome feeling one gets when they share knowledge is what I believe drives our community, and we will crank it way up in the very near future. Exciting times ahead! James Falkner 2016-01-14T21:13:31Z
Categories: CMS, ECM

Liferay 6.2 CE GA6 Now Available

Liferay - Thu, 01/14/2016 - 08:11

I'm very happy to announce the release of Liferay Portal 6.2 CE GA6! Download it now: [Tomcat Bundle] [JBoss Bundle] [GlassFish Bundle] [Source Code] [Other bundles and Files] [Quick Start] [Detailed Install Instructions].

This is a minor update to address a significant incompatibility discovered in our community with Liferay  Sync. As Liferay 7 is right around the corner, we wanted to do this release so that those of you staying on 6.2 will be able to use Sync (and other mobile apps that heavily rely on JSONWS). No new features are added, and only these 9 commits are included.

The release also includes the latest Sync Connector plugin, so that you do not need to update it separately.

Release Naming

Following Liferay's official versioning scheme, this release is Liferay Portal 6.2 CE GA6. The internal version number is 6.2.5.  See below for upgrade instructions from 6.2.x, 6.1.x, 6.0.x, and 5.x.

Downloads

You can find the 6.2 CE GA6 release on the usual liferay.com downloads page (it might take an extra day to get this page updated, so use the above download links in the meantime). If you need additional files (for example, upgrade SQL scripts or dependency libraries), you can find them at the bottom of the downloads page.

Maven Artifacts

Developers can (or should be able to in the next day or so) find this release in our Maven repository, and it should be showing up on Maven Central in the near future. As a reminder, you can also find Maven artifacts for Liferay 7 Preview & Beta Releases (here's one of them) in the liferay-previews repository!

Source Code

As Liferay is an open source project, many of you will want to get at its guts. The source is available as a zip archive on the downloads page, or in its source code repository on Github. The repository has also been tagged for the release (as a reminder, the liferay-plugins repo no longer gets tags for portal releases as the plugins are de-coupled from core). Many community contributions went into this release, and hopefully many more in future releases! If you're interested in contributing, take a look at our new participate page on the Liferay Developer Network.

What's New / Changed?

This update fixes a JSONWS incompatibility introduced in GA5. If you are experiencing issues with Sync with GA5, you'll need to update to this release. Even if you don't use Sync, you should update to this release, as the issue could affect other apps that use JSONWS. Part of the fix is in the sync-connector plugin, which is bundled with this release.

Documentation

The Liferay Documentation Team has been continuously adding and improving on the official documentation. This includes updated javadoc and related reference documentation, updated tutorials and learning paths, and a new home on the Liferay Developer Network.

Our community has been instrumental in identifying the areas of improvement, and we are constantly updating the documentation to fill in any gaps. Check out Rich's blog for more detail on how you can get involved.

Support Matrix

Liferay has published the official compatibility matrix for 6.1 and 6.2. This is the official support matrix for our Enterprise Subscription customers, but it's a pretty good reference for CE as well.

Liferay Marketplace

Most Liferay-authored Marketplace plugins were updated to support 6.2 GA1 when it was first released, and remain compatible with this updated GA6 release.

If you are a Marketplace Developer, and have authored a 6.2 CE GA1-GA5-compatible app, you should ensure your app continues to work with this 6.2 CE GA6 release. It is Liferay's aim to remain compatible within a given release family, so in the unlikely event that your app works with GA5 but NOT GA6, you will need to make any necessary changes and re-submit, and let the Marketplace team know about any incompatibilities you discovered. Chances are you will have nothing to do (since you declared compatibility with 6.2.0+, which includes 6.2.5).

Bug Reporting

As always, the project continues to use issues.liferay.com to report and manage bug and feature requests. If you believe you have encountered a bug in the new release (shocking, I know), please be cognizant of the bug reporting standards and report your issue on issues.liferay.com, selecting the 6.2.5 CE GA6 release as the value for the Affects Version/s field.

Upgrading

Good news for those of you on 6.0 or prior! Liferay introduced the seamless upgrade feature with Liferay 6.1. Seamless upgrades allow Liferay to be upgraded more easily. In most cases, pointing the latest version of Liferay to the database of the older version is enough. There are some caveats though, so be sure to check out the Upgrading Liferay information on the Liferay Developer Network for more detail on upgrading to this release.

Getting Support

Support for Liferay 6.2 CE comes from the wonderful and active community, from which Liferay itself was nurtured into the enterprise offering it is today. Please visit the community pages to find out more about the myriad avenues through which you can get your questions answered, and check out the new Liferay Developer Network for technical resources during your Liferay journey.

Liferay and its worldwide partner network also provides services, support, training, and consulting around Liferay via its Enterprise Subscription.

What's Next

Of course we in the Liferay Community are interested in your take on the new features in Liferay 6.2 and the updates in this GA5 release. We've been working on the next evolution of Liferay, based on user feedback and community ideas, and work is nearing completion. If you are interested in learning more, join our expedition team and see what's under the hood of Liferay 7!

As I mentioned earlier, we do regular open source releases of Liferay Portal every 6 months, until the next major release. So if you find bugs in this or previous releases, and want to up their priority to get them fixed, be sure to use JIRA and vote for your favorite issues! The next CE release will most likely be based on Liferay 7.

Kudos!

This release was produced by Liferay's worldwide portal engineering team, and involved many hours of development, testing, writing documentation, translating, testing some more, and working with the wider Liferay community of customers, partners, and open source developers to incorporate all sorts of contributions, both big and small. We are glad you have chosen to use Liferay, and hope that it meets or exceeds your expectations!

In addition to Liferay's engineering staff, a special thanks goes to the many open source developers who volunteered their time and energy to help with the release, whether it was bugfixing, idea generation, documentation, translations, testing, or other contribution that helped to improve this release. Check out the Community Contributor Hall of Fame and be sure to thank them if you run across them in the community (or add your name if you have contributed and are not listed).

James Falkner 2016-01-14T13:11:15Z
Categories: CMS, ECM

Open Services Gateway Initiative (OSGi) Introduction

Liferay - Fri, 01/08/2016 - 09:44
The Open Services Gateway Initiative (OSGi) is specification that defines modular based software management and its execution. OSGi makes software management and its execution simpler by making large application into small bunch of pieces and we call it as module. These modules are working independent way so that when we need we can start module and we can stop module. As for OSGi a module is Bundle or Plugin-in   OSGi provides execution environment so that we can install, start and stop module whenever we required such a way OSGi provides OSGi containers to manage lifecycle of these bundles.   Bundle/Plug-In/Software component   Bundle is a collection Java classes and resources make it as package then we call it as bundle and these bundle can be working as independent or it can be depends on other bundle or plugin. We can say bundle is small piece of software and as for OSGi we can specify as OSGi bundle.   Note:   As for our understand bundle is java jar file.   OSGi specification   https://www.osgi.org/developer/specifications/   OSGi implementations   After release of OSGi specification by OSGi Alliance in March 1999 then people implemented specifications as software and the following are popular implementation software open source groups.   Equinox   Equinox is reference implementation of OSGi from eclipse and they have implanted OSGi software so that it provides runtime environment for OSGi based software development.   http://www.eclipse.org/equinox/documents/quickstart.php   Apache Felix   Felix is also implemented OSGi specification from Apache and its open source implementation.   http://felix.apache.org/   Knopflerfish   Knopflerfish is another Open source Implementation for OSGi   https://www.knopflerfish.org/   Note:   All above implementation covered all specifications of OSGi R3 and OSGi R4 specifications.   Software Developers can use any one of the implementation to implement their software as modular based way. We can also inherited features from above all implementations.   All OSGi implementations they packages as jar file so that it will provide execution environment for OSGi bundles. OSGi have basic standalone container to execute bundles and if we want other environments support we need to take relevant environment support bundle so that it will provide execution environment for different kind of environment.   Basic OSGi implementation Jars   From Apache Felix     felix.jar     Start the framework   From the installation directory by typing in the terminal     java -jar bin/felix.jar     From Eclipse Equinox       org.eclipse.osgi_3.2.0.jar     Start OSGi Framework     java -jar org.eclipse.osgi_3.2.0.jar –console     The above implementation jars covered all specification that defined by OSGi so that we can develop OSGi bundles then we can run it on OSGi containers.   OSGi bundle Lifecycle   As for software development mode each software component have its own lifecycle same way OSGi bundle also have its own lifecycle and these lifecycle will be manged by OSGi Framework implementation software or we can say OSGi containers. The following are OSGi bundle lifecycle stages     Install Resolved Uninstall Start Active Stop     Install   Install is start point to OSGi bundle and we need to install OSGi bundle with help OSGi commands then Bundle will be available in OSGi container.   Resolve   In the resolve stage it will check all dependent bundles and its required bundles if everything satisfied then it will moved to other stage otherwise it will be uninstalled.   Uninstall   Uninstall is completely removing OSGi bundle from OSGi container and this we can manually uninstall with command or If the bundle not resolved by all decencies then it’s automatically uninstalled.   Start   After all dependencies and required bundles are resolved then bundle will be started, once bundle is started then it will be available for use.   Active   Once bundle available to use in OSGi container then we will make it active so that it will be under real usage and it we can experience as end user.   Stop   Stop stage we can make OSGi bundle inactive so that it will not available for real use but still Bundle available for OSGi container.       The following are the commands to working with OSGi Bundle lifecycle   Apache Felix   The following are the commands to working with bundle lifecycle and we need to provide bundle path as variable for each command.     felix:install file:/path/to/bundle/bundle.jar   felix:start file:/path/to/bundle/bundle.jar   felix:stop file:/path/to/bundle/bundle.jar   felix:update file:/path/to/bundle/bundle.jar   felix:uninstall file:/path/to/bundle/bundle.jar     To work with shell based commands Apache Felix uses another OSGi bundle called Apache Felix GOGO   Apache Felix GOGO   Apache Felix GOGO is sub project of Apache Felix and it provide command based interface to working with OSGi bundles lifecycle.   http://felix.apache.org/documentation/subprojects/apache-felix-gogo.html     The Gogo subproject of Apache Felix and its consists of three bundles   Runtime   Implements the core command processing functionality.   The following is Bundle implemented Runtime   org.apache.felix.gogo.runtime.jar   Shell    Provides a simple textual user interface to interact with the command processor. The following is Bundle implemented Shell   org.apache.felix.gogo.shell.jar   Command    Implements a set of basic commands.   org.apache.felix.gogo.command.jar   Note:   Apache Felix GoGo is already included in the Apache Felix Framework Software so as soon as we start Felix OSGi jar file then it will be available as console so that we can use above specified commands to manage bundle lifecycle.   Example Gogo Console   Open your terminal in you system start Felix Framework jar file then you can see Apache Felix GoGo console.     $ cd felix-framework-3.0.0 $ java -jar bin/felix.jar _______________ Welcome to Apache Felix Gogo   g! lb START LEVEL 1    ID|State      |Level|Name     0|Active     |    0|System Bundle (3.0.0)     1|Active     |    1|Apache Felix Bundle Repository (1.6.2)     2|Active     |    1|Apache Felix Gogo Command (0.6.0)     3|Active     |    1|Apache Felix Gogo Runtime (0.6.0)     4|Active     |    1|Apache Felix Gogo Shell (0.6.0)     5|Installed  |    1|Example Bundle (1.0.0) g! start 5 Hello from Bundle 5. g!     lb command list the available bundle in OSGi container and to start the bundle we can specify the bundle order number as argument.   Equinox   Similar to Apache Felix equinox also have similar commands and its console to work with bundle lifecycle     install <bundle URL>   Installs the bundle from the given URL   start <bundle # or bundle name>   Starts the bundle with the given numeric or symbolic id   stop <bundle # or bundle name>   Stops the bundle with the given numeric or symbolic id   ss   Reports a summary status of all installed bundles   diag <bundle # or bundle name>    Reports any resolution problems for the bundle with the given numeric or symbolic id     Equinox also implemented OSGi console using following bundle     org.eclipse.equinox.console.jar     Internally Equinox also used Apache Felix gogo to provide command line interface and along with Equinox console.   Example of Equinox Console     osgi> ss "Framework is launched."     id         State       Bundle 0          ACTIVE      org.eclipse.osgi_3.10.0.v20140606-1445 1          ACTIVE      org.apache.felix.gogo.runtime_0.10.0.v201209301036 2          ACTIVE      org.apache.felix.gogo.command_0.10.0.v201209301215 3          ACTIVE      com.meera.sample.HelloWorld_1.0.0.qualifier 4          ACTIVE      org.apache.felix.gogo.shell_0.10.0.v201212101605 5          ACTIVE      org.eclipse.equinox.console_1.1.0.v20140131-1639   osgi> stop 3 Goodbye World!!   osgi> start 3 Hello World!! Osgi     SS will use to list available bundles in OSGi container and we will use Bundle number in to start or stop bundle.   To work with Basic OSGi development using Apache Felix we need following bundles     felix.jar org.apache.felix.gogo.runtime.jar org.apache.felix.gogo.command.jar org.apache.felix.gogo.shell.jar     To work with Basic OSGi development using Equinox we need following bundles     org.eclipse.osgi_3.10.0.jar org.apache.felix.gogo.runtime.jar org.apache.felix.gogo.command.jar org.apache.felix.gogo.shell.jar org.eclipse.equinox.console.jar     If we want work with other environments such as web applications we should have other OSGi bundle to provide execution run time environment.   Example:   To work with web application environment using OSGi we need following OSGi implementation bundles     Apache Felix HTTP Service   http://felix.apache.org/documentation/subprojects/apache-felix-web-console.html     Apache Felix Web Console   http://felix.apache.org/documentation/subprojects/apache-felix-http-service.html     Apache Felix Log   http://felix.apache.org/documentation/subprojects/apache-felix-log.html       Similarly we need different implementation OSGi bundle to provide different types of environments.   In this case we need to setting up required bundles so that we can create execution environment rather than this there is project from Apache called Apache Arise it will provide all types of pluggable OSGi plugins to create different types of execution environment   Apache Aries   The Aries project consists of a set of pluggable Java components enabling an enterprise OSGi application programming model. This includes implementations (and extensions) of the following Enterprise OSGi specifications   http://aries.apache.org/  

 

  Asynchronous Services and Promises Specification Blueprint Specification JTA Transaction Services Specification JMX Management Model Specification JNDI Services Specification JPA Service Specification Service Loader Mediator Specification Subsystem Service Specification  

 

Author Meera Prince Liferay Contributor of The Year 2014 Liferay Top Contributor Award Winner 2013 http://www.liferaysavvy.com Meera Prince 2016-01-08T14:44:55Z
Categories: CMS, ECM

Search-backed and content-driven Megamenus

Liferay - Mon, 12/28/2015 - 13:10

Okay, that is a mouthful. To rephrase my compound title, we'll be talking about an approach that 

  1. uses search to
  2. update a content item that
  3. follows a structure tailored to a
  4. template that renders a megamenu.

There! Thats the flow in a nutshell. If that already has the gears turning in your head, then you're welcome. Ta-ta! But if you need more, read on.

Note that I'm discussing a design here, resorting to low-level implementations only where needed. Undertanding the moving parts in this design/approach is the real value of this post.

What is a megamenu?

You've seen them. Megamenus are everywhere. A megamenu is basically a beautiful and useful kink in your navigation. Most navigation HTML provides a hierarchical menu reflecting your sitemap. But every so often, a business may want to break away from that mundaneness and give the user a rich navigational experience.

For a quick example, visit amazon.com and hover over any item under Shop by Department. Each of those is a megamenu.

Our Simple Course Megamenu

Consider the below megamenu which we will use as a case study for the purposes of this post.

It features 4 tabs. Each tab shows a list of courses arranged alphabetically. Clicking a course takes you to the course content page. All courses are Liferay journal articles of a custom subtype called Course.

The Megamenu Content Structure

More often than not, the information we display in a megamenu has a well-defined structure. For the above example, we can quickly define a content structure for our megamenu that would look something like this:

Tab (Text/Repeats) Course Letter (Text/Repeats) Course Title (Text) Course URL (Text)

Using the above structure, you could manually create all the content necessary for our courses megamenu. Sounds crazy! Right. And we don't want to do anything crazy! So hang in there.

The Megamenu Content Template

Here is the stripped-down megamenu template that uses the structure above to render the megamenu.

<div class="mega-dropdown-nav-container"> <ul class="nav nav-pills nav-justified block-light" role="tablist"> #foreach ($studyLevel in $txtQualificationLevel.getSiblings()) <li role="presentation"> <a data-target="#$studyLevel.txtIdentifier.getData()" aria-controls="# $studyLevel.txtIdentifier.getData()" role="tab" data-toggle="pill"><strong> $studyLevel.getData()</strong></a> </li> #end </ul> </div> <div class="mega-dropdown-tab-container"> <div class="tab-content"> #foreach ($studyLevel in $txtQualificationLevel.getSiblings()) <div role="tabpanel" class="tab-pane $active" id="$studyLevel.txtIdentifier.getData()"> <div class="mega-dropdown-menu-inner"> #foreach ($letter in $studyLevel.txtLetter.getSiblings()) <ul> <li class="dropdown-header">$letter.getData()</li> #foreach ($course in $letter.txtCourseTitle.getSiblings()) <li><a href="/-/$course.txtFriendlyUrl.data">$course.getData()</a></li> #end </ul> #end </div> </div> #end </div> </div>   Theme Navigation Trigger Now, hook up your megamenu content to your theme navigation.   navigation.vm ...

#foreach ($nav_item in $nav_items)
#if ($velocityCount == 3) ### drop the COURSES megamenu item here
#parse ("$full_templates_path/megamenu.vm")
#end
...

  megamenu.vm #set ($journalContentUtil = $utiLocator.findUtil("com.liferay.portlet.journalcontent.util.JournalContentUtil")) #set ($content = $journalContentUtil.getContent( $themeDisplay.getSiteGroupId(), $propsUtil.get("megamenu.article.id"), null, $locale.toString(), $themeDisplay ) )   <li class="navlink-courses dropdown mega-dropdown visible-md visible-lg visible-xl" id="layout_megamenu" $nav_item_attr_selected role="presentation">         <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Courses <i class="icon icon-chevron-down icon-sm"></i></a>         <div class="dropdown-menu mega-dropdown-menu" role="tabpanel">                 $content         </div> </li> <li class="navlink-courses hidden-md hidden-lg hidden-xl"><a href="#">Courses</a></li>   What we have so far
  • A megamenu content structure
  • A megamenu content template
  • A megamenu content item (journal article) tied to that structure and template
What is still worrisome is the craziness involved in manually updating our megamenu content item. This is where the Liferay Search API comes to the rescue. But first, a quick note on the megamenu XSD.   The Megamenu XSD  The Megamenu Content XML If you examine the content in the database of your megamenu journal article, you will find something similar to the below.   <?xml version="1.0"?> <root available-locales="en_US" default-locale="en_US">     <dynamic-element name="txtQualificationLevel" type="text" index-type="keyword" index="0">         <dynamic-element name="txtIdentifier" index="0" type="text" index-type="keyword">             <dynamic-content language-id="en_US"><![CDATA[all-courses]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="0" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="0" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="0" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[advanced-certificate-in-management]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Advanced Certificate in Management]]></dynamic-content>             </dynamic-element>             <dynamic-element name="txtCourseTitle" index="1" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="1" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[advanced-certificate-in-financial-planning]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Advanced Certificate In Financial Planning]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[A]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="1" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="2" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="2" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[bachelor-of-commerce-bcomm-]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Bachelor of Commerce (BCOM)]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[B]]></dynamic-content>         </dynamic-element>         <dynamic-content language-id="en_US"><![CDATA[All Courses]]></dynamic-content>     </dynamic-element>     <dynamic-element name="txtQualificationLevel" type="text" index-type="keyword" index="1">         <dynamic-element name="txtIdentifier" index="1" type="text" index-type="keyword">             <dynamic-content language-id="en_US"><![CDATA[undergraduates]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="2" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="3" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="3" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[advanced-certificate-in-management]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Advanced Certificate in Management]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[A]]></dynamic-content>         </dynamic-element>         <dynamic-content language-id="en_US"><![CDATA[Undergraduates]]></dynamic-content>     </dynamic-element>     <dynamic-element name="txtQualificationLevel" type="text" index-type="keyword" index="2">         <dynamic-element name="txtIdentifier" index="2" type="text" index-type="keyword">             <dynamic-content language-id="en_US"><![CDATA[postgraduates]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="3" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="4" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="4" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[higher-certificate-in-management]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Higher Certificate In Management]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[H]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="4" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="5" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="5" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[master-of-business-administration-mba-]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Master of Business Administration (MBA)]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[M]]></dynamic-content>         </dynamic-element>         <dynamic-content language-id="en_US"><![CDATA[Postgraduates]]></dynamic-content>     </dynamic-element>     <dynamic-element name="txtQualificationLevel" type="text" index-type="keyword" index="3">         <dynamic-element name="txtIdentifier" index="3" type="text" index-type="keyword">             <dynamic-content language-id="en_US"><![CDATA[ce]]></dynamic-content>         </dynamic-element>         <dynamic-element name="txtLetter" index="5" type="text" index-type="keyword">             <dynamic-element name="txtCourseTitle" index="6" type="text" index-type="keyword">                 <dynamic-element name="txtFriendlyUrl" index="6" type="text" index-type="keyword">                     <dynamic-content language-id="en_US"><![CDATA[postgraduate-diploma-in-banking]]></dynamic-content>                 </dynamic-element>                 <dynamic-content language-id="en_US"><![CDATA[Postgraduate Diploma in Banking]]></dynamic-content>             </dynamic-element>             <dynamic-content language-id="en_US"><![CDATA[P]]></dynamic-content>         </dynamic-element>         <dynamic-content language-id="en_US"><![CDATA[Continuing education]]></dynamic-content>     </dynamic-element> </root>   This content may look overwhelming at first, but it is sickeningly simplistic, and hence very flexible. This is all you need to know.
  1. The root element has one or more dynamic-element elements.
  2. Each dynamic-element can have one dynamic-content element and one or more dyamic-element elements.
  3. And recursion. That's it.
  The XML Schema Definition Use any of numerous tools to create an XML Schema Definition for this XML structure. Once you have an XSD, you can then use any XML Schema binding framework (XML Beans, JAXB, etc) to convert between an object model and an XML document that conforms to said schema. This is powerful now.   Putting Search to work There are many ways to do this, but we chose to implement a simple admin portlet with a single button on it. Clicking the button does the following work.
  1. Fire a search to bring back all content of type course
  2. Sort the courses
  3. Partition the courses into four buckets corresponding to the four tabs on the megamenu. We use a custom field called studyLevel for each course that serves as the discriminator for the tabs
  4. Organize the courses into the object model that is convertible to our Megamenu content XML document.
  5. Convert the object model to XML
  6. Retrieve the megamenu content item
  7. Update it with the XML
  8. Done.
So why even do it this way?
  1. The content that populates the megamenu is web content, so updating the megamenu is as simple as updating a content item. Happens on the fly.
  2. We wanted our megamenu to be extremely performant, so we preferred to just load a content item and thus reuse any Liferay caching that already services existing content
  3. We wanted a way to refresh the content on demand. E.g. fire a search and refresh the content item after adding one or more courses.
  4. We wanted to leverage Liferay's cotnent versioning so we can examine the content evolution of our megamenu and use as needed.

Some useful code snippets follow. I hope someone finds this approach helpful.

Useful Code Snippets Faceted Search Configuration {"facets": [     {         "displayStyle": "asset_entries",         "static": true,         "weight": 0.25,         "order": "OrderHitsDesc",         "data": {             "values": ["com.liferay.portlet.journal.model.JournalArticle"],             "frequencyThreshold": 0         },         "className": "com.liferay.portal.kernel.search.facet.AssetEntriesFacet",         "label": "asset-type",         "fieldName": "entryClassName"     },     {         "displayStyle": "asset_tags",         "weight": 0.25,         "static": true,         "order": "OrderHitsDesc",         "data": {             "values": ["course"],             "frequencyThreshold": 0         },         "label": "asset-type",         "className": "com.liferay.portal.kernel.search.facet.MultiValueFacet",         "fieldName": "type"     } ]}   Calling into the Search API String searchConfiguration = portletPreferences.getValue("jsonFacetedSearchConfigurationString", StringPool.BLANK);   import com.liferay.portal.kernel.search.Document import com.liferay.portal.kernel.search.SearchContext import com.liferay.portal.kernel.search.QueryConfig import com.liferay.portal.kernel.search.FacetedSearcher import com.liferay.portal.kernel.search.facet.AssetEntriesFacet import com.liferay.portal.kernel.search.facet.Facet import com.liferay.portal.kernel.search.facet.ScopeFacet import com.liferay.portal.kernel.search.facet.config.FacetConfiguration import com.liferay.portal.kernel.search.facet.config.FacetConfigurationUtil import com.liferay.portal.kernel.search.facet.util.FacetFactoryUtil import com.liferay.portal.kernel.search.Field import com.liferay.portal.kernel.search.Hits import com.liferay.portal.kernel.search.Indexer import com.liferay.portal.kernel.search.IndexerRegistryUtil import com.liferay.portal.kernel.search.QueryConfig import com.liferay.portal.kernel.search.SearchContext import com.liferay.portal.kernel.search.SearchContextFactory import com.liferay.portal.kernel.search.SearchResultUtil   List<Document> documents = null; SearchContext searchContext = SearchContextFactory.getInstance(request); searchContext.setAttribute("paginationType", "none");   QueryConfig queryConfig = new QueryConfig(); searchContext.setQueryConfig(queryConfig);   searchContext.setStart(1); //searchContext.setEnd(); // I am hoping NOT setting this would work as paginationType is set to "none"   Facet assetEntriesFacet = new AssetEntriesFacet(searchContext); assetEntriesFacet.setStatic(true); searchContext.addFacet(assetEntriesFacet); Facet scopeFacet = new ScopeFacet(searchContext); scopeFacet.setStatic(true); searchContext.addFacet(scopeFacet);   List<FacetConfiguration> facetConfigurations = FacetConfigurationUtil.load(undergraduateSearchConfiguration); for (FacetConfiguration facetConfiguration : facetConfigurations) {     Facet facet = FacetFactoryUtil.create(searchContext, facetConfiguration);     searchContext.addFacet(facet); } Indexer indexer = FacetedSearcher.getInstance(); Hits hits = indexer.search(searchContext); documents = hits.toList()   Retrieving & Updating The Megamenu Content Item https://docs.liferay.com/portal/6.2/javadocs/com/liferay/portlet/journal/service/JournalArticleLocalServiceUtil.html#getArticle(long, java.lang.String) https://docs.liferay.com/portal/6.2/javadocs/com/liferay/portlet/journal/service/JournalArticleLocalServiceUtil.html#updateContent(long, java.lang.String, double, java.lang.String) Javeed Chida 2015-12-28T18:10:13Z
Categories: CMS, ECM

From Atomic design to your Liferay project

Liferay - Mon, 12/28/2015 - 12:09

I would like to start saying that this entry is focused on designers and front-ends but I think that it would be useful for all people who wants to know what is the real advantage to applying Atomic design.

Part of this entry is about Liferay themes, so I have to say that for me there are three approaches to turn visual designs in a Liferay theme:

  1. Close to bootstrap system: like a bootstrap extension, for example: Lexicon has been built under this approach.
  2. Freestyle over custom.css: the most common way, “do not look back” your style and your tecniche over Liferay, example: my free themes.
  3. Applying Atomic design principles.

All of them are perfectly valid and I have tried to use all of them but today and in this blog entry I’m going to talk about advantages of Atomic design, from its design principles to how I usually apply it to Liferay front-end/themes.

  I’m going to continue with a simple sentence: “Atomic design is not a new thing”:

Designers have been working on this way for a long time but we have used other names, probably the most common would be “system design". But yes this concept has been getting importance so can be a bridge between designers and technical people, from the abstract to the concrete. Atomic design language is simple, we will speak and work along these five groups:

 

There is a lot of information about Atomic design but here a little resume about how those groups are conceptualized:

  • Atoms: Color palette, Font sizes, Labels, Inputs, Buttons, etc..
  • Molecules: Built by atoms, for example: an advance search block which contains four atoms one label, input type text, input type select and a button.
  • Organism: Based on union of molecules, to create little components with some complexity, like a header based on a logo, a navigation and a search block.
  • Templates: Here it starts a concrete language, as you can imagine we can use Organisms to create all templates as the project needs.
  • Pages: And at last, template content is replaced with real content to give an accurate design of what a user will see.
  Why should front-end people find out advantages on this approach?

These days at much projects front-end people are assuming the responsibility to translate design language to technical language, and yes, that works many times!. But languages are created to communicate and bring people so let language does its work and get some rest for front-end happy people.

As you can see in Atomic design groups image we start in abstract terms (atoms, molecules and organisms) and we finish with so concrete terms like templates or pages. Atomic design language is simple and concise.

  Project reality and Atomic design

It does not matter how many care we spend in our projects, most of the time we will need to change little design things, but how much impact will it have in design, front-end or developing? By using the same language we will be able to change one little thing (an atom) which will change all design in all templates and all pages. I know I know it sounds too good, like a fantasy but it can work with little approach changes:

  Approach changes for Visual Designers and UX Designers:

We need extensible tools, tools which allow us to create reusable symbols. Most common tools to work on this concept are Illustrator or Sketch which allow you to create atoms of type text, color, and groups.

I know that this explanation is very short to transmit so big change so I have created a sketch file which can explain better the concept. The file is only an example and a beginning of how it can work, I didn't want to intrude in how you are working.

Download sketch file:

 

This file has six artboards, the first one is a file's explication, the rest are one artboard for each atomic group, atoms, molecules, organism, templates and pages, there are builded three atoms, two molecules, two organism and one template. To build them I have only needed this symbols and styles:

 

Now, we can change an atom like color to change all molecules, organisms and templates:

The sketch file is totally free and feel free to use it like a base to create more complex projects.

  Where is the improvement for UX guys?

Normally UX designer works before a visual designer and then when visual design is finished they can review the results and make suggestions, the advantage in Atom design starts in atoms because UX guys can start their testing over an atom, for example: if we want to validate buttons touchables sizes (over UX recommendations), we will be able as soon as we have button atom ready!

  Approach changes for Front-ends and Developers:

Now I’m going to share how I have ordered css files in an Atomic design approach, but this is only my way, if you guys find out some better way It would be a pleasure to me to know it.

I have created a git repository with a Liferay theme where applies this approach and architecture, here:

https://github.com/marcoscv-work/atomic-design-theme

 

As you can see inside _diffs directory there is a new directory called “atomic”. custom.css will only load atomic main files inside atomic directory so we can go directly inside atomic directory:

_atomic.scss will load all atoms, molecules, organisms, templates and pages from respectively directories, and _atomic _variables.scss will load all variables which are divided by group:

 

Atomic design is totally independent from frameworks for technology, so you can work as you prefer, this theme is only an example about how to translate the language to files and directories structure.

I’m sure that following this approach we can improve the workflow, getting better the design design, the communication between teams and our front-end organizing.

 

More info about what I’m working on, Liferay themes or Liferay general world on my twitter @marcoscava

Marcos Castro 2015-12-28T17:09:14Z
Categories: CMS, ECM

2015 themes

Liferay - Sun, 12/27/2015 - 16:14

Hey guys, before this year ends I wanted to share with you some impressions and feedback which many of you have given me about the three free themes I have shared this year.

First, I would like to give you thanks for all positive appreciations: 5/5 stars, comments, almost 5.000 downloads, keep them all these months between more viewed in Liferay marketplace or even some collaborations through github to improve them.

But the more impressive thing for me has been that a lot of sites are using them as a finish solution and in differents ways that I never imagined and well, this is the reason why I'm writing this entry:

  Differents ways to use the same theme: Advice: These three themes have site templates which you will see after their installation. Manzanita theme:

Download on marketplace - Github

This theme was conceptualized to create simple brand websites with a simple navigation. It needs a small logo like an icon and has an advance color palette settings and it is totally responsive:

That was the first thought, but you guys are using it to create:

  • Complex websites like insurance portals and intranets, adding a simple left sitemap portlet to create different navigation levels.
  • Blog sites like medium: It uses structures/templates which allow to create blocks with 100% width images or text blocks with limited width.
  • And the most awesome way for me was that some of you guys have used it to create product shop pages reusing content grid to show products and its modal to open the integrations with ecommerce solution.
  Madrid theme:

Download on marketplace - Github

This theme was a tribute to my hometown, and all included pictures and videos are taken by me and are totally free:

I thought on it like a presentation page, in fact the theme includes an auto generated submenu which allow you to navigate between portlets at the same page, but here some examples about how you all are using it:

  • Product sites, type of page with a long vertical scroll, changing the navigation portlet index to show circles in a page side.
  • Photographer sites, with portlet index navigation as separators between types of photography.
  Traveler theme:

Download on marketplace - Github

Theme with pictures of some of my travels and it was conceptualized like a modern travel agency, this theme is very different from what we are used to because it will display all portlets in vertically, and you will be able to navigate along them using big arrows. It also includes a good example of main configurable navigation, you can change the navigation side or the main color palette:

This theme has been used in ways like:

  • Portfolio sites: showing visual designs, pictures or videos.
  • Tours sites: A little instruction with illustrations.
  • Presentations like powerpoint or keynote: I have used this way
  • And the most impressive for me, an eLearning site!: each page is a chapter which has a portlet with topics and you can move free between all topics, the last portlet contains the chapter exam.

 

At the moment this is all, if you are using some of these themes in other different and creative way please let me know to extend this list and to bring us more possibilities.

More info about what I’m working on, Liferay themes or Liferay general world on my twitter @marcoscava

Marcos Castro 2015-12-27T21:14:08Z
Categories: CMS, ECM
Syndicate content