Thursday, June 14, 2012

How to Rotate Logs in CQ / WEM

Use Case:

  • Rotate all logs in CQ
  • Logs are taking a lot of space in file system
Solution:

Till CQ5.4

There are different kind of logs in CQ. Please refer http://www.wemblog.com/2012/01/how-to-change-different-log-locations.html for that

Here is process to rotate all logs,

CQ Logs:

crx-quickstart/logs/error.log :

You can rotate error log using sling:OsgiConfig under /libs/sling/config/org.apache.sling.commons.log.LogManager. Please override this under /apps/sling/config/org.apache.sling.commons.log.LogManager. You can additionally have environment specific configuration as config.author or config.publish










crx-quickstart/logs/request.log and crx-quickstart/logs/access.log:


CRX Log:

crx-quickstart/logs/crx/error.log

You can rotate CRX log through configuration in /crx-quickstart/server/runtime/0/_crx/WEB-INF/log4j.xml by changing configuration of 

<appender name="error" class="org.apache.log4j.RollingFileAppender">
        <param name="File" value="crx-quickstart/logs/crx/error.log"/>
        <param name="maxFileSize" value="10MB"/>
        <param name="maxBackupIndex" value="20"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{dd.MM.yyyy HH:mm:ss} *%-5p* %c{1}: %m (%F, line %L)%n"/>
        </layout>
    </appender>

/crx-quickstart/logs/{stdout,stderr}.log

These logs are not controlled by sling or log4j. You have to use apache log rotate utilities to do this. You might have to do following to rotate these logs (By default they are not rotated)

After
export CQ_LOGDIR
CQ_LOG="${CQ_LOG:-"$CQ_LOGDIR/startup.log"}"

------- ADD ------

CRX_LOG_STDOUT="${CQ_LOG:-"$CQ_LOGDIR/../../logs/stdout.log"}"
export CRX_LOG_STDOUT

CRX_LOG_STDERR="${CQ_LOG:-"$CQ_LOGDIR/../../logs/stderr.log"}"
export CRX_LOG_STDERR

And change your rotate option as,

exec $jvmExe 2>&1 | /usr/sbin/rotatelogs "$CQ_LOG.%Y%m%d" 86400
| /usr/sbin/rotatelogs "$CRX_LOG_STDOUT.%Y%m%d" 86400 | /usr/sbin/rotatelogs "$CRX_LOG_STDERR.%Y%m%d" 86400

That mean rotate both log after 86400 second (1 day).


Server Logs

crx-quickstart/server/logs/{access,startup}.log

Server logs can not be rotated at sling level. You need to rotate these logs at OS level using logrotate utility similar to http://httpd.apache.org/docs/2.0/programs/rotatelogs.html

For this in serverctl script you can do following (Adjust log file location accordingly),

After
export CQ_LOGDIR
CQ_LOG="${CQ_LOG:-"$CQ_LOGDIR/startup.log"}"

------- ADD ------

CQ_LOG_ACCESS="${CQ_LOG:-"$CQ_LOGDIR/access.log"}"
export CQ_LOG_ACCESS

And change your rotate option as,

exec $jvmExe 2>&1 | /usr/sbin/rotatelogs "$CQ_LOG.%Y%m%d" 86400
| /usr/sbin/rotatelogs "$CQ_LOG_ACCESS.%Y%m%d" 86400

That mean rotate both log after 86400 second (1 day).

If you do not have logrotate utility, OOTB CQ support rotation based on size (Not on date or number), For that go to /crx-quickstart/server/etc/server.xml and add following line

<log-file>
<log-file-name>logs/access.log</log-file-name>
<log-max-file-size>20MB</log-max-file-size>
</log-file>

<log-file>
 <log-file-name>../logs/server.log</log-file-name>
 <log-max-file-size>20MB</log-max-file-size>
</log-file>

Launchpad Logs

crx-quickstart/launchpad/logs/error.log

You can configure launchpad error log using felix configuration or creating a custom configuration in crxde may be under /apps/sling/config. Please see http://sling.apache.org/site/logging.html for more information. You can also control sling logs rotation though /crx-quickstart/launchad/sling.properties

Look for, following properties
org.apache.sling.commons.log.file.number=5
org.apache.sling.commons.log.file.size='.'yyyy-MM-dd
org.apache.sling.commons.log.file=${sling.home}/logs/error.log




Dispatcher log:

For dispatcher log you have to use http://httpd.apache.org/docs/2.0/programs/rotatelogs.html (Similar to server log). Something like

