Category Archives: API General concepts

Using RQL commands not implemented yet

jRQL did not offer all RQL commands existing. So you might need to use not yet implemented RQL commands within your programs. This is possible with jRQL of course, because you can trigger your own RQL commands and parse the response.

First, every jRQL object offers the following methods to call the MS with a self build RQL command string:
every object > callCms()
every object > callCmsWithoutParsing()

This is achieved by the interface CmsClientContainer which every jRQL class implements directly or indirectly. At the end the implementation in class CmsClient is used, therefore you can use should use it immediately there, if it is available.

Use the 2nd method, if you don’t need the result of a RQL command at all or the MS did not even return anything interesting.  It’s a small performance improvement.

Second you need to get all GUIDs to build your own RQL request string. Please refer to the post get GUIDs from all jRQL objects.

At last you need to parse the returned RQL response from the method callCms(). jRQL encapsulate the parsed response in one of the following classes:
RQLNode
RQLNodeList

You need to retrieve the respective tags and attribute values from the response now. Most important methods to achieve this are:
RQLNode > getNode()
RQLNode > getNodes()
RQLNode > getAttribute()

After getting the GUIDs of an implemented jRQL object again, I recommend to retrieve it via the offered methods and proceed with jRQL objects instead of using raw RQL commands for further steps.

With this way you can even use RQL commands which jRQL do not offer. This is not very elegant, I know, therefore keep me informed what’s missing and i will try to implement it into next version of jRQL.  I will announce an enhancement of jRQL API on the jRQL twitter stream.

Advertisements

Get GUIDs from all jRQL objects

The Management Server (MS) internally uses global unique identifier (GUID) as the primary key to all records. These GUIDs therefore are very important and you often need to get it back from jRQL objects to use it further, maybe in own RQL commands.

For every jRQL class which is tight to a MS object deliver the object’s GUID from a method of this style:
.get<class name>Guid();

Let me give some examples:
Project > getProjectGuid()
Template > getTemplateGuid()
TemplateElement > getTemplateElementGuid()
Page > getPageGuid()
AuthorizationPackage > getAuthorizationPackageGuid()
PublicationPackage > getPublicationPackageGuid()

Special are the main classes CmsClient and Project, because they encapsulate the session information additionally. For you own RQL command (or other reasons) you can get the session information back as following:
CmsClient > getLogonGuid()
Project > getSessionKey()

Please have in mind, that a session key is only available if you enter a MS project like it is in SmartTree and SmartEdit. Project still can be used in jRQL as it would be in ServerManager. In that case no session key is available and using a method requiring a session key will throw a MissingSessionKeyException.

Handling content class element names and other parameters

Because jRQL accesses all page elements via content class element names you need to feed your scripts and batch programs with these names.

Within all productive used plugins and batch programs I never use hard coded element names, because I wouldn’t have the chance to change these names easily.

In short, this is not a way of configuring all plugins with element names and other parameters. I use this hard coded approach only for on the fly programs I need to run usually once (directly running within Eclipse) but never productive.

I want to have all element names and other parameters within RedDot CMS. This store all elements names as close as possible to the content classes. And, in addition, I can even reuse a parameter on different plugins, simply by connecting to an existing parameter page.

To achieve this, I introduced 2 special content classes and a utility Java class to access these parameter values. Both are tightly connected.

For every plugin use an instance of content class rql_script, which has in the container parameters several instances of rql_script_parameter:

Above image shows one way to define parameters – using the headline of pages rql_script_parameter. Left beside the = is the parameter name, right the value. I maintain this pages only via SmartTree, so no SmartEdit red dots are available. Another way is to put the parameter name in the headline (without a =) and put the value into the ascii text element value, what overcome the length limit on headline (256 characters).

You can download the content classes for your own creation of such structure.

In last step you need to know how to access such parameters from your jRQL programs.  Use a code snippet like this to getting access to your parameters:

String logonGuid = “0B1FBC04A6D94A45A6C5E2AC8915B698”;
String sessionKey = “C26CF959E1434E31B7F9DA89829369B4”;
String projectGuid = “73671509FA5C43ED8FC4171AD0298AD2”;

CmsClient client = new CmsClient(logonGuid);
Project project = client.getProject(sessionKey, projectGuid);

