Skip navigation
All Places > Alfresco Premier Services
fmalagrino

WCMQS Part II

Posted by fmalagrino Employee Aug 20, 2018

Welcome to WCMQS Part II! If you didn't read part I so far, please do so for some more background information.

 

WCMQS is based on Spring Surf and not Aikau as few people thought.

 

What does it mean that it is based on Spring Surf?

 

Spring Surf needs for rendering a new page a page.xml and page.ftl a template.xml and template.ftl and a webscript(s).

 

When you install WCMQS the alfresco data dictionary is extended by a new content model names ws:webSiteModel

the model is designed to be as generic as possible

The model have new types :

  • ws:website type
  • ws:section type
  • ws:webroot type
  • ws:webassetCollectionFolder type
  • ws:webassetCollection type
  • ws:indexPage type
  • ws:article type
  • ws:image type
  • ws:visitorFeedback type
  • ws:visitorFeedbackSummary type
  • ws: publishqueueentry type
  • ws:webasset aspect

 

Let's see what are these new types in details:

 

The ws:website type:

Is derived from the cm:folder type and represent a website.

This type has properties that apply to an entire website, such as host name, port and context of the web application that delivers the website.

If you read part I, you should understand yet where we modified these properties, in the Quick Start data in Alfresco Share. The folder at Documents/Alfresco Quick Start/Quick Start Editorial / Live is of this type. You can see the Host name. port and context in the folder's metadata.

 

 

Click "Edit Properties":

 

The ws:section type:

Is as well derived from the cm:folder type and represents a section of a website. 

The website is modeled as a tree of sections. 

A section defines an element in the website navigation and can contain child sections and web assets, such as the section's landing page, articles, collections of articles and images.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/blog  folder is of this type.

 

The ws:webroot type:

Is derived from the ws:section type and represents the root of a website's tree of sections.

This type extends the section type so therefore a web a webroot folder *is* also a section.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root  folder is of this type.

 

 

Edit Properties:

 

The ws:webassetCollectionFolder type:

Is derived from the cm:folder type and is used to hold asset collections.

Each section folder has a webassetCollectionFolder below it named 'collections' in which all of that section's asset collections are placed.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/blog/collections folder is of this type.

 

The ws:webassetCollection type:

Is derived from the cm:folder type and represents an asset collection.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/blog/collections/latest.articles folder is of this type.

 

 

Edit Properties:

 

The ws:indexPage type:

