Wednesday, November 22, 2017

Change File Upload Size

You can use the following instructions to modify the file upload size in AEM

Modify Asset Upload Size


2. Go to the below path:
/libs/dam/gui/content/assets/jcr:content/actions/secondary/create/items/fileupload.

You can change the "SizeLimit" property of the node to tweak the file upload options.

The current size limit is 2 GB default; you can increase it if application is expected to support higher file sizes.

Modify Zip Extraction Size

AEM provides "Unarchiver" workflow process to extract zip files. The extraction of zip is bound to following configurations in workflow step"

1. Number of files in a directory - 100 is default
2. Number of total files in the zip- 10,000 is default
3. Maximum size of extracted folder - 2GB is default

You can increase it from the configuration.

Tuesday, October 17, 2017

Apache - Restricting a path in web server

In case you need to restrict a particular virtual path on Apache, you need to add following code to your httpd.conf or apache2.conf file:

<Location "/bin/path">
AuthUserFile C:/Apache/users
AuthName "Restricted Files"
#AuthGroupFile /dev/null
AuthType Basic
Require valid-user
</Location>

AuthUserFile- is the location of password file. You can define your custom path. The value provided here is just for illustration purpose. For Linux it can look like - "/etc/users"

If you want to provide access to usergroups then you can use AuthGroupFile, otherwise you should comment it.

AuthType- Various methods of authentication are available. It may be any of - None, Basic, Digest and Form.

Creating users for access- Run below command

htpasswd -c /etc/mysite/users mysite-new-user

AuthType Basic is not a secure way for authorization. Instead use Digest method with SSL.

You can also authenticate users from LDAP or DB. Refer the documentation at- https://httpd.apache.org/docs/2.4/howto/auth.html


Sunday, October 8, 2017

OKTA SSO Integration

If you need to integrate OKTA SSO with AEM, you will need following things from the OKTA application-
  1. IDP certificate
  2. Single sign-on URL (also called IDP URL)
  3. Okta Logout URL (If your application need to support logout)

OKTA Configuration

Below are the things which need to be done at OKTA side:
1. Go to Self service App for OKTA
2. Click on Register new application
3. Fill in required details. Below are few important fields which must be configured carefully-
  • SAML Reciept: This is the returning URL to AEM  after successful user authentication in OKTA. This URL is generally in this format- https://youraemsitedomain.com/saml_login 

    It is Frequently found issue that this URL is not setup properly. So while trouble shooting validate that after successful authentication from OKTA user must return to exactly /saml_login page.  Validate this in SAML XML response too. No ending slashes or any other page. If user is not returning to /saml_login then there is an issue at OKTA side or at your web server side. In the most cases, correcting the SAML receipt URL at OKTA side fixes this issue. In worst case, check rewrite rules at your webserver if they are not screwing it up.
  • SAML Audience: This is your AEM domain name. Example value- youraemsitedomain.com    Ensure no http or https or www.
  • SAML Name Id: Use EmailAddress here.

AEM Configuration

Below are the key steps to configure OKTA SSO at AEM side:

1. Create certificate file
     Copy the certificate string in a text file and save it as idp_cert.cert in your local computer

2. Upload certificate in crx under path /etc/key using blow steps
  • Go to crxde
  • Create a node "saml" under /etc/key:
             jcr:primaryType- sling:Folder,
             idp_cert- Binary
        Save the node
  • Double click on binary type for the property name "idp_cert" and upload the certificate file that was created in step 1 above.
     After step 2 - The node should look like this-


3. Now, Go to AEM admin console and navigate to: Tools > Security > Users

  • Open user - "Administrator", Scroll down for Account settings
  • Click on Create KeyStore, Enter a value for the password in both text boxes (Note down this password, this will be required to setup the SAML OSGi configuration)
  • Click on Manage TrustStore. Click on Add Certificate from CER file
  • Click on Select Certificate file, Navigate to idp_cert.cert file that you created in step 1 and uncheck Map Certificate to user
  • Click on Submit.
   Screen should look like this-

   Note down the Alias Value on the left colum. This will be required to setup the SAML OSGi configuration.

