AdoptOS

Assistance with Open Source adoption

ECM

Create an upgrade process in 6.2

Liferay - Thu, 05/16/2013 - 18:27
Introduction

Recently I've been working in some new features regarding to internacionalization the name and description of DLFileEntryType entity. I create all the logic and everithing was fine. Everthing went smoothly.

Due I was changing a DB table I had to create an upgrade process  and the things became a litle bit hard (it's my very fist time creating an upgrade)... Why? Because I found  an absolute lack of  updated documentation about this kind of process.

It's true that I found a few wikis but it was a little messy (It was very funny to see five core engineers in the LA office triying to decode the [obsolete] documentation, true story...) So I've decided to create my fist blog entry regarding this.

But first of all... What is an upgrade process??

What we try to do in a upgrade process is guarantee that Liferay can upgrade from any previous version to any newer version.

We can see this in the following example. 

I'm going to explain (based in the  develop I made) the whole process, explaining how did I upgrade the  DLFileEntryType entity by adding a new column called fileEntryTypeKey and changing the name and the description columns introducing localization properties.

Step 1 - Modify an entity

The first thing to do is to perfome all the required changes in the entity. It will give you the basis for the rest of the process. Not very much to explain, edit the service.xml ...

...Then run...

... and modifiy the Impl classes you need. Nothing special

Step 2 - Change .ftl if needed

If the entity has some default objects (i.e. DLFileentryType has 5 default types) maybe you'll need to change its .ftl file :

Step 3 - Create some UpgradeProcess classes

Go to the proper version UpgradeProcess[XXX].java file (for us it's UpgradeProcess_6_2_0.java) and search for the right Upgrade[XXX].java (in this case is UpgradeDocumentLibrary). In this class (wich extends UpgradeProcess) you must introduce and override the doUpgrade() method like this:

As you can see we are directly using pure sql to perform the database upgrade. This clauses are surrounded by a try…catch that calls the method upgradeTable(few params) if something goes wrong...

Let's see that method deeply:

In there we are creating an UpgradeTable.java instance and we pass some values regarding the table we are modifiying. We get this values from an autogenerated class called XXXTable.java (DLFileEntryTypeTable.java for us).

Step 4 - Create the [XXX]Table class

Create this class is as simple as make its skeleton, modify portlet-model-hints.xml to define the configuraiton of the columns...

...and then run...

This is the generated class:

Step 5 - Create some logic to format and persist the current data

The last method that we can see in doUpgrade() is:

Here we are getting the previous values and we pass them to...

...where we will reuse them in the modified table.

Step 6 - Regenerate all the service and TEST!

This is the final step. All you got to do:

VERY IMPORTANT!!

Run

Doing this you could be sure you are not breaking the default data.

And that's all!!!

Roberto Díaz 2013-05-16T23:27:17Z
Categories: CMS, ECM

Sales and Marketing Friction Points [Infographic]

KnowledgTree - Tue, 05/14/2013 - 20:06
A Look At Possible Software-as-a-Service Solutions

Sales and marketing have to work together effectively. Your revenue depends on it. But as we’ve seen from our recent survey of sales and marketing professionals, at many companies there’s a lot of friction between the two teams. In fact, one data point showed that 50% of sales teams are not satisfied with their Marketing relationship.

So, what’s the source of the challenge? A few weeks back Daniel Chalef looked at the common friction points that exist between the two teams. The article summarized five key marketing automation and sales enablement technologies that help. Here’s a handy infographic to visualize how to solve the friction points.

Categories: ECM

Managing Liferay through the Gogo shell

Liferay - Tue, 05/14/2013 - 16:46

I have done a huge refactor for most of our OSGi related work, moving the majority of its components to the Liferay plugins SDK. Everything except the graphical admin UI is already in the master branch of the official repo so you can play with it; we would love to hear your feedback.

My goal with this post is to show you how create a new OSGi bundle in the plugins SDK using a practical example: extending the OSGi shell (we have spoken about it sometime ago). Let's try to do it:

Basic project structure

Currently there is no target in the SDK which allows you to create a bundle (I will push it soon) so you can use this example (or the other modules as http-service-shared or log-bridge-shared) as the basic skeleton for your tests:

As you can see, the structure is very simple; let my try to highlight the main OSGi related points:

  • All the new OSGi plugins will be based in the great bnd tool . You can configure all your bundle requirement through the bnd.bnd file
  • The build.xml of the plugin must import the build-common-osgi-plugin.xml build file: <import file="../../build-common-osgi-plugin.xml" /> 

As I have told you before I will include an Ant target to create this basic skeletons, but, until then, you need to do this by hand. Sorry about that :(.

Writing Gogo shell custom commands

As we have stated at the beginning of the post, we are going to write a bunch of custom commands for the Gogo shell. As you will see, this is an extremely easy task.

This commands can be created using a simple OSGi service with a couple of custom properties. We will use the OSGi declarative services approach in order to register our commands (Liferay already includes an implementation of the Declarative Services specification in the final bundle, so you don't need to deploy it by yourself).

At this point, we are ready to write our first command: the ListUsersCommand: 

The @Component annotation let us to define a new OSGi service in an extremely easy way. The Gogo commands are registered in the console using the properties osgi.command.function and the osgi.command.scope. The first one establishes the name of the namespace where the command will be allocated (in order to prevent name collisions) while the latter specifies the name of the command. It is important to note that the Declarative Service annotations I am using does not support inheritance, so everything you declare in a base class will not be inherited down in the hierarchy.

And, how do I write the implementation of my new command? You just need to write a new public method named as the value written in the osgi.command.function. If your command needs some argument you will need to specify as a parameter of your method (an the console will do the coercion of the basic types). In our example we are creating a usermanagment namespace, with a command called listByCompany which expects the companyId (long) as the unique parameter.

Easy, isn't it?

Consuming Liferay services

I would like to highlight the implementation of the listByCompany command (I am sure you have already guessed the previous command retrieves all the users of a certain company).

In order to get all this info we need to call the corresponding method in the users service. We could do something like UserLocalServiceUtil.getCompanyUsers(companyId) but this is not a good approach, so we are to going to get all the benefits of having all the Liferay services as OSGi services. We just need to grab a reference to the UserLocalService bean:

@Reference public void setUserLocalService(UserLocalService userLocaService) {    _userLocalService = userLocaService; }   protected UserLocalService _userLocalService;   Building and running the bundle Once we have written our command we need to build our final artifact: just type ant jar in the project folder and you will get the final jar file into the dist folder. Before deploying our new bundle let's connect to the Gogo shell in order to check which bundles we have already installed:     As you see, we have already a bunch of bundles running but nothing about the new commands we are writing. What commands are currently available in the console? Just type help in the console     Now we have to deploy our new bundle. To do that, we just need to copy it to the folder $liferay.home/data/osgi/deploy (it is the default folder, you can change it in the properties). You can use the deploy Ant task our just copy the folder into the previous folder. Once the bundle is deployed we should see it in the bundles list:     Take a look to the last line; you will see our bundle has been deployed and it is, hopefully, running. Let's see which commands we do have available once our new bundle is already installed.     Do you see the last two lines? These are the commands we have written (in this post we only have described one command, you can find the other one in the companion source code). So, if I type listByCompany ID_OF_A_COMPANY (mine is 10153) (since there is no collision I don't need to prefix the command with the namespace) you should get an output similar to this:   Users of the company 10153     User default@liferay.comwith id 10157     User test@liferay.comwith id 10195   Along this post we have seen how we can extend the Gogo shell creating new commands, consuming Liferay services and building a basic OSGi bundle in the plugins SDK. It is not a big deal but I think it is a good starting point to get used to the new OSGi abilities. Hopefully I will be able to push some more complex examples in the near future.   You can find the whole source code in the shared/gogo-commands-shared folder at my plugins repo. Miguel Pastor Olivar 2013-05-14T21:46:33Z
Categories: CMS, ECM

Mavenize Liferay Plugins SDK - Using Maven

Liferay - Mon, 05/13/2013 - 23:27

 

Overview

When working with Liferay projects using Liferay IDE and Plugins SDK it becomes highly difficult to manage dependencies, as Liferay IDE or Plugins SDK by default uses Ant for building and deploying, though Liferay does support Maven based Plugins but as a seasoned Liferay Developer we will be inclined to use Ant preferred to Maven.
The problem rather I call it a difficulty arises when,

  • The number of dependencies for our Portlet project increases and we need to maintain a version based configuration
  • We need to use or integrate our Portlet application with an existing Maven based application from an Organizational build repository

In this article we will look at how we can use Maven dependency management in Plugins SDK by still using the default Ant based Liferay SDK build, you can use any of your existing Liferay Plugins SDK project which has external dependencies.

Technical Platform

I have tested this application on the following technical platform, this works irrespective of Operating System.

Software Version Download Link Liferay CE Portal Server (Tomcat) 6.0.x http://sourceforge.net/projects/lportal/files/Liferay%20Portal/6.0.6/liferay-portal-tomcat-6.0.6-20110225.zip/download Liferay CE Plugins SDK 6.0.x http://sourceforge.net/projects/lportal/files/Liferay%20Portal/6.0.6/liferay-plugins-sdk-6.0.6-20110225.zip/download Apache Ant 1.7.x or above, preferred 1.8.x http://ant.apache.org/bindownload.cgi Apache Maven 2.2.1 or above, preferred 3.0.3 http://maven.apache.org/download.html Apache Maven Ant Tasks 2.2.1 or above http://maven.apache.org/ant-tasks/download.html The Server distribution is not required for the subject of the article it’s preferred to have as the Liferay Plugins SDK might/will use some dependencies from the server distribution   Setup and Installation

Assuming that you have downloaded and installed the above mentioned softwares, for the sake of convenience we will use the following variable names for respective installation DIR’s,

  • $LIFERAY_HOME - the home directory where Liferay server is installed e.g. C:\lportal-6.0.6
  • $LIFERAY_SDK_HOME - the home directory where Liferay server is installed e.g. C:\liferay-plugins-sdk-6.0.6
  • $ANT_HOME - the home directory where ANT is installed e.g. C:\apache-ant-1.8.2
  • $M3_HOME - the home directory where Maven 2.2.x is installed e.g. C:\apache-maven-3.03

Now copy the maven-ant-tasks-2.1.3.jar to $ANT_HOME/lib

Implementation

Let’s use the Liferay IDE to create a new Portlet plug-in look at Using Liferay Maven SDK or you can import the attached Liferay Google Maps demo project in to your workspace,
Open the build.xml of the project that has been created, by default the project build template looks like

 

Now to Mavenize the default ANT build.xml we do the following,

  1. Add the xmlns:artifact=” antlib:org.apache.maven.artifact.ant” to the element of the orginal build.xml
  2. Create a new ant target called “copy-dependencies”, this step is crucial, you can have any name for the target but then what the target does is important. This target will download (only time only) and copy the dependencies to docroot/WEB-INF/lib folder
  3. Add an ant call to “deploy” target within the “copy-dependencies”, this will enable the build.xml to follow the default Portlet application building and deploying post copying the dependencies
  4. Make the copy dependencies as the default target for the project

A example of build.xml with above configurations is available here

 

Observe the artifact:dependencies task portions those are important pieces of mavenizing our ant build. We add the dependencies to the project the same way we add them in Maven pom.xml with little bit of variation to the syntax.

After this once you execute the build in Portlets plug-in directory, it will first download the dependency jars if it does not exist in to the local Maven repository and they will added to the docroot/WEB-INF/lib directory when copy-dependencies target is called, which also includes call to the Liferay default deploy target

Voila! Now we are able to use the Maven dependency management with Liferay Plugins SDK default Ant build system. I hope this article has helped you, for further reading you can check the following links,

Kamesh Sampath 2013-05-14T04:27:21Z
Categories: CMS, ECM

HOW-TO Clear Liferay Cache

Liferay - Mon, 05/13/2013 - 23:26

 

I was learning on how to implement the  export and import functionality on Liferay, initially I thought it to be rather a tedious job but thanks to Liferay API/Framework which made my job easier with Liferay Portlet Data Handlers thanks to Jorge Ferrer who gave me an insight to the API/Framework and how to use the same. All I was required to do is just create a class that extends from BasePortletDataHandler and have it configured via the liferay-portlet.xml

But this activity lead to an interesting learning, initially when I implemented this I saw that data was getting exported/imported without any errors but then I see that its not refreshing the UI immediately after the import. This kind of annoyed me for long time .. thanks to Raymond Auge for is timely insight that we need to clear the cache for the same to be refreshed.. so started my next task on hunting the class which can do the job..

The initial analysis started with me doing the manual task of clearing the caches via the Portal Control Panel using the Server Administration --> Resources (tab) --> Actions panel where we have the action buttons that will clear the cache held by Database, Virtual Machine both local and clustered...  when i did this sequence of actions after my Import, i see the data getting refreshed instantly..  so whats next ? finding out the class that did these jobs, when back tracing from the Server Admin page i landed up in the class EditServerAction, there I got the following three sweet little methods that can do the job for me,

  • CacheRegistryUtil.clear()  -  to clear all the Database caches
  • MultiVMPoolUtil.clear()    - clearing cache across JVM clusters
  • WebCachePoolUtil.clear() - clearing cache in Single VM

All left with me post this findings is that i need to call the required or all methods post my successful import of the data to clear the required caches...

Kamesh Sampath 2013-05-14T04:26:13Z
Categories: CMS, ECM

Using liferay-ui:search-toggle - with Basic or Advanced Search only

Liferay - Mon, 05/13/2013 - 23:12

 I was using <liferay-ui:search-toggle> tag, and my requirement was to to show only advanced search and no basic search. but by default <liferay-ui:search-toggle> will show basic search unless and until user clicks the advanced search atleast once. I tried all possible ways and finally found the solution, this what i did to make my <liferay-ui:search-toggle>show only "Advanced Search" without "Basic" search toggle link.So what we need to do is,

  1. We need to override the isAdvancedSearch method of the XDisplayTerms class to always return true, where "X" your class prefix e.g.ArticleDisplayTerms which extends form com.liferay.portal.kernel.dao.search.DisplayTerms
  2. Update your *_search.jsp which has the <liferay-ui:search-toggle> with the following piece of code
    <style type="text/css">                .toggle-link {display: none;} </style>

This style overriding will prevent the "<<Basic" search link form being displayed, the next piece of  code snippet will make the "Advanced" search displayed by default, we are a kind of triggering the Search link click
....
String key = "<replace with the id of your <liferay-ui:search-toggle> tag";
SessionClicks.put(request, key,"advanced");
.....

The key piece of code which does sends signal to the underlying liferay code to show only "advanced" is SessionClicks.put(request, key,"advanced");

The same could be achieved when we want to display only basic search and no advanced search just by changing the "advanced" --> "basic"

That is it, once we have done with this our <liferay-ui:search-toggle> will always display only "Advanced"  or  "Basic" search

Kamesh Sampath 2013-05-14T04:12:43Z
Categories: CMS, ECM

Liferay Portal 6.1-CE on JBoss AS71

Liferay - Mon, 05/13/2013 - 23:09

 

After setting up Liferay Portal 6.1-CE on  JBoss AS7 based in this post,  i thought it was a piece of cake to deploy Liferay Portal 6.1-CE on JBoss AS7.1(Thunder) but not until i found that we need to do few more updates rather changes to Liferay 6.1-JBoss CE bundle.

Here is the list of what we need to do,

$JBOSS_70_HOME - refers to the Liferay 6.1-CE JBoss AS 7.0.2 directory or any JBoss AS 7.0.2 directory where you have deployed Liferay Portal

  1. Liferay Modules -- Check the $JBOSS_70_HOME/modules/com/liferay/portal/main/module.xml you will see urn:jboss:module:1.0,the we need to update to urn:jboss:module:1.1, once one we can copy it to the $JBOSS71_HOME/modules directory
  2. You need to repeat this for any additonal modules that you might have deployed to the JBOSSAS_70 JBoss Portal bundle
  3. Deployment Structure (optional) -- Based on this AS71 post, I understood that JBoss AS71 does not export the system module, but if we check  $JBOSS71_HOME/standalone/deployments/ROOT.war/WEB-INF/jboss-deployment-structure.xml you will see an dependency as follows,
                      <module name="system" export="false">                                <imports>                                     <include path="com/sun/jmx"/>                                     <exclude path="/**" />                               </imports>                        </module>            Just remove or comment that entry   And that's it once we do that and try redeploying the ROOT.war (rename the ROOT.war.failed --> ROOT.war.dodeploy) will trigger the deployment. Kamesh Sampath 2013-05-14T04:09:22Z
Categories: CMS, ECM

How-To implement Pagination in Liferay

Liferay - Mon, 05/13/2013 - 23:00

 

Liferay provides  a rich set of tag libraries that can help in implementing certain complex functionalities like search container, pagination etc.,  with few lines of code. In this blog let’s see how we can implement the same.   For the demo purposed I used the following technical platform,
  •   Liferay Portal v6.1.CE (beta)
  •  Liferay Portal SDK v6.1.CE
  •  Apache Ant  1.8.2
  •  RHEL 6.1 (Windows could also be used)
  •  Eclipse IDE 3.7.1 with Liferay IDE
Use case This demo uses a very simple use case of displaying 200 list items of type ListItemModel, the ListItemModel is the model class as shown below,   ListItemModel.java     This model class holds the item its id, name and description.  The application will build a Portlet that will display the Model List items with pagination as shown below,   PaginationDemoPortlet       The user should be able to paginate across 200 records with 10 records on each page with PreviousNextFirst and Last options. Implementation To achieve the use case the application uses a small DAO utility class called Pagination Utility, this class will help in Querying for the records from the back end (here its mock objects), the PaginationUtlity class has only one method called getListItems(int  n) that will return ‘n’ list items. The PaginationUtility class is shown below,   PaginationUtility.java     The following steps shows how to implement the Pagination using liferay-ui [1] tag, typically the code of the view page.  
  1. The first and fore most step is to define the pagination container, the liferay-ui 1tag provides a the search-container1 tag which could be used to initialize the container
<liferay-ui:search-container emptyResultsMessage="there-are-no-items" delta="10"> Parameter Description emptyResultsMessage Used to display the message to the user when no records are found, a resource bundle key could be specified for internationalization   delta the default number of items that needs to be displayed on the page  
  1. The next step is to manipulate  the result and set the same in pageContext of the JSP page, this is done using the liferay-ui’s search-container-results1,  when manipulating the result we need to set the following pageContext variables to enable the Liferay-ui tag to process and display them,
a.       results – the variable that will hold the subList of the entire result set with its start determined by searchContainer.getStart() and end determined by searchContainer.getEnd(), where searchContainer is an implicit variable available to the page context after Step #1 b.      total – The total result set size , in our case 200 <liferay-ui:search-container-results>                                 <%                                                 List<ListItemModel> tempResults = PaginationUtil                                                                                                                 .getListItems(200);                                                                                 results = ListUtil.subList(tempResults,                                                                                                                 searchContainer.getStart(),                                                                                                                 searchContainer.getEnd());                                                                                 total = tempResults.size();                                                                                 pageContext.setAttribute("results", results);                                                                                 pageContext.setAttribute("total", total);                                 %> </liferay-ui:search-container-results>  
  1. The third step of the implementation is to define the result row which is done using the liferay-ui’s search-container-row  tag, this tag takes the following parameters,
  Parameter Description className The model class that is contained in the result set returned by the PaginationUtil   keyProperty The primary key or unique key property that will be used or passed to various actions modelVar The temporary variable where the current resultset object will be stored, typically an instance of className   <liferay-ui:search-container-row                                 className="com.accenture.icos.demo.portlets.ListItemModel"                                 keyProperty="id" modelVar="listItemModel">  
  1.  The fourth step of the implementation is to define the columns that will be displayed in the resulting table, this is done using the liferay-ui’s search-container-column-text[1]  this tag takes the following two properties,
Parameter Description name The HTML name attribute for the table column   property The model property form which the value of the column needs to be set   <liferay-ui:search-container-column-text name="id" property="id" />  
  1. The last and final step of the implementation is to define the paginator element of the results which will help in navigating across pages typically First, Next, Previous, Last etc.,  this is done using the liferay-ui’s  search-container-row[1]
</liferay-ui:search-container-row>   [1] The tag libraries used above also take certain other parameters, which can be used on need basis for further details please consult the Liferay TLD documentation   Kamesh Sampath 2013-05-14T04:00:33Z
Categories: CMS, ECM

Using Liferay Portal 6.1 Published in Print

Liferay - Mon, 05/13/2013 - 15:42

I am pleased to announce the immediate availability of the print edition of Using Liferay Portal 6.1! For those of you on your toes (and you know who you are), it's actually been available since Friday, but who reads a blog entry that is published on Friday afternoon?

It's a big book. We're getting close to 700 pages now in print, and that does not include the properties reference, which we think is better as an online reference than stuffed into the book (plus, we can lower the price if we excise those pages). I want to acknowledge the hard work of Liferay's Knowledge Management team for a job well done: Jim Hinkey, Stephen Kostas, Jesse Rao, and Cody Hoag. In addition to these guys, some other key contributors include James Falkner, Bruno Farache, Michael Han, Jeffrey Handa, Mark Healy, and Jonathon Omahen.

So if you like big, thick books on your shelf, especially ones with the Liferay logo on them, why not pick one up?

Of course, we're not stopping there. I'm in the midst of working on the styling of the epub version of the book, which we'll release next. Stay tuned!

Richard Sezov 2013-05-13T20:42:55Z
Categories: CMS, ECM

RE:5 tips to improve usage of the Liferay script console

Liferay - Mon, 05/13/2013 - 13:26

// In reply to 5 tips to improve usage of the Liferay script console - by Sébastien Le Marchand

Sébastien wrote a very good article about Liferay script console. Here is one more tip in response of the call for sharing at the end of the article. I post it as a sepreate blog entry because I cannot use Gist or format in comment area....

  Tip #6: Schedule your script to run as a CRON job If you want to schedule your script to execute at certain times as a CRON job (One scenario can be: Run the task "deactivate users never logged and created since more than 2 years" every month.), you can use Liferay's Scheduler Engine API, like in the following example: The following code outputs the string "test" to a file one time per minute in the next 10 minutes:   You can change your job schedule by changing the parameters in CronText constructor.   You will also need to use proper escape characters in the script.   Note that when Liferay Scheduler Engine execute the script, the following predefined variables are not available:
  • out (java.io.PrintWriter)
  • actionRequest (javax.portlet.ActionRequest)
  • actionResponse (javax.portlet.ActionResponse)
  • portletConfig (javax.portlet.PortletConfig)
  • portletContext (javax.portlet.PortletContext)
  • preferences (javax.portlet.PortletPreferences)
  • userInfo (java.util.Map<String, String>)

 

Kan Zhang 2013-05-13T18:26:01Z
Categories: CMS, ECM

Closing the Loop with KnowledgeTree for Salesforce and KnowledgeTree for Mobile

KnowledgTree - Sun, 05/12/2013 - 22:20
A Closer Look At Our Latest Sales Enablement Solutions

Last month we released KnowledgeTree for Salesforce, the first release of many geared toward empowering enterprise sales organizations to curate and surface just the right content at just the right time. This month, we're excited to share with you some improvements we've made to KnowledgeTree for Salesforce and introduce our brand new KnowledgeTree for Mobile application for iOS. Both help close the loop between marketing teams curating content for the field, and sales teams taking advantage of content in the field. Let's find out how.

KnowledgeTree for Salesforce

Publishing content for use in the field should never be a fire-and-forget process. The best content portfolio is pruned and refreshed as needed. But, how can you determine what content needs pruning and why? Your sales team, the ones using the content, can be a great source of feedback about what's working and what isn't.

Imagine a sales rep working diligently in Salesforce. He's got a good opportunity, International Mining, on the hook. Because KnowledgeTree for Salesforce is installed he has instant access to collateral that his marketing team has curated for opportunities such as this.

read more

Categories: ECM

5 astuces pour améliorer l’usage de la console de script de Liferay

Liferay - Sun, 05/12/2013 - 20:30

// The english version of this article can be found here: 5 tips to improve usage of the Liferay script console.

// Si vous utilisez un lecteur RSS pour lire ce billet, veuillez basculer vers la page HTML pour voir correctement les morceaux de code.

Depuis la version 6.0,  Liferay propose une console de script intégrée dans le Control Panel. Très puissant, cet outil devient vite indispensable dès que l’on y a goûté (si vous ne connaissez pas encore la console de script, jetez un oeil sur l’article d’introduction de Jeffrey Handa).

Dans la suite de ce billet, je vais vous présenter 5 astuces simples pour encore mieux profiter de la console de script.

Les exemples de mise en oeuvre qui suivent sont basés sur le langage Groovy, mais la plupart de ces astuces sont applicables avec les autres langages supportés par la console de script du portail.     Astuce n°1 : Mettez du HTML dans vos sorties  Il faut savoir que la sortie par défaut de la console de script est rendue directement en tant que contenu HTML. Pensez-donc à intégrer des balises HTML dans vos sorties pour bénéficier d’une mise en forme riche.   Exemple de script :    Résultat :     Astuce n°2 : Affichez les exceptions dans l’interface utilisateur  Lorsque une exception survient lors de l'exécution d’un script,  le message d’erreur est toujours le même quelque soit l’exception et ne donne aucun détail, ce qui oblige à consulter les logs du serveur pour effectuer un diagnostique.     Pour obtenir le détail de l’exception directement dans l’interface utilisateur, encadrez l’ensemble de votre traitement par un bloc try/catch et affichez la stack trace de l’exception sur la sortie de la console (depuis la clause catch)..   Example de script :   Résultat :    A noter que cela ne fonctionne pas pour les erreurs liées à la syntaxe du script.     Astuce n°3 : Exploitez les variables prédéfinies  Un script exécuté depuis la console du control panel dispose des variables prédéfinies suivantes :
  • out (java.io.PrintWriter)
  • actionRequest (javax.portlet.ActionRequest)
  • actionResponse (javax.portlet.ActionResponse)
  • portletConfig (javax.portlet.PortletConfig)
  • portletContext (javax.portlet.PortletContext)
  • preferences (javax.portlet.PortletPreferences)
  • userInfo (java.util.Map<String, String>)
Lorsque vous écrivez vos scripts, soyez conscient des possibilités offertes par ces variables, tout particulièrement la variable actionRequest, utile pour beaucoup d’appel de méthodes.   Exemple de script :   Résultat : .     Astuce n°4 : Implémentez un mode preview La console de script ne permettant pas de faire de rollback sur l’exécution d’un script, il est très pratique d’intégrer un mode preview pour les scripts qui modifient les données en base.   Ce mode "preview" consiste à utiliser un flag qui détermine si les les opérations à effets de bord sont exécutées ou non, alors que les données parcourues sont systématiquement tracées. Ceci permet donc de se faire une idée des données impactées par un script avant de faire effectivement les mises à jour en base de données.   Exemple de script :   

 

Astuce n°5 : Prévoyez une sortie fichier pour les scripts "longue durée" Lorsque l’exécution d’un script dépasse une certaine durée, la console ne répond plus et retourne une erreur, alors même que le script peut continuer son exécution et potentiellement mener à bien l’ensemble de son traitement... Mais impossible de connaître le statut du traitement sans la sortie correspondante !   Pour remédier à cela, il suffit de prévoir une sortie fichier en plus de la sortie console, comme sur l’exemple ci-dessous : Une fois le script initial exécuté, il est possible de lire le fichier généré sans pour autant avoir d’accès direct au système de fichier, en utilisant un second script : A noter que cette technique basée sur un fichier de sortie dédié est préférable à l’utilisation d’un logger classique car elle facilite la récupération des données de sortie du script (qui seraient plus difficile à isoler parmi l’ensemble des logs du portail).    Et vous, avez-vous des astuces à propos de la console de script à partager avec la communauté ? Faites en part dans les commentaires de ce billet !   Lectures complémentaires Sébastien Le Marchand 2013-05-13T01:30:15Z
Categories: CMS, ECM

5 tips to improve usage of the Liferay script console

Liferay - Sat, 05/11/2013 - 18:35

// La version française de cet article est là : 5 astuces pour améliorer l’usage de la console de script de Liferay.

// If you use a RSS reader to read this post, please switch to the HTML page to correctly view the code snippets.

Since the release 6.0, Liferay provide a script console integrated into the Control Panel. Very powerful, this tool becomes fast essential for any portal administrator or developer (if you do not still know the script console, have a look on this article by Jeffrey Handa).

During this post, I am going to present you 5 simple tips to take better advantage of the script console.

The following implementation samples are based on the Groovy language, but most of them are applicable with other languages supported by the portal script console.     Tip #1: Use the HTML in your outputs You need to know that the script console default output is rendered as HTML content. Thus, think to embed HTML markup in your outputs to enjoy rich formatting.   Script example:    Output:     Tip #2: Show up exceptions on user interface When any exception arises during script execution, the error message is always the same and give no detail about the error. So, you need to access server logs to make a diagnostic.     To show up exception details on the user interface, envelop your whole code with a try/catch block and print the stack trace on the console output (from the catch clause). There is nevertheless a limitation: it doesn’t work for script syntax errors.   Script example: Output:      Tip #3: Exploit the predefined variables  A script executed from the Control Panel can access the following predefined variables :
  • out (java.io.PrintWriter)
  • actionRequest (javax.portlet.ActionRequest)
  • actionResponse (javax.portlet.ActionResponse)
  • portletConfig (javax.portlet.PortletConfig)
  • portletContext (javax.portlet.PortletContext)
  • preferences (javax.portlet.PortletPreferences)
  • userInfo (java.util.Map<String, String>)
When you write your scripts, be aware of possibilities offered by these variables, particularly the actionRequest variable, useful for a lot of method calls.   Script example: Output:     Tip #4: Implement a preview mode The script console not allowing execution rollback, it’s very convenient to set up a preview mode for side-effect scripts (i.e. performing database updates).   Ce mode "preview" consiste à utiliser un flag qui détermine si les les opérations à effets de bord sont exécutées ou non, alors que les données parcourues sont systématiquement tracées. Ceci permet donc de se faire une idée des données impactées par un script avant de faire effectivement les mise à jour en base de données.   This "preview mode" consists in using a flag which determines if the operations with side effects are executed or not, while the visited data are systematically printed. This thus allows to have an outline of the data impacted by the script, before effectively doing updates to database.   Script example :   

 

Tip #5: Plan a file output for "long-running" scripts When the execution of a script exceeds a certain duration, the console doesn’t respond any more and returns an error, whereas the script can continue its execution and potentially bring to a successful conclusion... But impossible to know the status without the corresponding output!   To by-pass this limitation, you can set up a file output besides the console output, like in the following example:  Once the initial script was executed, it is possible to read the generated  file without direct access to the file system, by using a second script: Note that method based on a dedicated output file is better than using a classic logger because it’s easier to get back the script output data (which would be more difficult to isolate among all  portal logs).   And you, do you have some tips about script console that you can share with the community ? Let us know in the comments !   Further reading: Sébastien Le Marchand 2013-05-11T23:35:42Z
Categories: CMS, ECM

Using custom java classes in a JSP hook

Liferay - Fri, 05/10/2013 - 15:15
pre { white-space: pre; } Issue

In Liferay hook development, one common question is:

How to import/use/access custom java classes in a JSP hook?

The question can be described as:

1. Create a hook project (for example: sample-hook)

2. Create a custom class (for example: com.kzhang.CustomJavaClass) in hook project.

3. Override a Liferay portlet jsp (for example, html/portlet/blogs/view.jsp) and try to use the CustomJavaClass in the jsp. Liferay will throw "class CustomJavaClass can't be resolved to a type" exception or ClassNotFound exception.

 

Cause

The jsps in hook plugin is deployed to ROOT servlet context. for example, the html/portlet/blogs/view.jsp in hook plugin will be copied to ${container.deploy.folder}/ROOT/html/portlet/blogs/view.jsp, and the origional view.jsp will be renamed as view.portal.jsp.

The custom classes are still remains in the hook servlet context. for example, the com.kzhang.CustomJavaClass in hook plugin will be still in ${container.deploy.folder}/sample-hook/WEB-INF/classes/com/kzhang/CustomJavaClass.class.

In html/portlet/blogs/view.jsp it can not find CustomJavaClass because each servlet context can only see it's own classes and those of the parent classloaders. In our case, the html/portlet/blogs/view.jsp is in ROOT servlet context which can not see the CustomJavaClass in sample-hook servlet context

 

Solution

There are some discussions in Liferay forum:
http://www.liferay.com/community/forums/-/message_boards/message/7454307
http://www.liferay.com/community/forums/-/message_boards/message/13467179
http://www.liferay.com/community/forums/-/message_boards/message/21397246
http://www.liferay.com/community/forums/-/message_boards/message/11508053

The most common solution is to use the ext plugin instead of hook plugin.

But can we avoid using the ext plugin and leave everything as a hook?

Solution 1: Use Spring + PortletBeanLocatorUtil + JAVA reflection

Step 1. Create the custom-spring.xml in /sample-hook/docroot/WEB-INF/src/context/custom-spring.xml folder.

Step 2. In custom-spring.xml, define the bean for your custom java class:

Step 3. In web.xml, add the context-param to load the custom-spring.xml:

Step 4. In custom_jsps/html/portlet/blogs/view.jsp, use PortletBeanLocatorUtil to load the custom java class:

If your CustomJavaClass implements an interface which is accessable in ROOT servlet context, then you can cast the customJavaClass to the interface and use the class thru interface. Otherwise you will need to use JAVA reflection to dynamically invoke the methods in the custom class.

Solution 2: Override Struts Action and call the custom classes in Struts Action.

Setp 1. In liferay-hook.xml, override the view action of blogs portlet:

Step 2. Create the CustomStrutsAction, invoke the custom class in CustomStrutsAction and set the result in to renderRequest attribute:

( Instead of result, you can also set the custom class in the renderRequest attribute and invoke it in jsp either by using it's Interface or use java reflection)

Step 3. In custom_jsps/html/portlet/blogs/view.jsp, get the result from the renderRequest attribute:

Kan Zhang 2013-05-10T20:15:39Z
Categories: CMS, ECM

SharePoint Users at a Crossroads

Alfresco - Thu, 05/09/2013 - 08:50

SharePoint users are at a crossroads. They have put a massive amount of content into SharePoint that isn’t always easily retrieved. They have invested time, resources and money trying to configure SharePoint to solve their content management problems.  Users are found questioning if SharePoint is efficiently managing their business-critical content processes.

AIIM has realized the challenges that SharePoint users are facing and recently addressed them at the seminar in Toronto, “SharePoint at a Crossroads.”

Attendees at the event were from a broad range of organizations with varying successes, difficulties and questions about SharePoint. Some are looking for more value from their ECM, including mobile and secure cloud solutions. Some have just deployed SharePoint and are experiencing success in their first stages of implementation. Many attendees were looking for SharePoint partners to solve their problems related to scalability, accessibility to content and flexibility of the platform to create unique business solutions.

Alfresco participated in the event as the only ECM alternative to SharePoint. Many participants were partners with add-on solutions to SharePoint or imaging solutions that integrate with many different ECMs. Alfresco uniquely represented one of the options that SharePoint users face—replacing it with another ECM.

A recent survey of over 500 professionals was conducted that found 80 percent of those using SharePoint thought it fell short of their expectations. Alfresco offers many valuable features in comparison to SharePoint:

  • Lower cost and higher ROI
  • Faster implementations
  • More advanced workflow capabilities
  • Scalability and stronger search features
  • An open platform that more easily integrates with business-critical tools

While not everyone is looking to migrate to a new ECM, there are tools available to better manage content already in SharePoint. To learn more about managing your SharePoint data in Alfresco, watch our webinar recording.

There are many different options to choose from when considering your current ECM investment and where to invest your resources in the future. Alfresco offers a scalable, flexible and cost efficient solution for managing your content. Is SharePoint providing the same for you?

Categories: ECM

Liferay Sync Mobile 2.0

Liferay - Wed, 05/08/2013 - 17:46

We are pleased to announce that Sync Mobile 2.0 has been released!

  In addition to having incorporated several bug fixes, this version represents the integration of noteable, new features:  
  • Tablet Support: You can, now, use Sync on your iPads and Android tablets.
  • Revamped UI: Allows you to fully take advantage of larger screen sizes while providing for a heightened file-previewing experience.

 

Here are some screenshots of Sync running on an iPad:

 

 

 

You can install Sync from Google Play and App Store

 

  Bruno Farache 2013-05-08T22:46:18Z
Categories: CMS, ECM

Liferay, WebSockets, and Node: Good Times!

Liferay - Wed, 05/08/2013 - 16:47
Lately I've been tinkering a lot with lightweight, asynchronous, event-driven apps on Liferay using a variety of established techniques and frameworks. It's a nice way to build apps! After working it for a while, I wanted to share what I've learned, so put together a talk and was fortunate to be selected to attend and speak at this year's KCDC, and presented my learnings and a demo via a presentation on Event-driven Programming with Java and HTML5 WebSockets.   You can find the slides on SlideShare, and the demo code on GitHub.   At the end of the presentation I showed a demo, and I wanted to go into a bit more detail here. It is essentially a WebSockets demo using a Google Heatmap to visualize the location of bloggers who are blogging on a Liferay site. I used Tomcat 8.x for the JSR-356 WebSockets implementation, partly because I am comfortable it, but also because it has a bug that I wanted to use to demonstrate a point I made during the talk :) I'm pretty sure GlassFish doesn't suffer from this!   Social Driver To simulate lots of people doing activity on Liferay (and therefore generating activities for which I can listen), I re-used my Social Driver, resurrected from 7Cogs. This code spawns theads that programmatically create users and create blog entries, wiki pages, forum posts, and do other activities like vote and comment on content. It does this in separate threads, which simulates lots of people doing things on your Liferay site.   I have covered the basics of the SocialDriver in my series of "7Cogs is Dead! Long Live 7Cogs!" posts (here, and here), which I hope to finish off in the next couple of weeks.    Demo Part 1 In the first part of the demo, I have a Google Heatmap which visualizes the location of the fake users, based on their registered address (which is also faked). When content (blogs, wikis, forums) is created, a SocialActivity is generated. My hook listens for these events, and sends them to my WebSocket endpoint, which ships them to my client webpage with the Google map. It all works great when you have a single thread generating events.  The map builds nicely, and all is well. However, a few seconds after you start up more threads, things get weird, and WebSocket messages emitted from the server get jumbled and mixed together, causing the browser to immediately fail the websocket connection, and the client comes to a grinding halt (Liferay happily continues to create activities, though).   Demo Part 2 In part 2 we used Wireshark to inspect the network traffic, in an attempt to debug the problem.  Looking at the network traffic reveals that in the end, the last few WebSockets frames are mixed up / jumbled up, causing the browser to misinterpret the bytes, and fail quickly (which is nice!).   The problem appears to be that the code in Tomcat for sending messages down the pipe isn't multithread-safe.  Two or more threads can get into the same area of code, and send content at the same time, and this is exactly what happened here: my blog thread and my wiki thread tried to send messages to the client at the same time, and one's message was mixed in with the other, causing the browser to issue a cryptic Could not decode a text frame as UTF-8.  Looking at the offending packet in Wireshark: You can see the complete message of {"address":"Sudan"} but then some more bits that is the beginning of the next message, which the browser tries to interpret as text, and fails (it's actually the beginning of the next websocket frame).   Synchronizing the code that calls into Tomcat does the trick (e.g. via synchronized), but a) I shouldn't have to do that because it's part of the spec (and I think this is a bug in Tomcat), and b) Tomcat might not be the best place to scale out, especially because it's hosting Liferay already.  Node.js to the rescue!   Demo Part 3 Here, we let Node handle the websockets broadcasts to the clients, while Tomcat and Liferay handle the portal itself. The code in my tiny node server (which requires websockets.js, via npm install websockets) does the trick.  It listens for messages over HTML (this could have, and probably should have been done with redis pub/sub but I was out of time), and then broadcasts them to all clients listening on the websocket. In this demo there's only one client,    With node in place, and click the switch on the portlet, to switch over to it and then happily start up many threads and watch our heatmap build nicely:   Lessons learned
  • Coding event-based, asynchronous web program is fun and exciting! There are many frameworks and technologies to make it easy, both on client and server, and if I can do it, anyone can do it :)
  • It's really easy to integrate awesome apps with Liferay, due to its Java heritage, rich APIs and lightweight JSON or RESTful web services.
  • Java EE features (like JSR-356, aka WebSockets) and other upcoming technologies in Java EE 7 will lower the Java EE learning curve even further.
Enjoy! James Falkner 2013-05-08T21:47:52Z
Categories: CMS, ECM

Creating A Big Media Site in Liferay

Liferay - Wed, 05/08/2013 - 11:56
pre.line-pre { max-height: 100.0%; }

I wanted to prototype a site similar to an online tv and movie streaming service that isn't Netflix. I wanted to find a versital carousel that worked well with responsive (Flexslider2). I wanted the heading to become more of a solid background color after you scrolled down past the main carousel.

The carousels are fluid when the window is resized.


screenwidth: 1280px

screenwidth: 1024px

 

screenwidth: 480px

 

(after scroll past the main carousel the banner becomes a transparent color instead of gradient background image)

 

I loaded the additional js file for the carousel when detected

In the Main Carousel.vm velocity template I tweaked some of the js.

  • After the first slide is loaded I remove the loading class on the body tag.
  • I detect if there is a banner and toggle the banner from absolute position to fixed if the dockbar was still on the screen.
  • Detect the height of the carousel - #banner height then if vertical scroll is larger than that number then I add a class of changed, which replaces the background image with a background color.
Download and Test

Download big-media-theme.war for 6.1.1+

Git Branch

Bradley Wood 2013-05-08T16:56:41Z
Categories: CMS, ECM

Crafter + Alfresco Powers Next Generation Websites

Alfresco - Tue, 05/07/2013 - 09:31

“Web content management is evolving from website publishing to digital experience support,” according to Forrester’s WCM for Digital Customer Experience Q2 2013.

What does Forrester mean?  You don’t need an explanation if…

  • You’re reading this on a smartphone or tablet
  • You’ve updated a website on your own, without sending files to an IT person
  • You rely on user generated or suggestions from trusted communities

Websites were once about flat content with little interaction.  Today, that sort of nostalgia doesn’t play.  What we expect is…

  • A digital experience that flows from browser to tablet to mobile flawlessly
  • A site to be responsive to our requests with targeted information
  • Communities to suggest and bubble up the best ideas, relevant to our needs

Building these abilities into a website isn’t easy. It takes more than pretty pictures and snappy text.  It takes extensive use of digital assets integrated into the web experience.  It assumes responsive design for viewing on any screen. It requires content targeting for presentation of the right content at the right time. It takes a dedicated tool purpose built for accomplishing the goal of delivering an awesome web experience. Yet many web and content experience management solutions are heavy, hard to learn and expensive.

Alfresco has a solution for WCM that it is built around the open strategy of content services. As a strategy, we decided to be committed to what we do best, manage digital content.  And although the core of WCM is managing digital content, today’s modern web requires a comprehensive solution. Welcome Crafter, you do it very well.

Who says?

  • YouSendIt:  “Crafter enabled our marketing and web development teams to easily deliver dynamic and engaging content, while knowing we have preeminent Crafter experts on hand for support,” said Steve Ceplenski, Senior Director, Web Services at YouSendIt. “Using Crafter’s next generation technology, we are able to quickly develop targeted content for our brand, and easily integrate with a SaaS translation system to manage sites in multiple languages.”
  • Full Sail University:  “We wanted to make use of rich web media, including flash and video in our new website and Alfresco did not limit us in any way.  Combining Crafter with Alfresco allowed us increased flexibility and to scale with relative ease” Mark Gilbert, VP Information and Media Technologies.  Read more here.
  • MasterCard, National Academy of Sciences and Harvard Business Publishing to name a few – check out more references here.

Today we welcome Crafter Software to the Alfresco Partner Program as their own organization with their own team to sell and support the solution. Check out their website to learn more and read more about the great work they are doing!

Categories: ECM

Select Category And add Post in message board using velocity template

Liferay - Tue, 05/07/2013 - 07:13

Hi Guys,

It is possible to put web content of MB-category in every page rather than to display message board in every page in website .

On selecting category, we will open a pop-up dialog box for inserting  Post in message board. 

Template Code :

 

#set ($MBLocalService= $serviceLocator.findService("com.liferay.portlet.messageboards.service.MBCategoryLocalService"))   #set($cat=$MBLocalService.getCategories($groupId))   <form name="frmmb" id="frmmb"> <select name="foo" id="foo" onchange="pop(this.value)"> <option  value= "select">  -select-- </option>  #foreach ( $c in $cat) <option  value= "$c.getCategoryId()">  $c.getName() </option>    #end </select> </form> <script type="text/javascript" charset="utf-8">      function pop(value) { var s=value; alert(s);  AUI().ready('aui-dialog','aui-dialog-iframe','liferay-portlet-url', function(A) {          var url = Liferay.PortletURL.createRenderURL();          url.setPortletId("19");          url.setWindowState('pop_up');              url.setParameter("&_19_struts_action=%2Fmessage_boards%2Fedit_message&_19_mbCategoryId=");   window.myDialog = new A.Dialog(             {                  title: 'Ask a Question?',                  width: 640,                  centered: true              }         ).          plug(              A.Plugin.DialogIframe,             {                  uri: url.toString()+""+s,                  iframeCssClass: 'dialog-iframe'             }          ).render();     });  }   </script> <input type="button"  class="aui-button-input aui-button-input-submit"  name="dialog" value="Select Catagory & Add Question" />

 

I implemented this code at http://liferay.medicalassociation.in/ask-question  Visit For Better Understanding .

chirag @ India 2013-05-07T12:13:42Z
Categories: CMS, ECM
Syndicate content