is derived from the cm:content type and represents an index page of a section (also know as the section's landing page).

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/blog/index.html asset is of this type.

 

 

More --> Edit Properties: --> all properties :

The ws:article type:

Is derived from the cm:content type and represents any piece of text-based content such as a news article or a blog post.

The article type defines few associations that allow an article to be linked with related articles and a couple of images.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/blog/blog1.html file is of this type.

 

 

More -->Edit properties --> All Properties:

 

The ws:image type:

Is derived from the cm:content type and is used for general image assets.

In the Web Quick Start data in Alfresco Share, in the Documents/Alfresco Quick Start/ Quick Start Editorial/root/publications/Alfresco-Office.jpg file is of this type.

 

 

 

The ws:visitorFeedback type:

Is derived from the dt:dataListItem type and represents feedback that has been submitted by visitors to a website.

The Intention is to be sufficiently generic to be useful for a number of different types of feedback including comments, reviews, ratings, and questions.

Each website has a Share data list created for it into which items of visitor feedback are placed.

When first Installed, Quick Start does not have any visitor feedback.

Submitting a comment to a blog post or a 'contact us' request from the website will create a node of this type in the repository

To add a datalist to your website you need to customize the site and drag and drop the datalist to current site pages.

 

 

 

After you clicked "OK" you should see a new option in the Menu called Data Lists,

 

 

If you use a blog or contact us

 

 

The ws:visitorFeedbackSummary type:

Is derived from the cm:object type and is used to record summary information about visitor feedback received for a given asset such as the number of comments received and the average rating was given.

 

The ws:publishqueueenty type:

Is derived from the cm:object type and is used to record nodes that have been queued up for publishing.

 

In share there are two workflow.

  • Review and Publish Section Structure 
  • Review and Publish

The first enable the review  and publish the structure of a section of the website. To publish particular section, initialize a workflow on that section's index.html. It will publish that section folder collection folder and as well subsections folders.

 

The second instead enables you to review and publish web content. Too publish the content you start the Review and Publish workflow.

 

The ws:webasset type:

Is derived from the cm:titled aspect and is used to mark any piece of content that is addressable through a website.

Among other things, a web asset (a node with the ws:webasset aspect) has two multi-valued NodeRef properties (ws:parentSection and ws:ancestorSections) that contain the identifier(s) of the section(s) in which  the asset is placed and its ancestor sections.

When an asset is created in, moved to, or removed from a section, these properties are updated to reflect the asset's new location.

This is done to make certain kinds of common queries very fast.

 

Other useful  properties :

Order index:

To configure the order in which navigation looks display. 

Lowest value of order index appeared to the right of the Home link and the remaining links are added in ascending numerical order.

NB : this is a mandatory aspect used on the folder called ws:ordered

 

 

Exclude From Navigation :

It allows you to show or hide that section from the menu.

Hi everybody,

 

To make a label bold or with a different color in APS you need to create a new class and add the new CSS property inside it.

 

The Process in my example will have only one human task with four check-boxes.

 

 

From the four check-boxes in the example two check-boxes should be bold and two normal but with blue as the color.

 

Let's create first the four check-boxes :

 

After this click the tab style and create a Classname

 

After you create the Classname you can create the style.

 

In the Style section let's create two classes: One to be bold and one to have the rest of the checkboxes blue but not bold.

 

Now that you have created this the next step is to add the class in the fields that we need.

 

In my example, test and test 3 will be bold and test2 and test4 blue.

 

Edit your first checkbox, click style and add the class to make it bold (this is the class from the style definition).

 

 

 

Now let's do the same for the second checkbox and let's make it blue and not bold.

 

 

Now edit the third and fourth checkbox similar to number one and two to apply the style on the check-boxes.

 

Now it's time to run the app and test the configuration. If all was done correctly you should have as result two check-boxes bold and two check-boxes blue as shown in the next screenshot:

 

 

NB: This work only on Activiti-app at the moment Workspace doesn't read any inline CSS or JS if you want use Workspace you'll need to create a custom control to do validation or hook into an event for that specific component or treat it as a custom stencil

 

If you want to download the app is available here.

This article provides information on how to migrate a project using the Alfresco Maven SDK version 2.2.0 to the new version 3.0.

 

Before starting I recommend to read the official SDK 3.0 documentation : http://docs.alfresco.com/5.2/concepts/sdk-getting-started.html, the Alfresco Beta User guide is also a good reference : https://community.alfresco.com/docs/DOC-6855-alfresco-sdk-30-beta-user-guide

 

Why upgrade to new SDK

 

The SDK version 3 get rid of the compatibility matrix and supports the following Alfresco version :

  • 4.2.X
  • 5.0.X
  • 5.1.X
  • 5.2.X

 

The SDK also supports the community release.

 

The targeted version is set by a property (alfresco.platform.version and alfresco.share.version) so it's easy to switch target version.

 

Upgrading to newest version of the SDK is easier than before since the version is set using the property : alfresco.sdk.version

 

The SDK 3 now produce JAR file by default, but can also produce AMPs if you need. All the archetype have been revamped to follow standard folder structure.

 

Hot reloading is available using HotSwapAgent or Jrebel (you need license for this one). Both allow to reload classes and web-resources. But Jrebel is more powerful and allows to reload spring context file.

For more information about HotReloading and how to setup please refer to the official documentation : http://docs.alfresco.com/5.2/concepts/sdk-hot-reloading.html

 

The new version of SDK is highly configurable. The Alfresco Maven plugin that handle running and testing your module offer 40 configurable parameters. The execution is controlled by the maven command: "mvn install alfresco:run"

 

Migrating your project

 

The SDK 3.0 revamped project structure introduces a major change since the version 2.2.0 so it's no longer compatible. The recommended approach is to create a new project based on the version 3.0 and migrate your project file to this new project.

 

Generate and configure your new project

 

The maven archetype are up to date and can be used to generate a new project compatible to the new version with the command "mvn archetype:generate -Dfilter=org.alfresco:"

Since we are talking about an old All-In-One project we will use the all-in-one archetype (org.alfresco.maven.archetype:alfresco-allinone-archetype) in the version 3.0.1.

Maven will take care of generating the folder structure and the default configuration.

 

By default generated project are configured to use the following community version:

  • Platform : 5.2.e
  • Share: 5.2.f

 

You can adjust the version by updating the properties :

  • alfresco.platform.version
  • alfrescco.share.version

 

If you want to use enterprise version you will need to update the properties "maven.alfresco.edition" replacing "community" with "enterprise". You also need valid credential for the alfresco-private repository to retrieve archetype.

 

If you need to test your extension with external dependency (such as RM), you can configure the Alfresco Maven Plugin to install those module on your platform or your share when running locally.

 

In order to achieve this you will need to add the module to the "platformModules" and "shareModules" in the configuration section for "alfresco-maven-plugin".

 

For example if you want to add Record Management Community version 2.6.0 to your platform and share you need to add:

  • In the platformModules section:

 

<moduleDependency>

<groupId>org.alfresco</groupId>

<artifactId>alfresco-rm-community-repo</artifactId>

<version>2.6.c</version>

<type>amp</type>

</moduleDependency>

 

  • In the shareModules section:

 

<moduleDependency>

<groupId>org.alfresco</groupId>

<artifactId>alfresco-rm-community-share</artifactId>

<version>2.6.c</version>

<type>amp</type>

</moduleDependency>

 

You can find those information on Alfresco Nexus repository.

You can start alfresco locally using the Alfresco Maven plugin to test your configuration.

 

Move your project to SDK 3.0 project

 

In the following section I will use an OOTB SDK 2.2.0 project generated with maven :

 

$ mvn archetype:generate -Dfilter=org.alfresco.maven.archetype:

 

With the following parameter:

 

Archetype version: 2.2.0

Define value for property 'groupId': com.example

Define value for property 'artifactId': aio

[INFO] Using property: version = 1.0-SNAPSHOT

Define value for property 'package' com.example: :

 

The target project will be generated from maven too with the same command and the following parameters :

Archetype version: 3.0.1

Define value for property 'groupId': com.example

Define value for property 'artifactId': aio30

[INFO] Using property: version = 1.0-SNAPSHOT

Define value for property 'package' com.example: :

 

So our project to migrate holds 2 extensions sub-module :

  • aio-repo-amp : I will refer to the root of this sub-module as AIO_REPO_ROOT
  • aio-share-amp  : I will refer to the root of this sub-module as AIO_SHARE_ROOT

 

And the new project also holds 2 extensions:

  • aio30-platform-jar:  : I will refer to the root of this sub-module as AIO30_PLATFORM_ROOT
  • aio30-share-jar : I will refer to the root of this sub-module as AIO30_SHARE_ROOT

 

Java Code

 

Java code is the easy part since the location of java class is standard in maven projects:

  • Copy AIO_REPO_ROOT/src/main/java/* to AIO30_PLATFORM_ROOT/src/main/java
  • Copy AIO_SHARE_ROOT/src/main/java/* to AIO30_SHARE_ROOT/src/main/java

 

Config folder (PROJECT_ROOT/src/main/amps/config)

 

When installing an AMP into an alfresco.war (or share.war) the content of this folder is expanded into <ROOT>/WEB-INF/classes.  In the new SDK,  such content goes into the resources folder since the resources folder is equivalent to the classpath root.

  • Copy the content of AIO_REPO_ROOT/src/main/amps/config/* to AIO30_PLATFORM_ROOT/src/main/resources
  • Copy the content of AIO_SHARE_ROOT/src/main/amps/config/* to AIO30_SHARE_ROOT/src/main/resources

 

Web folder (PROJECT_ROOT/src/main/amps/web)

 

This folder is used to hold web resources (CSS, JS….). In the new SDK those kind of files can go into 2 location:

  • PROJECT_ROOT/src/main/resources/META-INF/resources
  • PROJECT_ROOT/src/main/assembly/web

 

The first option is compatible with delivering a JAR file or an AMP file. The second can only be used if you plan to deliver AMP file. With the first option, your files will be compressed into the jar file and could not be overridden by other module or someone with access to the filesystem. The second option is the opposite, the file will be expanded in your war file and can be overridden by other module or someone with access to the filesystem.

 

Since only option one is compatible in all cases, I highly recommend to use that solution:

  • Copy the content of AIO_REPO_ROOT/src/main/amps/web/* to AIO30_PLATFORM_ROOT/src/main/resources/META-INF/resources
  • Copy the content of AIO_SHARE_ROOT/src/main/amps/web/* to AIO30_SHARE_ROOT/src/main/resources/META-INF/resources

 

Module.properties file

 

In SDK 2.2.0 the module.properties file is located in "amps" folder (PROJECT_ROOT/src/main/amps). In the SDK 3.0 these file goes into the module/<module_name> folder.

  • Copy the file AIO_REPO_ROOT/src/main/amps/config/module.properties to AIO30_PLATFORM_ROOT/src/main/resources/alfresco/module/<module_name>

 

Fixing path

 

In spring context file some path might be depending on the artifactId. You need to fix those path before testing your migration.

There is 2 way to fix this:

  • Change the artifactId to reflect your old artifactId
  • Rename the folder with the new artifactId

 

Summary

 

In order to migrate our project from SDK 2.2.0 to SDK 3.0 we have to:

  • Copy AIO_REPO_ROOT/src/main/java/* to AIO30_PLATFORM_ROOT/src/main/java
  • Copy AIO_SHARE_ROOT/src/main/java/* to AIO30_SHARE_ROOT/src/main/java
  • Copy the content of AIO_REPO_ROOT/src/main/amps/config/* to AIO30_PLATFORM_ROOT/src/main/resources
  • Copy the content of AIO_SHARE_ROOT/src/main/amps/config/* to AIO30_SHARE_ROOT/src/main/resources
  • Copy the content of AIO_REPO_ROOT/src/main/amps/web/* to AIO30_PLATFORM_ROOT/src/main/resources/META-INF/resources
  • Copy the content of AIO_SHARE_ROOT/src/main/amps/web/* to AIO30_SHARE_ROOT/src/main/resources/META-INF/resources
  • Fix path dependant from the artifactId

It has now been a few days since DevCon 2018 wrapped up, and after digesting everything that happened I feel like it is a good time to write down a few thoughts.  In short, DevCon was AWESOME!  It's no secret that DevCon was always a favorite of our community, our partners and of course, the extended team at Alfresco.  This year's event felt like we never stopped doing it.  The attendees were engaged, the energy was high, and the sessions were informative and fun.  For that, we owe Kristen Gastaldo, Francesco Corti, Richard Esplin and their collaborators at the Order of the Bee a huge amount of gratitude.  Even though it was a reboot of a crowd favorite event, a lot has changed.

 

The Alfresco community has always been a driving force at DevCon, as it should be.  We are an open source company, after all, and when you are an open source company your community plays a pivotal role in your success.  This year that was on full display.  Not only were a huge number of our community superstars there in person, but even the talk selection was a joint effort between the community and the company.  The talks themselves were also a great mix of Alfrescians and our extended community, partners and customers.  If I recall correctly it was almost a neat split right down the middle.  Collaboration with the community was a running theme throughout the conference, and was the focus of one of the talks that wrapped up the first day.  Suffice to say, there are a TON of opportunities to get involved.  Whether you blog, write tutorials, create and contribute your own community extensions or work on an existing one, or submit pull requests to one of our numerous open source projects, it isn't hard to find a way to contribute.

 

As for the talks themselves, the content was of the quality we expect from our team and community.  Several people from the Alfresco Strategic Services team were among those selected to present, but unfortunately I didn't get to see all of them due to conflicts with my own speaking slots and other conference duties.  Jose Portillo spoke on Solr Sharding, Luis Cabaceira shared some great work he has been doing with Piergiorgio Lucidi on ManifoldCF, Richard McKnight covered some best practices for building Alfresco extensions, and Mohammed Gazal took his first turn on the stage to present some work on PDF templating.  Luckily the talks were all recorded, and will be posted in the coming weeks.  If you missed something the first time around, you'll have the whole event at your fingertips. 

 

One thing in particular that I liked about this year's DevCon was the mix between what is best practice today, what is coming from Alfresco, and a third category that you might call "the art of the possible".  Of course we had some great sessions on securing content with our governance tools, exporting content, building ACS extensions, tuning Solr and building resilient systems, but we also had a lot of forward looking sessions focused on AWS, ADF and other cutting edge stuff coming out of Alfresco.  I'd like to see this continue in the future.  It's important for us to share the best way to do things today as well as preparing ourselves and our community for the future.

 

With so many submissions not everybody was able to be included in the official conference agenda, but we are working to find ways to get that knowledge out into the world.  Perhaps as blog posts, or maybe some community webcasts?  Not sure yet but I'd love to hear how you would like us to continue the momentum that DevCon started.  I'm coming off this conference with a huge amount of energy, and can't wait to see what the rest of 2018 has in store! 

Overview

 

One of the most critical and time consuming process in relation to the Alfresco Content Connector for Salesforce module is migrating all the existing Notes & Attachments content from Salesforce instance to the On-Premise Alfresco Content Services (ACS) instance. This requires lot of planning and thought as to how this use case can be implemented and how the content migration process can be completed successfully. When the end users start using the connector widget in Salesforce they will be able to upload new documents and make changes to existing documents etc within Salesforce but the actual content is stored in an ACS instance. Some of the core components/steps involved in this process are

  • Number of documents/attachments that need to be migrated to Alfresco
  • Salesforce API limits available per 24 hour period. Use SOQL query or ACC API functions to retrieve the content. We need to make sure the available API calls are not fully used by the migration activity.
  • Naming conventions - some of the special characters used in SFDC's filename may not be supported in Alfresco, so some consideration must be given to manipulate the filenames in Alfresco when the documents are saved.
  • Perform a full content migration activity in a Salesforce DEV/UAT environment that has a complete copy of production data. This will assist in determining issues such as naming conventions, unsupported documents/document types etc.
  • Custom Alfresco WebScripts/Scheduled Actions to import all content from SFDC to Alfresco
  • Make sure there are enough system resources in the Alfresco server to hold all the content in the repository. This includes disk capacity, heap/memory allocated to JVM, CPU etc. 

We will look in to all these core components in more detail later in this blog post.

 

Why Content Migration?

 

Why would we want to migrate all the existing content from SFDC to Alfresco? of course there are many reasons why this migration activity is required/mandatory for all the businesses/end users who will use this module.

  • End users need to be able to access/find the legacy or existing documents and contracts in the same way as they normally do.
  • Moving content over to ACS instance will save plenty of money for the businesses since the Salesforce storage costs are really expensive. 
  • Easier access to all documents/notes using the ACC search feature available in the widget.
  • Content can be accessed in both Salesforce and Alfresco depending on the end user's preference. Some custom Smart Folders can be configured in ACS to get a holistic view of the contents that the end user require. For example, end users would want to only see the content related to their region. In which case a Smart folder can be configured to query for a Salesforce object based on a particular metadata property value, such as sobjectAccountRegion, sobjectAccount:Regional_Team etc.

 

Steps Involved

 

  1. Determine the total number of Notes & Attachments that must be migrated/imported to ACS - This can be determined by using Salesforce Developer Workbench. Use a SOQL query to get a list of all Notes/Attachments of a specific Salesforce object. For example Accounts, Opportunities etc.SOQL Query

         You may also use the RESTExplorer feature in the workbench to execute this query.

Some sample SOQL queries are      

To retrieve attachments of all Opportunity objects in SFDC - Select Name, Id, ParentId from Attachment where ParentId IN (Select Id from Opportunity)
To retrieve Notes of all Account objects in SFDC - Select Id,(Select Title, Id, ParentId, Body from Notes) from Account

REST Explorer View

  

   2.   Develop Alfresco Webscripts/Aysychronous action to retrieve and migrate all content from SFDC to Alfresco - It is probably a good idea to develop an Alfresco Asynchronous action (Java based) as opposed to a Webscript to perform the migration process. This is to ensure the actual migration runs in the background and there are no timeouts or anything as such we may see using the normal webscipts. Based on the amount of content it take can take few hours for the action to complete successfully. We will use the ACC module's available API's to make a connection to Salesforce and then use the relevant functions to retrieve the content. The code snippet to make a connection and execute a SOQL query are below. To get the content of an Attachment object in SFDC use the getBlob method. It should be something like below,

apiResult = connection.getApi().sObjectsOperations(getInstanceUrl()).getBlob("Attachment", documentId, "Body");

Open a connection to SFDC

 

SOQL Query

 

Once the connection and query are established you can then look to save the file in Alfresco based on the end-user/business needs. The code snippet to save the document in alfresco is below.

 

Code

 

   3.   “Warm up” of Alfresco folder structures without human intervention - One of the prerequsite to the content migration process is pre-creating all the SFDC objects folder structure within ACS and make sure the folders are mapped to the appropriate SFDC object. This can be achieved by exporting all the SFDC objects details in to CSV file. the CSV file must contain information such as SFDC Record Id, AccountId, Opportunity Id, Region etc. The SFDC Record ID is unique for each and every Salesforce object and the Content Connector widget identifies the mapping between ACS and SFDC using this ID. Before executing the content migration code, we would need to make sure all the objects exist in ACS first. Once CSV file is generated, then develop a custom ACS web script to process the CSV file line by line and create the appropriate folder structures and assign metadata values accordingly. Once ready execute the web script to  auto create all folder structures in ACS. A simple code snippet is below.

 

Warmup Code

 

   4.   Trigger the Migration code to import all content from SFDC to ACS - Once all the folder hierarchy for the required SFDC objects are setup in ACS, you may now execute the Asynchronous action developed in Step 2. To execute the Java Asynchronous action you may create a simple web script which executes this action. A simple code snippet is below.

var document = companyhome.childByNamePath("trigger.txt"); var sfdcAction = actions.create("get-sfdcopps-attach"); sfdcAction.executeAsynchronously(document); model.result=document;

You may choose to execute this in multiple transactions instead of a single transaction. If there are tens and thousands of documents that need to be imported then the best approach is to have multiple transaction at the migration code level.

Once the migration process is complete, the documents must be located in the relevant folder hierarchy within ACS and its associated object page in SFDC.

 

ACC Documents

 

   5.   Validate the content - Once the document import process is complete, make sure to test & validate that all the documents are imported to the appropriate folder hierarchy in ACS and also it is accessible within the Salesforce Content Connector widget. Key things to check are the thumbnails, preview, file names, file content etc.

 

Hope all this information helps in your next Alfresco Content Services content migration activity.

Troubleshooting application performance can be tricky, especially when the application in question has dependencies on other systems.  Alfresco's Content Services (ACS) platform is exactly that type of application.  ACS relies on a relational database, an index, a content store, and potentially several other supporting applications to provide a broad set of services related to content management.  What do you do when you have a call that is slow to respond, or a page that seems to take forever to load?  After several years of helping customers diagnose and fix these kinds of issues, my advice is to start at the bottom and work your way up (mostly).

 

When faced with a performance issue in Alfresco Content Services, the first step is to identify exactly what calls are responding slowly.  If you are using CMIS or the ACS REST API, this is simple enough, you'll know which call is running slowly and exactly how you are calling it.  It's your code making the call, after all.  If you are using an ADF application, Alfresco Share or a custom UI it can become a bit more involved.  Identifying the exact call is straightforward and you can approach this the same way you would approach it for any web application.  I usually use Chrome's built in dev tools for this purpose.  Take as an example the screenshot below, which shows some of the requests captured when loading the Share Document Library on a test site:

 

 

In this panel we can see the individual XHR requests that Share uses to populate the document library view.  This is the first place to look if we have a page loading slowly.  Is it the document list that is taking too long to load?  Is it the tag list?  Is it a custom component?  Once we know exactly what call is responding slowly, we can begin to get to the root of our performance issue.

 

When you start troubleshooting ACS performance, it pays to start at the bottom and work your way up.  This usually means starting at the JVM.  Take a look at your JVM stats with your profiler of choice.  Do you see excessive CPU utilization?  How often is garbage collection running?  Is the system constantly running at or close to your maximum memory allocation?  Is there enough system memory available to the operating system to support the amount that has been allocated to the JVM without swapping?  It is difficult to provide "one size fits all" guidance for JVM tuning as the requirements will vary based on the the type of workload Alfresco is handling. Luis Cabaceira has provided some excellent guidance on this subject in his blog.  I highly recommend his series of articles on performance, tuning and scale.  When troubleshooting ACS performance, start by ensuring you see healthy JVM behavior across all of your application tiers.  Avoid the temptation to just throw more memory at the problem, as this can sometimes make things worse.

 

Unpacking Search Performance

 

Assuming that the JVM behavior looks normal, the next step is to look at the other components on which ACS depends.  There are three main subsystems that ACS uses to read / write information:  The database, the index, and the content store.  Before we can start troubleshooting, we need to know which one(s) are being used in the use case that is experiencing a performance problem.  In order to do this, you will need to know a bit about how search is configured on your Alfresco installation.  Depending on the version you have installed, Alfresco Content Services (5.2+) / Alfresco One (4.x / 5.0.x / 5.1.x) supports multiple search subsystem options and configurations.  It could be Solr 1.4, Solr 4, Solr 6 or your queries could be going directly against the database.  If you are on on Alfresco 4.x, your system could also be configured to use the legacy Lucene index subsystem, but that is out of scope for this guide.  The easiest way to find out which index subsystem is in use is to look at the admin console.  Here's a screenshot from my test 5.2 installation that shows the options:

 

 

Now that we know for sure which search subsystem is configured, we need to know a little bit more about search configuration.  Alfresco Content Services supports something known as Transactional Metadata Queries.  This feature was added to supplement Solr for certain use cases.  The way Solr and ACS are integrated is "eventually consistent".  That is to say that content added to the repository is not indexed in-transaction.  Instead, Solr queries the repository for change sets, and then indexes those changes.  This makes the whole system more scalable and performant when compared with the older Lucene implementation, especially where large documents are concerned.  The drawback to this is that content is not immediately queryable when it is added.  Transactional Metadata Queries work around this by using the metadata in the database to perform certain types of queries, allowing for immediate results.  When troubleshooting performance, it is important to know exactly what type of query is executed, and whether it runs against the database or the index.  Transactional metadata queries can be independently turned on or off to various degrees for both Alfresco Full Text Search and CMIS.  To find out how your system is configured, we can again rely on the ACS admin console:

 

The full scope of Transactional Metadata Queries is too broad for this guide, but everything you need to know is in the Alfresco documentation on the topic.  Armed with knowledge of our search subsystem and Transactional Metadata Query configurations, we can get down to the business of troubleshooting our queries.  Given a particular CMIS or AFTS query, how do we know if it is being executed against the DB or the index?  If this is a component running a query you wrote, then you can look at the Transactional Metadata Query documentation to see if Alfresco would try to run it against the database.  If you are troubleshooting a query baked into the product, or you want to see for sure how your own query is being executed, turn on debug logging for class DbOrIndexSwitchingQueryLanguage.  This will tell you for sure exactly where the query in question is being run.

 

The Database

 

If you suspect that the cause may be a slow DB query, there are several ways to investigate.  Every DB platform that Alfresco supports for production use has tools to identify slow queries.  That's a good place to start, but sometimes it isn't possible to do because you, as a developer or ACS admin, don't have the right access to the DB to use those tools.  If that's the case you can contact your DBA or you can look at it from the application server side.  To get the app server view of your query performance you again have a few options.  You could use a JDBC proxy driver like Log4JDBC or JDBCSpy that can output query timing to the logs.  It seems that Log4JDBC has seen more recent development so that might be the better choice if you go the proxy driver route.  Another option is to attach a profiler. JProfiler and YourKit both support probing JDBC performance.  YourKit is what we use most often at Alfresco, and here's a small example of what it can show us about our database connections:

 

 

With this view it is straightforward to see what queries are taking the most time.  We can also profile DB connection open / close and several other database related bits that may be of interest.  The ACS schema is battle tested and performant at this point in the product lifecycle, but it is fairly common to see slow queries as a result of a database configuration problem, an overloaded shared database server, poor network connection to the database, out of date index statistics or a number of other causes.  If you see a slow query show up during your analysis, you should first check the database server configuration and tuning.  If you suspect a poorly optimized query (which is rare) contact Alfresco support.

 

One other common source of database related performance woes is the database connection pool.  Alfresco recommends setting the maximum database connection pool size on each cluster node to the number of concurrent application server worker threads + 75 to cover overhead from scheduled jobs, etc.  If you have Tomcat configured to allow for 200 worker threads (200 concurrent HTTP connections) then you'll need to set the database pool maximum size to 275.  Note that this may also require you to increase the limit on the database side as well.  If you have a lot of requests waiting on a connection from the pool that is not going to do good things for performance.

 

The Index

 

The other place where a query can run is against the ACS index.  As stated earlier, the index may be one of several types and versions, depending on exactly what version of Alfresco Content Services / Alfresco One you are using and how it is configured.  The good news is that you can get total query execution time the same way no matter which version of Solr your Alfresco installation is using.  To see the exact query that is being run, how long it takes to execute and how many results are being returned, just turn on debug logging for class SolrQueryHttpClient.  This will output debug information to the log that will tell you exactly what queries are being executed and how long each execution takes.  Note that this is the query time as returned in the result set, and should just be the Solr execution time without including the round trip time to / from the server.  This is an important distinction, especially where large result sets are concerned.  If the connection between ACS and the search service is slow then a query may complete very quickly but the results could take a while to arrive back at the application server.  In this case the index performance may be just fine, but the network performance is the bottleneck.

 

If the queries are running slowly, there are several things to check.  Good Solr performance depends heavily on good underlying disk I/O performance.  Alfresco has some specific recommendations for minimum disk performance.  A fast connection between the index and repository tiers is essential, so make sure that any load balancers or other network hardware that sit between the tiers are providing good performance.  Another thing to check is the Solr cache configuration.  Alfresco's search subsystem provides a number of caches that improve search performance at the cost of additional memory.  Make sure your system is sized appropriately using the guidance Alfresco provides on index memory requirements and cache sizes.  Alfresco's index services and Solr can show you detailed cache statistics that you can use to better understand critical performance factors like hit rates, evictions, warm up times, etc as shown in this screenshot from Alfresco 5.2 with Solr 4:

 

 

In the case of a large repository, it might also help to take a deeper look at how sharding is configured including the number of shards and hosts and whether or not the configuration is appropriate.  For example, if you are sharding by ACL and most of your documents have the same permissions, then it's possible the shards are a bit unbalanced and the majority of requests are hitting a single shard.  For this case, sharding by DBID (which ensures an even distribution) might be more appropriate and yield better performance.

 

It is also possible that a slow running query against the index might need some tuning itself.  The queries that Alfresco uses are well optimized, but if you are developing an extension and want to time your own queries I recommend looking at the Alfresco Javascript Console.  This is one of the best community developed extensions out there, and it can show you execution time for a chunk of Alfresco server-side Javascript.  If all that Javascript does is execute a query, you can get a good idea of your query performance and tweak / tune it accordingly.

 

The Content Store

 

Of all of the subsystems used for storing data in Alfresco, the content store is the one that has (typically) the least impact on overall system performance.  The content store is only used when reading / writing content streams.  This may be when a new document is uploaded, when a document is previewed, or when Solr requests a text version of a document for indexing.  Poor content store performance can show itself as long upload times under load, long preview times, or long delays when Solr is indexing content for the first time.  Troubleshooting this means looking at disk utilization or (if the content store resides on a remote filesystem) network utilization.

 

Into The Code

 

A full discussion of profiling running code would turn this from an article into a book, but any good systems person should know how to hook up a profiler or APM tool and look for long running calls.  Many Alfresco customers use things like Appdynamics or New Relic to do just that.  Splunk is also a common choice, as is the open source ELK stack.  All of these suites can provide a lot more than just what a profiler can do and can save your team a ton of time and money.  Alfresco's support team also finds JStack thread dumps useful.  If we see a lot of blocked threads that can help narrow down the source of a problem.  Regardless of the tools you choose, setting up good monitoring can help you find emerging performance problems before they become user problems.

 

Conclusion

 

This guide is nowhere near comprehensive, but it does cover off some of the most common causes for Alfresco performance issues we have seen in the support world.  In the future we'll do a deeper dive into the index, repository and index tier caching, content transformer selection and execution, permission checking, governance services and other advanced topics in performance and scalability.

fmalagrino

WCMQS Part I

Posted by fmalagrino Employee Apr 28, 2017

What is WCMQS ?

Alfresco Web Quick Start is a set of website design templates and sample architecture, built on the Alfresco Share content management and collaboration framework.

With Quick Start, developers can rapidly build customized and dynamic web applications with powerful content management features for the business users without having to start from scratch.

Using standard development tools developers can quickly deploy the comprehensive content management capabilities of Alfresco to build new and innovative web applications. Developed using the Spring framework with Alfresco Surf, the Web Quick Start allows developers to easily extend Alfresco to add new features to support the demands of the business.

Why is good to know WCMQS ?

  • WCMQS is a powerful component for creating a website
  • You can customize your website as you wish
  • You can create web scripts in JavaScript or Java
  • You can use any JavaScript frameworks like AngularJS, ExpressJS etc, and libraries like jquery and also any responsive frameworks like Bootstrap foundation etc

 

How do you Install WCMQS ?

 

There are two ways to install WCMQS in your alfresco application:

1) If you use the installer you need tick the checkbox Web Quick Start 

2) if you are installing manually Alfresco using the war then you need only to add the war WCMQS to your alfresco application.

 

For checking that WCMQS have been installed correctly on your Alfresco application you can create a collaboration site:

 

 

 

After you have created your collaboration site it is time to add the web quick start dashlet.

 

Below, the screen captures will explain how to add a dashlet on Alfresco.

 

 

Choose "Add Dashlet"

 

 

Drag the "Web Quick Start" into one of the columns

 

The added dashlet will grant you access to two prototype websites: 

Finance (single language)

Government (multilanguage)

 

In my example I select Finance.

 

After you select one of the two prototypes it will create an example website inside the document library.

 

 

Configuring WCMQS :

 

After the installation it is time to configure WCMQS.

 

By default, WCMQS create two folders: One for editorial and one for live content:

 

Editorial and Live folder must have two different host as properties configured. By default the Editorial has the host "localhost" while live is be default configured to "127.0.0.1". Both are configured on port 8080 with the context name "wcmqs"

 

 

 

 

 

If you have a different port and you want a different name you need click the Editorial or Live and modify the properties.

 

In my example, the port is 8888 (because my alfresco run in port 8888) and my website will be called test.

 

 

Same configuration for live (apart from the host name):

 

 

#Once you decided how the site is called you need go under tomcat/webapps/ copy the WCMQS.war and rename to the name of your site.war. Alfresco will create your new site. Restart tomcat and now is time to test your site going to your "host":"port"/"context" of the site in my case will be localhost:8888/test/

 

 

If you have done all correctly you should see the following site :

 

If you need to create a custom property files and you want to use this custom property file in  Process Services you can do it using a Java Delegate or a Spring bean.

 

In my case, I used a Java Delegate.

 

First of all, create your custom property file and upload it to the following folder:

 

/alfresco/process-services-1.6.0/tomcat/webapps/activiti-app/WEB-INF/classes/

 

Now it is time to create a java delegate: But first of all it is important to understand what is the command to load the file properties:

 

It is just one line of code and it's the following line:

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("generic.properties");

With this code of line, you tell the java delegate which property file to load.

After you loaded it you can start to save your properties inside the property file and they will be used in Process Services.

String host = "";

String username = "";

String password = "";

Properties properties = new Properties();

properties.load(inputStream);

host = properties.getProperty("generic.host");

username   = properties.getProperty("generic.username");

password = properties.getProperty("generic.password");

execution.setVariable("host", host);

execution.setVariable("username", username);

execution.setVariable("password", password);

Let's explain a bit the code

 

So first as the best practice, we create some string and we set the value to empty. Otherwise you can have a null pointer exception.

 

After that, we load inside the Properties object our custom file property

 

Then we start to set our string with the value of the property that is set inside our file property.

 

In our example, generic.host will have some value inside the property file.

 

After we have assigned our string with all the value that we need from the property file we can set them as a variable 

 

execution.setVariable("host", host);

 

So this piece of code means that you have inside your process a variable called host and you are assigning this variable to the string value of the host entry inside the property file (generic.host)

 

After you finish the code it is time to export it as a jar and add the jar inside the following path:

 

/alfresco/process-services-1.6.0/tomcat/webapps/activiti-app/WEB-INF/lib/

 

To apply your new java delegate you need to create a service task and apply under the class field  the name of your class. Below are few screenshots how to do this:

 

1. A very simple example workflow

the process

 

 

2. Configure the global variable:

 

3. The variables set in step 2.

 

 

4. Setup the java delegate (adding the class name to the "class" field:

 

 

I created 2 forms for testing that my Java delegate is loaded correctly.

 

If the host variable will be empty the process should go one way and if it is correct it should go to the form that will display text with all our information of the file properties 

 

How to configure this:

 

1. Create the condition on one arrow :

 

Condition on arrow

 

2. Enter the condition (host: not empty) that will allow to the form success:

 

 

3. And the second condition:

 

 

 

If the host is not empty the process should go to the human task with the following form:

 

 

The reference form here is "success" and this is how it looks like:

 

 

Otherwise, if there is some problem from the java delegate it will go to the other form called "wrong":

 

 

 

For testing you can use the following snippets:

 

Java code:

package my.Test;

import java.io.InputStream;
import java.util.Properties;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;


public class GenericCustomProperties implements JavaDelegate {
String host = "";
String username = "";
String password = "";

   



    public void execute(DelegateExecution execution) throws Exception {
         InputStream inputStream = this.getClass().getClassLoader()
         .getResourceAsStream("generic.properties");
          Properties properties = new Properties();
          properties.load(inputStream);
          host = properties.getProperty("generic.host");
          username   = properties.getProperty("generic.username");
          password = properties.getProperty("generic.password");
          execution.setVariable("host", host);
          execution.setVariable("username", username);
          execution.setVariable("password", password);

         

    }


}

Please be sure to create a java project with a package called my.Test create containing a class called

GenericCustomProperties.java

 

Now that you created this java class export it as jar and upload at the following path: /alfresco/process-services/tomcat/webapps/activiti-app/WEB-INF/lib/

 

As custom properties, you can create a file called generic.properties, open it and write the following snippet:

generic.host=127.0.0.1:8080
generic.username=username
generic.password=password

 

The file needs be located inside the following path:

 

/alfresco/process-services-1.6.0/tomcat/webapps/activiti-app/WEB-INF/classes/

About three years ago, Alfresco created a new branch of our support and services organization, the Premier Services team.  Since then, the Premier Services team has grown into a first class global support organization, handling many of Alfresco's largest and most complex strategic accounts.  Our group consists of some of Alfresco's most seasoned and senior support staff and has a presence in APAC, EMEA and the US serving customers worldwide.  Today we start a new chapter in our journey.

 

One of the benefits of working with large accounts is the breadth and depth of problems we get to help them solve.  Premier Services accounts tend to be those with extensive integrations, demanding uptime, reliability and performance requirements, complex business environments and product extensions.  We are launching our blog to share best practices, interesting insights, code / configuration examples and problem solving tips that arise from our work.  This blog will also serve as a platform for sharing new service offerings and updates to existing offerings, and to give our customers and community members some insights into the direction that our service offerings will take as they evolve.  For our inaugural blog post, we'd like to talk about three recent changes to the Alfresco Premier Services offerings which we think will help reduce confusion about what we deliver and give our customers some extra value.  

 

First, you may have noticed that our web site has been updated as a part of Alfresco's Digital Business Platform launch.  As a part of this update we have started the process of merging two of our premier services offerings.  Previously we offered an On-site Services Engineer (OSE) and a Remote Services Engineer (RSE).  Going forward we are combining these into a single Premier Services Engineer (PSE) offering.  We can still deliver it on-site or remote, and the pricing has not changed.  Where there were differences in the services, we've taken the more generous option and made it the default.  For example, OSE and RSE service used to come with a different number of Alfresco University Passports.  Going forward all PSE customers will get five passports included with their service.  Future passports issued to Premier Services accounts will also include a certification voucher.

 

The other changes in our service are additions intended to help with a pair of common customer requests.  It is common for customers to start to staff up at the beginning of an Alfresco project, and we are often asked to help evaluate potential hires.  In support of this request we have created a set of hiring profiles that identify the core skills that we find will enable a new hire to come up to speed quickly on the Alfresco platform.  These hiring profiles and assessments are available now to all Premier Services accounts.  A second major change is the addition of Alfresco Developer Support to Premier Services accounts on the Alfresco Digital Business Platform.  What this means is that if you are a Premier Services customer and are using Alfresco Content Services 5.2+ AND Alfresco Process Services powered by Activiti 1.6+, you will get Developer Support for two of your support contacts included with your service at no additional cost.  This is a huge addition to the Premier Services portfolio, and we're excited to be able to offer it in conjunction with our peers on the dev support team.

 

Stay tuned for more from the Premier Services team, our next blog posts will take an in-depth look at some challenging technical issues.