4. At Tools > Security > Users
  • Open user - "authentication-service", Scroll down for Account settings
  • Click on Create KeyStore and provide the same password . Click OK. 
    This will initialize the Keystore and Authentication Service to use the certificate you provided earlier. On clicking manage trust store button on the same page, you can see your previously created certificate.

5. Configure Saml Authentication Service
  • Go to /system/console/configMgr
  • Open "SAML 2.0 Authentication Handler"
  • Add required details
6. Configure the Referred filter
  • On the System console configMgr, Open "Apache Sling Referrer filter"
  • Add the Okta domain name e.g. "mysite.okta.com"

Other things you may need to setup this functionality is:
  • Create new user group- for default user group configured in step 5
  • Create CUG for the path (May be this can be skipped, as it worked for me without CUG setup)

This article is specifically articulated for OKTA integration. Refer the Adobe documentation  for integrating SSO with other SAML providers - https://helpx.adobe.com/experience-manager/using/aem63_saml.html

Monday, September 11, 2017

Custom userpicker to select users from a specific group

If you need to customize the userpicker component to allow users to pick a particular user from a specific group, you have to extend the OOTB userpicker component. It uses the UserManager service instance to get the group authorizable and retrieve the group members using getMembers() method thereafter. Refer the sample code for this purpose-


Workflow Customizations | Touch UI

The Scribcopia blog article is a good reference to start with workflow customization in touch UI. In this article, I am going to describe few additional steps which help you to perfect the authoring behavior.

1. Handling Validation of additional fields in start workflow dialog

You need to add in custom java-script clientlibs file with category- "cq.authoring.editor.core,cq.authoring.editor" (Obviously, the two categories will be added separately in your categories multifield property of your clientlibs.)

Below is the sample code to refer on what events you need to handle in your client library code. You need to change it as per your business requirements.

Below things are done in this code:

  • If author selects your custom workflow model- Show additional fields and disable the submit button in order to stop submitting the form without filling the mandatory field(s).
  • The second part of code handles enabling/ disabling of the workflow start button based on author filling out the mandatory field(s).

2. Adding additional fields in start workflow dialog

Please note that the custom class selectors for the additional fields are added in startworkflow.jsp file as mentioned in the Scribcopia blog post. Below is the sample code for the same:

Here two fields are added one of which reviewer is mandatory and the other is scheduled publish time.

3. Customizing User picker drop-down

If you happen to customize the user picker for your reviewer user picker drop-down based on a specific user group, refer this blog post- Group based userpicker.

Sunday, August 27, 2017

Collapsible Multifield

Multifields add length to the dialog UI. To make it easy for authors we can provide feature to collapse on composite fields. Use the layout type as "granite/ui/components/foundation/layouts/collapsible" to achieve this feature.

For this field structure should follow like this:

+ mycollapsible
  - sling:resourceType = "granite/ui/components/foundation/container"
  - jcr:title = "My Collapsible"
  + layout
    - sling:resourceType = "granite/ui/components/foundation/layouts/collapsible"
  + items
    + item1
    + item2

Refer the screenshot below-


After applying this change the dialog should look like this-

AEM Version Tested with: AEM 6.3
Issues Observed: When we use collapsible feature for multi level the values are not saved properly as JSON object. One workaround to this is to use collapsible feature at children level.

Resources: https://docs.adobe.com/docs/en/aem/6-3/develop/ref/granite-ui/api/jcr_root/libs/granite/ui/components/foundation/layouts/collapsible/index.html

Wednesday, July 12, 2017

Developing with git by forking a repository

When collaborating with Git, the “fork and branch” workflow is a common way of collaborating on open source projects  and, also useful for internal project development to give code owners better control on managing code commits from the bunch of developers. Required steps to this workflow are given as below:

First time setup

1. Fork a GitHub repository
Go to the GitHub repository in your browser and Click the Fork button on the upper right-hand side of the repository’s page.

2. Clone the forked repository to your local system
Copy the URL of the forked repository and run the below clone command in a folder at your machine(Where you will at sore the local copy of your repository):
$git clone <git_fork_url>

3. Add a Git remote for the original repository
$git remote add upstream <git_original_url>
4. List Git remote List
$git remote -v

Routine Work for development

1. Create a feature branch in which to place your changes
$git checkout -b feature/<jira-id-title>

