Monday 11 January 2016

Implement Use-Interface using Sightly in AEM 6.x

Implementing sightly can be basically done with two important APIs (although few others are also available). In my other article I have cover up how you can  Access OSGI ser­vice from the WCMUse-class in Sightlyhere we are going to cover next important one which shows how you can implements the Use-interface in Java and combine your business logic with component file. 
Let’s see Use interface first, later we will jump to code. 
All you need to make sure is to implement public void init(javax.script.Bindings bindings) The initmethod will be called on initialization of the class with a Bindings object that holds all the context objects and any parameters passed into the use-class. Business logic will be present in this method, although you are free to create custom method which will be called from init().
Binding object is an mapping of key/value pairs, all of whose keys are Strings.

Sunday 10 January 2016

Create a OSGI Configuration Listener in AEM 6.1

Following article demonstrate business scenario where you need to execute a job, call a method or simply log when there in change in XYZ OSGI configuration. Taking forward the OSGI Configuration Management and Reading of OSGI Configuration, I will show you how you can create a OSGI Configuration listener. Before that’s take a look at below…
ConfigurationListener[Interface] objects are registered with the Framework service registry and are notified with a ConfigurationEvent object when an event is fired. ConfigurationListenerobjects can inspect the received ConfigurationEvent object to determine its type, the pid of theConfiguration object with which it is associated, and the Configuration Admin service that fired the event.
I have used com.day.cq.wcm.notification.email.impl.EmailChannel service but you can use any service based on your requirements and will read property email.from when their is a change. Let’s get started..
1. Create a Service which Implement ConfigurationListener interface

Indexing Properties and Nodes for AEM 6.0 and 6.1

To index a particular property, create a node directly under your oak:index of type oak:QueryIndexDefinition with the following properties:
name = propertyNames, type String[], value is the name of the property(ies) you want to index
name = type, type String, value = property
name = reindex, type Boolean, value = true
To index entire nodes so that you don’t have to list all their property names (for example, if they are coming from an outside source and you don’t know them all ahead of time), you have to do different things depending on if you are on 6.0 or 6.1. The following steps concern indexing nodes (and their properties) in the DAM, but they should work for general cases:
For 6.1:
  1. In CRXDE Lite, navigate to this path: /oak:index/damAssetLucene/aggregates/dam:Asset. You should see a list of nodes with names that start with “include” and then a number.
  2. To this list, add a new node of type nt:unstructured that follows the same naming convention and a new number one higher than the current highest (for example, if “include7” is the highest number with 7 then make a node with the name “include8”). The name probably doesn’t matter but we don’t tempt fate around here.
  3. Add a property to this node with the name “path” with a String value set to “”, for example: “jcr:content/metadata”.
  4. Click Save All.
  5. Navigate up the tree to /oak:index/damAssetLucene.
  6. Change the value of the “reindex” property on this node to “true”. This should perform a reindex on the repository.
For 6.0:
  1. In CRXDE Lite, find the node /oak:index.
  2. Under the oak:index node, create a new node of type oak:QueryIndexDefinition with the name “damAssetLucene”.
  3. Set the following properties on this new node:
    1. Name: async, type: String, Value: async
    2. Name: compatVersion, type: Long, Value: 1
    3. Name: evaluatePathRestrictions, type: Boolean, Value: true
    4. Name: reindex, type: Boolean, Value: false (you don’t want to trigger a reindex yet!)
    5. Name: type, type: String, Value: lucene
  4. Click Save All.
  5. Under the damAssetLucene node you just created, create a new node of type nt:unstructured with the name “aggregates”.
  6. Click Save All.
  7. Under the aggregates node you just created, create a new node of type nt:unstructured with the name “dam:Asset”.
  8. Click Save All.
  9. Under the dam:Asset node you just created, create a new node of type nt:unstructured with the name “include0”.
  10. Add a property to the include0 node with the name “path” with a String value set to “”, for example: “jcr:content/metadata”.
  11. Click Save All.
  12. Navigate back up the tree to the damAssetLucene node you created earlier.
  13. Change the value of the “reindex” property on this node to “true”. This should perform a reindex on the repository.
The key thing to note here is that you are replicating some of the same node structure on 6.0 that already exists by default on 6.1, but the compatVersion property is set to 2 in 6.1 and must be set to 1 on 6.0.
With the transition to Jackrabbit Oak, a lot of people are still working out what the best practice is for indexing Oak nodes; this may not be the definitive way to do indexing for properties and nodes in AEM, but it is one way we have found that seems to work well.

Installing Bundles by Runmode

If I had a dollar for every bundle configuration I've looked at where there was a little checkbox titled "Enabled", I'd have, like, maybe $31 dollars and I could afford a new Indie Steam game or perhaps 12 of them if I waited for the summer or holiday sales... In reality, I've been on countless projects where the prevailing approach for ensuring a bundle only runs for a specific runmode is to make it configurable via the aformentioned checkbox. While this approach certainly works, there's a much easier and, in my opinion, cleaner and better way to handle this that I think gets overlooked
For starters, consider that you can provide runmode-specific configurations for your bundles via simple naming convention. I'd cover this myself, but Krtisian Wright does an excellent job of doing so here. In short, you'll typically see structures along the following lines:
  • /apps/skynet/config.author
  • /apps/skynet/config.publish
  • /apps/skynet/config.<some-other-runmode>
And, yes, Skynet is being built on top of AEM. You heard it here first... Back on topic, the same naming conventions apply for installation of bundles as well. For example
  • /apps/skynet/install.publish
will have any bundles therein installed only if the current runmode is publish. Also, for what it's worth, you can even chain runmodes together for both the configuration and installation of bundles. For example
  • /apps/skynet/install.publish.staging
will install any bundles underneath so long as the instance's runmode is both publish and staging. For the unaware, yes, you can have as many runmodes as you want for any particular instance. This allows you to set up environment-specific configurations. Further, note that the runmodes "author" and "publish" are just two default runmodes for AEM that have a bunch of predefined configuration set up for you. In fairness, one advantage to using the "Enabled" checkbox approach is that you could then test your bundle on any instance by configuring it. However, configuring bundles directly through Felix instead of doing so via sling:OsgiConfig nodes can open up its own can of worms in the generation of an nt:file and actually overwriting your sling:OsgiConfig with this nt:file if it exists :(. So, for future projects, I highly recommend setting up runmodes for your specific environments and building out your configurations and bundle installation for each exactly as you want them using the above approach.

Chrome Console Magic

Chrome Console Magic
Chrome has many timesaving and neat tools built into it, many of these tools are not necessarily obvious on the surface. This post is a deeper dive into what is available. If you are not familiar with Chrome Dev Tools at all, this post is probably not for you.

$ selectors

Chrome has built-in selectors much like jquery.
On this page you will see 3 divs, two with a selector-test class and one with selector-test id.
There are 4 useful types of $ selectors in Chrome.

$()

$() selects the first matching element. (If jquery is active on the page, it will select all matching elements). It will match classes prefaced with ‘.’, IDs prefaced with ‘#’, or regular elements such as ‘p’, 'div', etc.
Example 1 (in the console type):
 $('.selector-test')
Chrome returns:
  <div class="selector-test">Test selector content (.selector-test)</div>
Example 2:
  $('div')
Chrome returns:
  <div class="selector-test">Test selector content (.selector-test)</div>
The same div is selected in both examples as both the first item with class "selector-test" and the first div on the page.