ScriptParameters parms = project.getParameters(“267761”);
String imageFragmentTmpltName = parms.get(“imageFragmentTmpltName”);
String numberListTmpltElemName = parms.get(“numberListTmpltElemName”);
String numberOfColumnsTmpltElemName = parms.get(“numberOfColumnsTmpltElemName”);

The method project.getParameters() needs the page ID of your rql_script instance, in our case the page “createGallery parameters” has the page ID 267761.

The next 3 lines receive the parameter values for the 3 given content class element names, what makes it possible to change the element names in the content class and  – don’t forget – the parameter values quite easy.

This approach assume that your parameters are defined always within the scope of a project. If you follow this approach and you need a plugin in several projects you need to create the same parameter values within different projects and use the parameter’s page ID (e.g. 267761) as an input parameter of your plugin or batch program.

Transparent caching to increase performance

Working with jRQL is completely based on content class names and content class element names. Therefore in the background it needs to access content classes and elements very often. This was the main reason for me to introduce some caches within the objects.

I introduced caches as often as possible. I used the policy to cache the results of the RQL commands – for mostly static information. Means even page details will be cached, because I assumed they will not change while a jRQL process is running.

But there are several exceptions, for instance getting the page state within the workflow (draft, in correction, released) in contrast would be never cached, because I consider this to be changed quite often and to dangerous to cache. I reject using a cache when it seems to dangerous to me. The correctness stands over the performance, I think.

If you change a page, content class or any other object via jRQL the caches are automatically invalidated. This forces a re-read at the next access of the object’s data into the cache again. This is handled completely transparent as long as you use jRQL functions.

Because this caches can occupy an quite reasonable amount of memory, especially the caches within page objects, the class Page offers the method freeOccupiedMemory(). This can happen if you loop through hundreds of pages, because all pages are referenced from the PageArrayList and so will not be released by the Garbage Collector.

Use page.freeOccupiedMemory() at the end of your loop to keep your memory usage low. With that method all cache data and page details will be deleted, so the memory will not increase until the limit of the Java VM is reached.

But still the page object can be used afterwards, because the page GUID will not be removed. All empty instance variables and caches will be filled again.

Automatic activation of new content class elements in pages

Imagine you have a content class with a lot of pages as instances of it. Now you need to add a new element to this content class and want to import the new values for each page of this content class programatically.

In this scenario you might experience the problem, that the RQL command getting the page elements did not deliver the new element from the old page.

The reason for this is, that the CMS didn’t add the new page element only by adding the new element to the content class. I call this behavior, that the element is not activated on the page.

CMS solve this issue the way that the new page element will get activated, if you use the element somewhere in your display project variant’s code and access the page in SmartEdit or page preview. This was a big dilemma for me, because of often had thausands of pages I never can access in SmartEdit manually.

The good news is, that jRQL has an automatic activation mechanism built into. The only thing you need to do is to use the element in the SmartEdit code. I usually add a HTML comment with the value of the new element to achieve this.

What happens whtin jRQL? If you try to get the new element from a page of this content class (without using them in SmartEdit before) jRQL

  1. catches the exception that the element could not be found.
  2. Than it gets the whole SmartEdit HTML code of the page, what is similar of accessing the page in SmartEdit mode page closed. With this the CMS activate the new element on the page.
  3. jRQL gets all elements of the page again (page action=load) and try to find the given element again.

Step 3 now can end with an exception that the element cannot be found what is a programming mistake or it goes well, if you mentioned the new element in a comment of the template of your SmartEdit code.

Because I had this need very often in my projects and it’s impossible to go through all pages in SmartEdit only to activate new elements I added this feature.

Default values of content class elements are returned automatically

Quite often I use a default value in content class elements. Unfortunately the MS did not display it to the author and therefore are not returned automatically via RQL.

Because I feel uncomfortable with it, I added this feature to jRQL. All sub classes of Element (means all StandardField types, Image, Media and OptionList) and text elements return automatically and completely transparent the default value of the underlaying content class element.

Means that all get*Value methods are returning the default value from content class element without any effort for you.

You can find out if on the page a value was entered or the default value is returned ask the Element with one of the methods:

currentPg.getOptionList("content class element name").isEmpty();
currentPg.getOptionList("content class element name").hasTemplateDefaultValue();
currentPg.getOptionList("content class element name").isValueEntered();

Separate classes for page elements

For most content and structural elements of a page separate classes exists. The following page element types are supported by jRQL:

Affix Diese Klasse beschreibt ein Prefix oder Suffix eines Projektes.
Container Diese Klasse beschreibt einen RedDot MultiLink Container.
DynamicTextAnchor Diese Klasse beschreibt einen RedDot Dynamic Anchor (Text oder Bild).
Frame Insert the type’s description here.
ImageElement Diese Klasse beschreibt ein Image-Element einer Seite.
List Diese Klasse beschreibt einen RedDot MultiLink List.
MediaElement Diese Klasse beschreibt ein Media-Element einer Seite.
MultiLink Diese Klasse beschreibt einen RedDot MultiLink (Container or Liste).
Note Diese Klasse beschreibt eine Bemerkung zu einer Seite.
OptionList Diese Klasse beschreibt das Seitenelement Optionsliste.
StandardFieldDateElement Diese Klasse beschreibt ein RedDot Standardfeld Date (type=5).
StandardFieldNumericElement Diese Klasse beschreibt ein RedDot Standardfeld Numeric (type=48).
StandardFieldTextElement Diese Klasse beschreibt ein RedDot Standardfeld (type=1).
StandardFieldUserDefinedElement Diese Klasse beschreibt ein RedDot Standardfeld user defined (type=999).
TextAnchor Insert the type’s description here.
TextElement Diese Klasse beschreibt ein RedDot Textelement (type=31 oder type=32).

These classes offers always the full set of available functions. The most often used, like getting and setting a value are supported directly on Page. If you miss a method on Page, please check these classes directly.

You can always get the element instances of a page with a simple get method, like

OptionList optList = currentPg.getOptionList("content class element name");
optList.selectDefault();

These lines change the option list value on currentPg to it’s default value defined in the content class element. This method is only available on the optList element, but not as special method on Page.

In addition you can ask every page element object for the corresponding content class element. In jRQL they are called TemplateElement like in old version of RedDot CMS (was renamed later to content class elements).

From my most often used elements you can get the underlaying content class element (=tempate element) simply with the  method getTemplateElement():

currentPg.getContainer("content class element name").getTemplateElement();
currentPg.getImageElement("content class element name").getTemplateElement();
currentPg.getList("content class element name").getTemplateElement();
currentPg.getMediaElement("content class element name").getTemplateElement();
currentPg.getMultiLink("content class element name").getTemplateElement();
currentPg.getOptionList("content class element name").getTemplateElement();
currentPg.getStandardFieldDateElement("content class element name").getTemplateElement();
currentPg.getStandardFieldNumericElement("content class element name").getTemplateElement();
currentPg.getStandardFieldTextElement("content class element name").getTemplateElement();
currentPg.getStandardFieldUserDefinedElement("content class element name").getTemplateElement();

Like the template elements shadowing the page element the content class (=template) is backing the page currentPg.  To get the underlaying content class from a page use this method:

You can ask the currentPg itself for its content class:

Page currentPg = project.getPageById("34009");
Template template = currentPg.getTemplate();
System.out.println(currentPg.getTemplateName());

Exception handling and important exceptions

Every unexpected case, from an IO communication problem with RedDot CMS until a request to a page element that does not exist will be thrown as an Exception.

jRQL generally throw a RQLException which contain a explanation text I have written and optional an embedded more specialized excption, e.g. in the case of an IO error. You have to handle this exception in your code every time.

In addition to this general exception there are 35 more specialized sub classes of RQLException covering special problems in your code, often from a logical point of view.

Let me introduce the ElementNotFoundException – it will be thrown if you access a page element which cannot be found in the underlaying content class.

Or the WrongTypeException if you use a method like currentPage. getContainer(“element name”), but the element in the underlaying content class is a list and not a container.

Access only via content class element names

As explained in the getting started post to get a value of a StandardField Text from a page you need to now the name of the corresponding content class element. Times ago a content class was named template and therefore jRQL uses the old names.

What’s the reason for this?

If you have a page with a link (list, container, anchor) you can change the name of that link for the page. After creating a new page every structural element on a page gets the name of the respective content class element.

jRQL has to be independent of this and therefore is rely only on the names of content class elements. This is true even for content elements, like a text element, even you cannot change the name of a text element on a page. This is for consistency only.

Note:
Be careful using content class element names directly in your plugins! Even content class elements needs to be renamed from time to time. Therefore I uses parameters for my plugins with all the needed names of content class elements. The special class ScriptParameters is available to support easy access (needs corresponding content classes).