2. Make your changes to the new branch.

3. Commit the changes to the branch.
Use the git add and git commit commands as required

4. Sync with latest upstream code
Run below commands on the repo:
a. $git fetch upstream
b. $git merge upstream/develop (for Dev branch merge) or
$git merge upstream/qa (for qa branch merge)

5. Push the branch to GitHub
$git push origin feature/<jira-id-title>

6. Go to the browser and create a pull request from the new branch to the original repo. Please make sure to add reviewers.

7. Clean up after your pull request is merged
a. $git pull upstream develop
b. $git branch-d feature/<jira-id-title>
c. $git push origin develop
d. $git push --delete origin feature/<jira-id-title>

8. Clear history of a repo
git checkout --orphan tmp-main # create a temporary branch
git add -A  # Add all files and commit them
git commit -m 'Initial commit'
git branch -D main # Deletes the main branch
git branch -m main # Rename the current branch to main git push -f origin main # Force push main
branch to Git server

Friday, April 21, 2017

AEM6 | How To DO's

1. Ensuring that component/ servelet works in specific environment only

There are several workarounds to it. But the suggested solution is to bind a configuration policy with your component which might be a service, servlet, job, workflow etc. The declaration looks like this-

@Component(policy=ConfigurationPolicy.REQUIRE)

Now, you need to create configuration settings file for only those environment where you want your component to work i.e. runmode based configuration file. For example if you want your component to work only in authoring environment then create a configuration file for your component under "/apps/{yourProjectCodeRoot}/config.author".

2. Configuration preferences order

Resolution order at startup- 

  1. /apps/*/config
  2. /libs/*/config
  3. crx-quickstart/launchpad/config

Resolution order at runtime- 

  1. Chnage in OSGi console
  2. /apps/*/config
  3. /libs/*/config

3. Runmode preferences order

There are several methods for specifying which run mode to use; the order of resolution is:
  1. sling.properties file
  2. -r option through command line
  3. system properties (-D) in start up script
  4. Filename detection/ Jar name

4. Production Ready Mode

If you start AEM instance with "nosamplecontent" runmode, it will ensure that by default the instance is pre-configured with major security measures.

5. AEM instance behavior to author/ publish

Behavior of an AEM instance is driven by the run mode. For authoring instance- run mode must be set to "author". For publisher instance- run mode must be set to "publish".  "author, publish, samplecontent, nosamplecontent" - are the Installation run modes. They can not be changed after installation.

In addition, the "Day CQ WCM Filter" should be set to "edit" on author and "disabled" on publish instances from the OSGi console or through the OSGi configuration file.

6. Linking SonarQube with Jenkins 

Refer the instruction on the SonarQube website- https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Jenkins

The simple way to integrate the two is - "Analyzing with the SonarQube Scanner for Maven". Follow the instructions on the above link. When setting up the Build profile in Jenkin set the Goal as shown in below snapshot-

7. Accessing AEM logs

You can use this URL- http://{host:port}/system/console/slinglog/tailer.txt?tail=500&name=/logs/error.log

Monday, February 13, 2017

Scrabble Letters as an Array

What is Scrabble Game?

The word board game "Scrabble" vary in the letter distribution of the tiles, because the frequency of each letter of the alphabet is different for every language. As a general rule, the rarer the letter the more points it is worth. Many languages use sets of 102 tiles, since the original distribution of one hundred tiles was later augmented with two blank tiles. In tournament play, while it is acceptable to pause the game to count the tiles remaining in the game, it is not acceptable to mention how many tiles are remaining at any time. Several online tools exist for counting tiles during friendly play.

Below is the useful information for Scrabble programmers-

List of characters in an scrabble game


 It may vary from language to country, below one is for English:

private String[] charList = { "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "F", "F", "G", "G", "G", "H", "H", "I", "I", "I", "I", "I", "I", "I", "I", "I", "J", "K", "L", "L", "L", "L", "M", "M", "N", "N", "N", "N", "N", "N", "O", "O", "O", "O", "O", "O", "O", "O", "P", "P", "Q", "R", "R", "R", "R", "R", "R", "S", "S", "S", "S", "T", "T", "T", "T", "T", "T", "U", "U", "U", "U", "V", "V", "W", "W", "X", "Y", "Y", "Z", };

You can generate it from following two inputs-

String list = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

int[] count = {9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1};

The above list does not include two blank characters, add them separately.

Sunday, February 12, 2017

David Nuescheler's Model

While designing data model for AEM application, one should keep the David Nuescheler's Model in consideration. This is a conceptual theory which tells about basic principles for designing a content repository. Though as per his article mentioned in wiki he says it's his personal view and others may have some objections, but still these are widely accepted in AEM world. This model is divided into seven simple principles-

Rule #1: Data First, Structure Later. Maybe.

Not to worry about a declared data structure in an ERD sense. Initially.
Learn to love nt:unstructured (& friends) in development. Structure is expensive and in many cases it is entirely unnecessary to explicitly declare structure to the underlying storage.
Data constraints like mandatory or type and value constraints should only be applied where required for data integrity reasons.

Rule #2: Drive the content hierarchy, don't let it happen.

The content hierarchy is a very valuable asset. So don't just let it happen, design it. If you don't have a "good", human-readable name for a node, that's probably that you should reconsider. Arbitrary numbers are hardly ever a "good name".
For best performance, the number of child nodes attached to individual nodes in a content repository should generally not exceed 1'000.

Example
I would model a simple blogging system as follows. Please note that initially I don't even care about the respective nodetypes that I use at this point.
1
2
3
4
5
6
/content/myblog
/content/myblog/posts
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping
/content/myblog/comments/iphone_shipping/i_like_it_too
/content/myblog/comments/iphone_shipping/i_like_it_too/i_hate_it
Code samples are intended for illustration purposes only.
think one of the things that become apparent is that we all understand the structure of the content based on the example without any further explanations.
What may be unexpected initially is why I wouldn't store the "comments" with the "post", which is due to access control which I would like to be applied in a reasonably hierarchical way. Using the above content model I can easily allow the "anonymous" user to "create" comments, but keep the anonymous user on a read-only basis for the rest of the workspace.

Rule #3: Workspaces are for clone(), merge() and update().

Explanation
If you don't use clone(), merge() or update() methods in your application a single workspace is probably the way to go.
"Corresponding nodes" is a concept defined in the JCR spec. Essentially, it boils down to nodes that represent the same content, in different so-called workspaces.
JCR introduces the very abstract concept of Workspaces which leaves a lot of developers unclear on what to do with them. I would like to propose to put your use of workspaces to the following to test.
If you have a considerable overlap of "corresponding" nodes (essentially the nodes with the same UUID) in multiple workspaces you probably put workspaces to good use.
If there is no overlap of nodes with the same UUID you are probably abusing workspaces.
Workspaces should not be used for access control. Visibility of content for a particular group of users is not a good argument to separate things into different workspaces. JCR features "Access Control" in the content repository to provide for that.
Workspaces are the boundary for references and query.

Example
Use workspaces for things like:
  • v1.2 of your project vs. a v1.3 of your project
  • a "development", "QA" and a "published" state of content
Do not use workspaces for things like:
  • user home directories
  • distinct content for different target audiences like public, private, local, ...
  • mail-inboxes for different users

Rule #4: Beware of Same Name Siblings.

Explanation
While Same Name Siblings (SNS) have been introduced into the spec to allow compatibility with data structures that are designed for and expressed through XML and therefore are extremely valuable to JCR, SNS come with a substantial overhead and complexity for the repository.
Any path into the content repository that contains an SNS in one of its path segments becomes much less stable, if an SNS is removed or reordered, it has an impact on the paths of all the other SNS and their children.
For import of XML or interaction with existing XML SNS maybe necessary and useful but I have never used SNS, and never will in my "green field" data models.

Example
Use
1
2
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping
Code samples are intended for illustration purposes only.
instead of
1
2
/content/blog[1]/post[1]
/content/blog[1]/post[2]
Code samples are intended for illustration purposes only.

Rule #5: References considered harmful.

Explanation
References imply referential integrity. I find it important to understand that references do not just add additional cost for the repository managing the referential integrity, but they also are costly from a content flexibility perspective.
Personally I make sure I only ever use references when I really cannot deal with a dangling reference and otherwise use a path, a name or a string UUID to refer to another node.

Example
Let's assume I allow "references" from a document (a) to another document (b). If I model this relation using reference properties this means that the two documents are linked on a repository level. I cannot export/import document (a) individually, since the reference property's target may not exist. Other operations like merge, update, restore or clone are affected as well.
So I would either model those references as "weak-references" (in JCR v1.0 this essentially boils down to string properties that contain the uuid of the target node) or simply use a path. Sometimes the path is more meaningful to begin with.
I think there are use cases where a system really can't work if a reference is dangling, but I just can't come up with a good "real" yet simple example from my direct experience.

Rule #6: Files are Files.

Explanation
If a content model exposes something that even remotely smells like a file or a folder I try to use (or extend from) nt:file, nt:folderand nt:resource.
In my experience a lot of generic applications allow interaction with nt:folder and nt:files implicitly and know how to handle and display those event if they are enriched with additional meta-information. For example a direct interaction with file server implementations like CIFS or WebDAV sitting on top of JCR become implicit.
I think as good rule of thumb one could use the following: If you need to store the filename and the mime-type then nt:file/nt:resource is a very good match. If you could have multiple "files" an nt:folder is a good place to store them.
If you need to add meta information for your resource, let's say an "author" or a "description" property, extend nt:resource not the nt:file. I rarely extend nt:file and frequently extend nt:resource.

Example
Let's assume that someone would like to upload an image to a blog entry at:
1
/content/blog/posts/shipping
Code samples are intended for illustration purposes only.
and maybe the initial gut reaction would be to add a binary property containing the picture.
While there certainly are good use cases to use just a binary property (let's say the name is irrelevant and the mime-type is implicit) in this case I would recommend the following structure for my blog example.
1
2
3
/content/blog/posts/shipping/attachments [nt:folder]
/content/blog/posts/shipping/attachments/front.jpg [nt:file]
/content/blog/posts/shipping/attachments/front.jpg/jcr:content [nt:resource]
Code samples are intended for illustration purposes only.

Rule #7: IDs are evil.

Explanation
In relational databases IDs are a necessary means to express relations, so people tend to use them in content models as well. Mostly for the wrong reasons through.
If your content model is full of properties that end in "Id" you probably are not leveraging the hierarchy properly.
It is true that some nodes need a stable identification throughout their live cycle. Much fewer than you might think though. mix:referenceable provides such a mechanism built into the repository, so there really is no need to come up with an additional means of identifying a node in a stable fashion.
Keep also in mind that items can be identified by path, and as much as "symlinks" make way more sense for most users than hardlinks in a unix filesystem, a path makes a sense for most applications to refer to a target node.
More importantly, it is **mix**:referenceable which means that it can be applied to a node at the point in time when you actually need to reference it.
So let's say just because you would like to be able to potentially reference a node of type "Document" does not mean that your "Document" nodetype has to extend from mix:referenceable in a static fashion since it can be added to any instance of the "Document" dynamically.

Example
use:
1
/content/myblog/posts/iphone_shipping/attachments/front.jpg
Code samples are intended for illustration purposes only.
instead of:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Blog]
-- blogId
-- author
[Post]
-- postId
-- blogId
-- title
-- text
-- date
[Attachment]
-- attachmentId
-- postId
-- filename
+ resource (nt:resource)
Purpose of this article is to spread the concept to more audiences reading this Blog. You can read original article here- http://wiki.apache.org/jackrabbit/DavidsModel

Saturday, January 28, 2017

Java Coding - Few Basic Rules

1. Variables Passed by Value, Objects Passed by Reference

In Java, variable method arguments e.g. intString are passed by Value while the objects are passed by reference. Be mindful to it.

2. You can not create object of an abstract class directly

You need to extend this class and implement missing abstract methods (If any). Abstract class may not contain any abstract method if needed so.

3. Java does not support multiple inheritance

Though you can give a hand to it through a class implementing multiple interfaces e.g. class C implements A, B.

CDN | Clearing Cloudflare cache

In order to clear Cloudflare cache automatically via code, follow below steps: 1. Develop Custom TransportHandler Develop a custom Trans...