DispatcherLog '|/usr/local/apache/bin/rotatelogs <Path-to-your-log>/logs/%Y-%m-%d-dispatcher.log 86400'

http://dev.day.com/content/kb/home/Dispatcher/faq-s/SetupDispatcherLogRotation.html


CQ5.5

Good thing about CQ5.5 is there is not different locations to control log rotation. You can control all log rotations through sling configuration http://sling.apache.org/site/logging.html. One thing to note here is, unlike CQ5.4 ../logs/<your-log> will point to logs folder under CQ root and not under /crx-quickstart/logs. If you want your logs to go under /crx-quickstart/logs you have to use log location as logs/<your-log> in sling configuration.

It is always recommended to modify your log configuration under /apps/<Path>, That way you can port it to different environment.

Some more reference 



Note: For OS level log rotation, You can use any log rotation you want and give path to CQ log files.

You can try this option as well, If log rotate utility option is not working after config through serverctl.

$NOHUP $jvmExe | /usr/sbin/rotatelogs "$CQ_LOG.%Y%m%d" 86400>> /dev/null 2>&1

Thursday, June 7, 2012

How to add a custom Login Module in CQ / AEM

Use Case:

1) You want to create a custom login module in CQ / AEM
2) You already have a custom login module in CQ5.4 and integrate it with CQ5.5

Prerequisite: Please check http://dev.day.com/content/kb/home/cq5/CQ5Troubleshooting/cq55prerelease-installandconfigchanges.html

Solution:

CQ 5.6 and less

Any custom login module should be added in CQ5.6 and less as a JAAS module. That mean CQ should have access to module during load time.

Here is set of steps you might have to do to create custom login module

1) Create a OSGI bundle with class that extend Jackrabbit AbstarctLoginModule (Example http://wemcode.wemblog.com/custom-login-module)

2) Create bundle as frangment bundle attached it to com.day.crx.sling.server



<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>!com.day.crx.core.token,!org.apache.jackrabbit.*,*</Import-Package>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>....... Package you want to export .... </Export-Package>
<Fragment-Host>com.day.crx.sling.server</Fragment-Host>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-Description>${project.description}</Bundle-Description>
<Bundle-Version>${project.version}</Bundle-Version>
<Include-Resource>lib=${basedir}/lib</Include-Resource>
<Bundle-ClassPath>
.,
lib/<Your custom jar file>.jar,
</Bundle-ClassPath>
</instructions>
</configuration>
</plugin>

3) Deploy and start your bundle as start level 15. You can do following things for that

curl -u admin:admin -T <Your custom module bundle>.jar http://<host>:<port>/apps/<Your path>/install/15/<Your login module>.jar

Or


<profiles>
<profile>
<id>install-packages</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.sling</groupId>
<artifactId>maven-sling-plugin</artifactId>
<executions>
<execution>
<id>install-package</id>
<goals>
<goal>install</goal>
</goals>
<configuration>
<slingUrl>${crx.url}/system/console/install</slingUrl>
<user>${crx.user}</user>
<password>${crx.password}</password>
<bundleStartLevel>15</bundleStartLevel>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

4) Change repository.xml 

Open the file crx-quickstart/repository/repository.xml (on the server's filesystem) and remove the <LoginModule>...</LoginModule> element.
Find the <SecurityManager> element and add the WorkspaceAccessManager as shown below:
<SecurityManager class="com.day.crx.core.CRXSecurityManager">
<WorkspaceAccessManager class="org.apache.jackrabbit.core.security.simple.SimpleWorkspaceAccessManager"/>
<UserManager class="com.day.crx.core.CRXUserManagerImpl">
<param name="usersPath" value="/home/users"/>
<param name="groupsPath" value="/home/groups"/>
<param name="defaultDepth" value="1"/>
</UserManager>
</SecurityManager>

5) Create custom jaas config

Now create the file crx-quickstart/conf/jaas.conf. In this file you would have something like this:

com.day.crx {
<Your login Module class name> sufficient
com.day.crx.core.CRXLoginModule sufficient;
};

6) Change start up script

Update your crx-quickstart/bin/start script with this jvm parameter (Replace /path/to/your/jaas.conf with the real path to the jaas.conf file):
-Djava.security.auth.login.config=/path/to/your/jaas.conf

7) Restart your CQ

Note: if you already have Non osgi version of your custom login module, You can use http://www.wemblog.com/2012/04/how-to-integrate-3rd-party-jar-file-in.html to convert to OSGI bundle. Make sure that you follow step 2.

To debug custom login module, you can follow steps mention in http://www.wemblog.com/2011/09/how-to-set-up-debug-mode-for.html

Note that LDAP login module com.day.crx.security.ldap.LDAPLoginModule in CQ is good example of custom Login Module.

AEM / CQ 6

From CQ6 onward, Login module can now be configured as pluggable login module in OSGI. To implement Login Module in CQ6 onward you can

Option 1:

implement org.apache.sling.jcr.jackrabbit.server.security.LoginModulePlugin Here is example of Pluggable Login Module with Authentication handler http://svn.apache.org/repos/asf/sling/trunk/bundles/auth/form/src/main/java/org/apache/sling/auth/form/impl/

More info: https://sling.apache.org/documentation/the-sling-engine/authentication/authentication-authenticationhandler/form-based-authenticationhandler.html

Option 2:

You can also use OAK external Login Module https://github.com/apache/jackrabbit-oak/tree/trunk/oak-auth-external To create custom login module (Which you register and service) as well. Example of that would be LDAP Login Module in AEM6 https://github.com/apache/jackrabbit-oak/tree/trunk/oak-auth-ldap

Here is one more example of how to use this in AEM 6 onward: https://helpx.adobe.com/experience-manager/using/oak-login.html


You do not have to restart your instance after creating custom login module in AEM 6.

Saturday, June 2, 2012

How to add a new supported language in CQ / WEM

Use case: 

  • You want to add new language to CQ
  • Change display language options in translator grid
  • Change language name and default countries 

Solution:

You can access translator UI in CQ with following URL http://<HOST>:<PORT>/libs/cq/i18n/translator.html



Create new language location for Dictionary

Go to CRXDE lite (or your favorite JCR browser) and add this structure (assuming /apps/myproject/i18n as a typical location for custom apps):
/apps/myproject/i18n [sling:Folder]
    - de [nt:unstructured] [mix:language]
        + jcr:language = de
    - fr [nt:unstructured] [mix:language]
        + jcr:language = fr
Then reload the translator and the path /apps/myproject/i18n should show up in the drop-down at the top.
Note: the translator will only save translations for languages that are actually present underneath the path (e.g. /apps/myapp/i18n), others will be skipped.

Change List of Languages Display in Grid

To change what languages are shown in the translator's grid, create a multi-value string property /etc/languages/languages (node structure must be created), containing the iso language codes (e.g. ["de", "fr", …]). The default is hard coded in the translator and maps the ootb CQ languages: ['de', 'fr', 'it', 'es', 'ja', 'zh-cn']


Add supported language in WCM

  • You need to overlay/overwrite /libs/cq/security/widgets/source/widgets/security/Preferences.js to change the list of available languages (used in security admin)
  • and overlay /libs/cq/security/content/tools/userProperties (inside change language list under items/common/items/lang/options - similar dialog to Preferences.js) (used for user drop-down in the top right on admin consoles)
  • Then you need to add the new language somewhere in the repo, e.g. /apps/yourapp/i18n, following the layout as under /libs/wcm/core/i18n (see also the above section on the translator UI). Stuff under /libs must not be changed!
Here is a sample package:
  • adds /apps/test/i18n with translation of "New..." in zh-cn ("simplified") and zh-tw ("traditional") languages
  • overlays /apps/cq/security/content/tools/userProperties and /apps/cq/security/widgets/source/widgets/security/Preferences.js to add the zh-tw language
  • to check, set the current user's language to "Traditional Chinese" and look in the siteadmin: the first button in the toolbar should now be "traditional" instead of "New..."
change language name and default country 

Note: since 5.5 load 21
This means:
  • language titles
  • country names
  • default countries (for codes like "en", "de", etc.)
A language list is stored under /libs/wcm/core/resources/languages. It can be overlayed by copying it to /apps/wcm/core/resources/languages and changing or extending the list there. If you do so, also change the configuration of the language manager com.day.cq.wcm.core.impl.LanguageManagerImpl: set langmgr.list.path = /apps/wcm/core/resources/languages at 
http://localhost:4502/system/console/configMgr/com.day.cq.wcm.core.impl.LanguageManagerImpl.

The default countries, which come into play when resolving the country for a language code such as "en" ("en_GB" would be such a default country), and in turn for displaying flags in the UI, are configured in this list as well. A property defaultCountry on a language node must contain the full code, such as "ja_jp", which would define "jp" as default country for "ja".

Information is provided by Alexander Klimetschek  from Adobe. Many thanks to him.