Search

AEM HUB

Synchronizing the code between AEM Instance and Eclipse

In this post, we will learn how to sync the code between AEM Instance and Eclipse.

Versions Used : AEM -> 6.3 , Eclipse -> Oxygen 3a

We will use AEM Developer tools eclipse plugin to do the sync operation.

Install AEM Developer tools in Eclipse

1) Open eclipse -> Go to Help -> click on Eclipse Marketplace.

EclipseContentSync-1

2) Search for AEM Developer tools and install the plugin.

EclipseContentSync-2

Import AEM maven project into Eclipse

In Project explorer view -> right click and select Import option.

On Import popup window -> select maven -> existing maven projects.

EclipseContentSync-3

Click Next -> browse maven project root directory.

EclipseContentSync-4

Click finish. Now our AEM project is imported into eclipse.

Change the default perspective to AEM perspective

Go to Windows -> perspective -> open perspective -> select AEM -> click open

EclipseContentSync-5

Now we have our project on AEM perspective.

EclipseContentSync-5-1

Convert the maven modules into content and bundle projects

Right click on demo.core module -> configure -> click on convert to Bundle Project.

EclipseContentSync-6

similarly right click on demo.ui.apps module -> select configure -> click on convert to Content Project.

Configure AEM server connector in Eclipse Servers view

To connect eclipse to AEM server click on “no servers are available” link in servers view.

EclipseContentSync-7

Click finish. To edit the server connection details like port , debug port, username and password,  double click on the configured server connector.

EclipseContentSync-9

Edit the properties and save.

To add the bundle and ui.apps package to the configured server -> right click on the server connector -> select Add or Remove.

EclipseContentSync-9.1

Add the bundles from left section to the right using Add button and click finish.

EclipseContentSync-8

Start AEM Instance

EclipseContentSync-11

Once the AEM Instance is started, go to eclipse and start the configured server in the Eclipse.

EclipseContentSync-10

once server is started, the bundle and ui.apps modules will be published to the AEM server.

To verify go to OSGi bundles console and find the demo.core module.

EclipseContentSync-12

If the bundle and ui.apps module is not published to the AEM server, republish the modules by removing all modules and adding them again to the Eclipse server connector.

EclipseContentSync-13

Now the Demo project is deployed to AEM.

Importing the Code changes from AEM Instance to Eclipse

open CRXDE and edit a component html file.

EclipseContentSync-14

Helloword.html file is updated with text “welcome to my world”as shown above.

To get the updated component to eclipse workspace, in eclipse right click on helloworld.html file and click on Import from server.

EclipseContentSync-15

The file will be imported from the AEM Instance to eclipse.

EclipseContentSync-17

Exporting the code changes from Eclipse to AEM

Updated helloword.html with some text in eclipse workspace as shown below.

EclipseContentSync-18

The updated file will automatically synchronized/pushed to AEM Instance.

EclipseContentSync-19

Thanks,

Madhu Samala 

Customizing Granite UI Form Field Component

In this article, I will be showing how to customize a Granite UI Field component with an example.

Use case: Customize the Granite UI Textarea field component to display the number of characters the author has entered in the field.

Granite UI already provided a range of components designed to be used in Touch UI dialogs, and in AEM these form field components are available under /libs/granite/ui/components/foundation/form/*

Every Granite UI Form field component inherits /libs/granite/ui/components/foundation/form/field component.

The Granite UI base field component is composed of three files:

field.jsp: handles the generic processing, labelling, description and calls init.jsp and render.jsp

init.jsp:  provides form value that we will need when rendering the field.

render.jsp: this is where the actual rendering of the field is performed and needs to be overridden for our custom field.

ootb-field-comp

By default all the OOTB Granite UI form components uses the sling:resourceSuperType property to inherit from base field component and overrides the render.jsp.

ootb-textarea-comp

To customize the Textarea component and show the number of characters the author has entered and recommended character count.

Step 1 : overlay or override the OOTB Textarea component into /apps/<project>/<any> folder.

custom-textarea

Step 2 : modify the render.jsp file to show the  recommended character count/no. of characters entered using coral UI character count api below the field.

Ref : https://docs.adobe.com/docs/en/aem/6-1/ref/coral-ui/docs/2.17.0-granite-004/character-count.html

Highlighted is the new code added to the overriden Textarea render.jsp file.

custom-render-jsp

Step3: Assign the custom Textarea component to the dialog field nodes.

custom-field-asign

dialog-char-count

When the maxLength property is set on the field node its shows the assigned max length value else it shows zero.

I have assigned maxLength 20 on short description field and on long description field maxLength property is not set.

shortDesc

longDesc

When the maximum Length has reached it displays error by highlighting the field with red border and the count goes to negative. If the MaxLength is not set then the count will be increased from zero to the number of characters entered.

text-error

Hope this will be useful.:)

Thank you!

Madhu Samala

AEM with Angular2

In this post, I will be sharing my view on Integrating AEM 6.1 with Angular2 and other front-end technologies with an example.

Getting started 

Requirement

AEM component with Angular2.

  • Create an AEM with Angular2 Form Component which displays address suggestions to the user when the user starts typing in the address field and when the user selects one of the address suggestions, it should auto populate the country, state and zip code fields.
  • Leverage Angular2 Http Service to make Ajax calls to google maps API for the address suggestions and address details and display the response using Angular data-binding feature.
  • Leverage AEM Authoring capabilities to make the Form component labels authorable from the component dialog.

AEM Project Setup

Generate the project structure using maven archetype 10 and remove unwanted modules (ui.content, it.tests and it.launcher) for this project. Now we have two modules.

  • Core – contains Java files.
  • ui.apps – contains templates, components, Clientlibs and Angular2 code.

project-layout-allmodules

Maven archetype 10 gives the basic project setup with template, page components and Clientlibs. So I’m directly jumping on to creating the Form component.

Creating the Contact Details Form Component

  • Create an AEM component with the name “contactdetails” under apps/ng2-aem/components/content/.
  • Use bootstrap ui framework to build the Form component UI.
  • Create the Touch UI dialog to make the Form title, description, first name, last name, email and address field’s labels authorable.

Backend Code

ContactDetails POJO class

–  /NG2-AEM.core/src/main/java/com/ng2/aem/core/models/ContactDetails.java

The ContactDetails class contains class members to match the fields specified in the component’s dialog, and also contains their getter and setter methods.

java-model-class

ContactDetailsUse class

–  /NG2-AEM.core/src/main/java/com/ng2/aem/core/components/ContactDetailsUse.java

The ContactDetailsUse is the server-side part of the AEM component and it extends the WCMUsePojo class.

java-wcmuse-class

Contactdetails component HTL file

– apps/ng2-aem/components/content/contactdetails/contactdetails.html

Assuming that you are already familiar with creating component and dialog in AEM, i’m not showing the steps here to create it.

component-basic-html

Component Dialog

component-dialog

Setting up the Angular2 code

Create a folder named “web” under /NG2-AEM.ui.apps/src/main/. This folder will contain our Angular2 code and its build configuration.

Build configuration

Create the following files under web folder.

 package.json

packageJson

Few words about scripts

build   :  invokes the “gulp build” task which then calls the “run-webpack” task to transpile Typescript code into JavaScript and bundle all the JS files into two files and place it into the AEM clientlib folder.

aemsync :  invokes the “gulp aemsync” task to sync the generated JavaScript files under “etc/designs” to running AEM Instance.

watch   :  invokes the “gulp watch” task to watch the for the changes in typescript files, and when there is a change in typescript files it calls the “run-webpack” task.

NPM Packages

Angular 2 is broken into a lot of packages under @angular organization in NPM. We’ll need to install them and also need RxJS, Zone.js, and some shims which Angular2 depends on.

tsconfig.json

tsconfigjson

typings.json

typingsjson

Typings will be downloaded to typings folder and they will be downloaded on “npm install”.

Webpack.config.js

In Webpack config file we specify all the source files where they are available and how to compile and then after compilation where to put them.

Here I’m using webpack to transpile the Typescript code to JavaScript and bundle all the files into two JS files and place them into /etc/designs/ng2-aem/clientlib-site/js Clientlib folder.

  • app.js – contains the application code.
  • pollifills.js – contains the browser supporting libraries.

webpack

gulpfile.js

Gulp JS file contains following tasks.

  • clean   : deletes the JS files from “/etc/designs/Ng2-AEM/clientlib-site/js” clientlib folder before webpack task runs.
  • run-webpack   : executes the webpack config file.
  • aemsync  : sync the JS files created with webpack to running AEM Instance.
  • watch   : watches for the changes made on Typescript files and runs run-webpack task.

gulp

Angular2 Components

Angular2 is component based. Component is the combination of an HTML template and a component class that controls a portion of the screen.

Every component begins with a @Component decorator function that takes a metadata object. The metadata object describes how the HTML template and component class work together.

The selector property tells Angular to display the component’s html inside a custom () tag.

The templateUrl property specifies the URL to an external file containing the html for the view.

ContactDetails Angular2 component

– web/src/app/components/contactdetails.component.ts

ng-comp1

ng-comp2

AddressSuggestion Model class

– web/src/app/models/address-suggestion.ts

address-model

ContactForm Model class

– web/src/app/models/contact-form.ts

conact-model

ContactDetailsService Interface

– web/src/app/services/Icontactdetails.service.ts

service-interface

ContactDetailsService class

– web/src/app/services/contactdetails.service.ts

service-class

Application Module

– web/src/app/app.module.ts

ng-app-module

Application bootstrap

– web/src/main.ts

ng-app-bootsrap

Part2 : Click here to continue

AEM with Angular2 – part2

Modify AEM Component to render Angular2 component content

In the AEM component’s HTL file “contactdetails.html” replace the entire Form html portion with the following Angular2 component selector,

<contact-details message=’${contactForm.contactDetails.contactJson}’>Loading contact form……</contact-details>

this selector will be used to render the Angular2 component’s html on the page, and we will need to pass the AEM dialog authored values as an input to the Angular2 component.

Angular2 root components do not allow to pass inputs using @Input(), so we will pass the dialog values as an selector tag attribute value.

–  /apps/ng2-aem/components/content/contactdetails/contactdetails.html

modified-htl-file

To display the content of Angular2 component we must have a separate .html template file, so create a new file “contactdetails.component.html” in the AEM component and copy the Form html in it. The path of this file need to be assigned to the templateUrl metadata property of Angular2 component.

–  /apps/ng2-aem/components/content/contactdetails/contactdetails.component.html

ng-comp-htm-1

ng-comp-htm-2

ng-comp-htm-3

 

ng-htm-comp-pointing

Modify UI.apps Maven POM file

– /NG2-AEM.ui.apps/pom.xml

Add the following exec maven plugin to the POM file.

ng2-maven-plugin

Building

mvn clean install -PautoInstallPackage

The maven build will invoke the Exec maven plugin which will trigger “npm install” and “npm run build” tasks which then executes the gulp build task which does the whole build process for the Angular2 code.

npm run aemsync : to manually sync the generated js files to running AEM instance without maven build.

Final Project Structure

project-layout-ui.apps

ng2-folder-structure

Output

comp-page-authoring

Drag the component on to the page and author the field labels in the dialog.

page-sugvalues-display1

When the user starts typing in the address field, suggestions will be shown below the field and when the user clicks on one of the address suggestions, the country, state and zip code fields are auto populated.

page-sugvalues-debug

page-values-results

Thank you!

Madhukar Reddy

Junit tests using Mockito & PowerMockito

Contents

Unit Test

Mock

Spy

Difference between Mock and Spy

Difference Between doReturn()/when and When/thenReturn() 

Ways to Initialize the Mocks

Why Mockito does not mock static methods

Mocking a Static Method of an external class

Mocking static void method call 

Mock private methods of a class under test

Invoking private methods from the unit test class

How to use Powermockito so that private void methods calls are skipped

Unit test a constructor and mock the private methods that the constructor calls

Mocking a constructor

Setting a value to private variable using Mockito

Verify

Argument Captor

Throwing an exception

Using matchers

Best Practices

Unit Test

Unit testing is to test methods of one class in isolation. But classes are not isolated. They may use methods from other classes. Those are often referred to as collaborators (external classes). This leads to two major problems:

  • External services might not simply work in a unit testing environment as they require database access or some other external systems.
  • Testing should be focused on the implementation of one class. If external classes are used directly, their behavior is influencing those tests. That is usually not wanted.

This is where we use Mockito and PowerMockito Frameworks.

What is a Mock?

Mockito mock() method is to create a mock (dummy) object of external classes in a JUnit test. When doing unit testing, we are only testing the functionality of the class. It should not be dependent to other classes. That’s why we mock the external classes, or other dependencies.

Two ways to create a Mock Object

  • ServiceUtil mServiceUtil = Mockito.mock(ServiceUtil.class);
  • @Mock ServiceUtil mServiceUtil;

What is a Spy?

A Mockito spy is a partial mock. We can mock a part of the object by stubbing few methods. Calling a method on a spy will invoke the actual method, unless we explicitly stub the method.

Two ways to spy an object

  • List<Productgroup> sListOfproductGroup = Mockito.spy(new ArrayList<Productgroup>());
  • @Spy  List<Productgroup> sListOfproductGroup = new ArrayList<Productgroup>();

Difference between Mock and Spy

Both can be used to mock methods.The difference is that in mock, we are creating a complete mock or fake object.While in spy, there is the real object and we just stub specific methods of it.

When using mock objects, the default behavior of the method when not stub is do nothing. If it’s a void method, then it will do nothing when you call the method or if it’s a method with a return then it may return null.

While in spy objects, since it is a real object, when you are not stubbing the method, then it will call the real method. If you want to mock, then you need to stub it.

Difference Between doReturn()/when and When/thenReturn()

  1.  doReturn()/when and when/thenReturn() are same for mocked objects. None of them call the actual method.
  2.  doReturn()/when and when/thenReturn() have different behavior for spied objects. doReturn()/when – it will not call real method on spied object.              when/thenReturn() – it will call real method on spied object.

Ways to Initialize the Mocks

  1.  Using Mockito.mock()

This is called One-by-one explicit mocking.

Ex:

mock

2) MockitoAnnotations initMocks()

We can initialize all mocks by calling initMocks() method of MockitoAnnotations.

Syntax: MockitoAnnotations.initMocks(this);

mock-ways2

3) Using MockitoJUnitRunner

Another way to initialize mocks is to use @RunWith(MockitoJUnitRunner.class) annotation at the test class level. It initializes mocks annotated with @Mock.

Here usage of MockitoAnnotations.initMocks(Object) is not needed. Mocks are initialized before each test method.

mock-ways3

4) Using MockitoRule

Another way of initializing the mocks is to use the MockitoRule class. It initializes mocks annotated with @Mock. Here usage of MockitoAnnotations.initMocks(Object) is also not necessary.

mock-ways4

5) Using PowerMockRunner

If we are using PowerMockito to mock static or final methods then we need to annotate the class with @RunWith(PowerMockRunner.class). This statement tells JUnit to execute the test using PowerMockRunner. We will use annotation @PrepareForTest which takes the class that needs to be mocked.

mock-ways5

Why Mockito does not mock static methods

The reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime. This means they inherit from the class to mock (that’s what Mockito does). This approaches do not work for static members, since you can’t override them using inheritance.

Mocking a Static Method of an external class

We need to use the PowerMockito.mockStatic to enable static mocking for all static methods of a class. This makes it possible to stub them using the when-thenReturn syntax.

And we don’t use the default JUnit runner when we use PowerMock. PowerMock provides its own runner which we will need to use, specified with the @RunWith annotation. The other annotation we are using @PrepareForTest is used to identify all of the classes that PowerMock will be mocking.

Below steps in setting up a test that mocks a static call.

  • Use the Power Mock runner:

@RunWith(PowerMockRunner.class)

  • Declare the class that we’re mocking:

@PrepareForTest(TagUtil.class)

  • Tell PowerMock the name of the class that contains static methods:

PowerMockito.mockStatic(TagUtil.class);

  • Stub the static method and return a mock value.

when(TagUtil.getTagIds()).thenReturn(tagIds);

Ex:

//External class

Public class TagUtil {

Public static List<String> getTagIds() {

// some code here

}

}

Unit Test:

static-mock

Mocking static void method call

Use PowerMockito doNothing() to mock/stub the static void method calls.

Ex:

static-void-mock

 

Mocking private methods of a class under test

Spy the class with PowerMockito and use PowerMockito doReturn syntax to stub private method of a class.

Ex:

mock-private

Invoking private methods from the unit test class

Use org.powermock.reflect.Whitebox class InvokeMethod() to invoke the private method of a class under test.

Syntax:

Whitebox. invokeMethod(Object instance, String methodToExecute, Object… arguments);

Ex:

invoking-private

Skip private void method call using PowerMockito

Use doNothing() to skip the private method call.

private-method-skip

Unit test a constructor and mock the private methods that the constructor calls

Ex:

In the below ProductUtil class constructor a private method is getting called which I need to stub and return some mock object if the private method returns something or  donothing() if  it is a void private method.

mock-const-void

 

Junit :

@Test

Public void testProductUtilConstructor() throws Exception{

// with below statement private method call cannot not be stubbed, because the productDetail object is not created yet, and it can only be created after the Constructor is called.

PowerMockito.doReturn(propertyMap).when(productUtil, “getTechSpecValues“, Mockito.any(Product.class), Mockito.any(List.class));

// with below statement the call to private method cannot be stubbed

doNothing().when(ProductUtil, “getSubDetails“,Mockito.any(Product.class), Mockito.anyBoolean());

// we call the constructor only after all mocking is done.

productUtil = PowerMockito.spy(new ProductUtil (mProductDetail, BigInteger.ONE,

mTechSpecList, “US”, “en”,”aqType”,true));

}

Solution:

we should not mock a class under test. If the constructor calls a method then the actions of the method should be tested as part of testing the constructor. If the method does stuff that is outside the scope of unit testing, mock the classes that method is using to do the “stuff”.

Mocking a constructor

Mocking a class constructor which has no parameters.

To stub an external class constructor call use PowerMockito whenNew() method and use withNoArguments() method if the constructor has no parameters to pass.

Ex :

ProductTest mProductTest = mock(ProductTest.class);

PowerMockito.whenNew(ProductTest.class).withNoArguments().thenReturn(mProductTest);

Mocking a class constructor which has parameters in 2 ways.

  1. Use PowerMockito whenNew() method and withArguments(…)

ProductDetailSpec mSpecifications = mock(ProductDetailSpec.class);

PowerMockito.whenNew(ProductDetailSpec.class).withArguments(Mockito.any(Product.class),Mockito.any(BigInteger.class),Mockito.anyBoolean()).thenReturn(mSpecifications);

2. Use PowerMockito whenNew() method and withAnyArguments()

ProductTest mProductTest = mock(ProductTest.class);

PowerMockito.whenNew(ProductTest.class).withAnyArguments().thenReturn(mProductTest);

Setting a value to private variable in mockito

Use whitebox setInternalState method to set a value to a private variable.

Listoftechspecs sListoftechspecs = Mockito.spy(new Listoftechspecs());

Whitebox.setInternalState(sListoftechspecs, “techspec”, techSpecList);

Verify

Mockito Verify method is used to verify if a method call is happened or not.

Ex:

verify(mResolver, times(1)).adaptTo(eq(Session.class));

Argument Captor

Argument Captor is used along with verify to capture the arguments for the method call so that they can be asserted.

Throwing an exception

If the method returns a value the syntax would be:

Mockito.when(method).thenThrow(new Exception());

If the method returns void, the syntax is :

Mockito.dothrow(Exception.class).when(instance).method(parameter);

Using matchers

When we want to return a value independently of the parameters content, we can use Matchers.any(Object.class) (where Object may be any custom class we prefer, or if use one of the classical Java types we may use their own methods: anyString(), anyInt(), anyList() …).

Ex:

PowerMockito.whenNew(ProductDetailSpec.class).withArguments(Mockito.any(Product.class), Mockito.any(BigInteger.class), Mockito.anyBoolean()).thenReturn(mSpecifications);

when(mResolverFactory.getServiceResourceResolver(Mockito.anyMapOf(String.class, Object.class))).thenReturn(mResolver);

If we want to do something like mixing parameters whose content we don’t mind while other values may be important, we should combine Matchers.any(Object.class) and Matchers.eq(instance)

Ex:

when(mServiceProxy.getValues(anyString(), eq(“T”))).thenReturn(mClassKeywords);

when(mJcrManager.getNodePath(Mockito.any(Product.class),eq(“path”),eq(“/content/tets/”))).thenReturn(TEST_NODE_PATH);

Another useful method is Matchers.isA(class).

Best Practices

1.Naming conventions: To identify the objects, mocks can start with “m” and spy object with “s”.

Ex:

Product mProduct = mock (Product.class);

Product sProduct = spy (new Product());

2. Don’t mock your model

Simply use your model class over mocking it.

Use:

Product Product = new Product ();

Product.setId (“123”);

Instead Of:

Product mProduct = mock (Product.class);

When(mProduct.getId()).thenReturn(“123”);

3. If we are using the same mock in many tests, then put the mock creation into @Before method. We can create a “basic” mock in setup () and add more mocked behavior to it in the individual test cases. Setup () gets called before each test, so you get fresh objects in each test.

Ex: In below case salesChannels object is used in two test methods

best-practice

 

4. Use the correct assertion method.

Use assertTrue(class.somethod());

Instead of using assertEquals(true, class.someMethod());

5. Declare all the mock objects as private.

6. Do not print anything out in unit tests.

7. Create unit tests that target exceptions.

 

CERTIFICATION : – AEM Run Mode

  1. Which is OOTB run mode applied at the time of installation of AEM instance?
    1. nosamplecontent
    2. author
    3. replicate
    4. loadsamplecontent
  2. How do you specify the osgi config of a java class in Publish runmode ?
    1. /apps/system/config/org.apache.felix.webconsole.internal.servlet.OsgiManager jcr:primary type= sling:osgiConfig
    2. /apps/system/config/org.apache.felix.webconsole.internal.servlet.OsgiManager.config jcr:primary type= sling:osgiConfig
    3. /apps/system/config/org.apache.felix.webconsole.internal.servlet.OsgiManager.config jcr:primary type= nt:file
    4. /apps/system/config/org.apache.felix.webconsole.internal.servlet.OsgiManager.properties jcr:primary type= nt:file
  3. You add “sling.run.modes=pubish” in sling.properties and start the instance using the command “java -jar aem-6-p4502.jar -r author”, In which mode will the instance start?
    1. Author
    2. Publish
    3. Due to conflict in the run modes, AEM will not start
    4. Both Author and Publish
  4. What is the correct order of precedence to set up run modes in AEM (from left to right,left being highest)
    1. system property,sling property,jar file
    2. jar file,sling property,system property
    3. sling property,jar file,system property
    4. jar file,system property,sling property
  5. Which three AEM jar names will start AEM in author mode?(choose three)
    1. cq5-author-4502.jar
    2. aem-publish.jar
    3. quickstart-4502.jar
    4. cq5-author-p4502.jar

 

Write/Read Binary data into/from JCR Node.

Write Binary Data : 

We can use Node API classes ValueFactory and Value to store binary data into JCR. ValueFactory can be used to create Binary object from InputStream and Value object from binary object.

[code language=”java”]

String html = "<html><head></head><body>
<h1>Welcome</h1>
</body></html>";
InputStream stream = new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8.name()));

ValueFactory factory = session.getValueFactory();
Binary binary = factory.createBinary(stream);
Value value = factory.createValue(binary);
Node node = // create node object;
node.setProperty("jcr:data", value);
node.getSession().save();

[/code]

Read Binary Data:

[code language=”java”]
ValueMap properties = getProperties();
properties.get("jcr:data", InputStream.class);
html2 = IOUtils.toString(properties.get("jcr:data", InputStream.class), "UTF-8");
[/code]

Example :

[code language=”java”]
package com.demoportal.aem.models.component;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import org.apache.commons.io.IOUtils;
import org.apache.sling.api.resource.ValueMap;
import com.adobe.cq.sightly.WCMUsePojo;
public class BinaryJcrData extends WCMUsePojo{
String html2;
@Override public void activate() throws Exception {
/* Write binary data into node */
String html = "<html><head></head><body>
<h1>Welcome</h1>
</body></html>";
InputStream stream = new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8.name()));
ValueFactory factory = getResourceResolver().adaptTo(Session.class).getValueFactory();
Binary binary = factory.createBinary(stream);
Value value = factory.createValue(binary);
Node node = getResource().adaptTo(Node.class);
node.setProperty("jcr:data", value);
node.getSession().save();

/* Read Binary data from JCR node */
ValueMap properties = getProperties();
properties.get("jcr:data", InputStream.class);
html2 = IOUtils.toString(properties.get("jcr:data", InputStream.class), "UTF-8");
}
public String getHtml2() {
return html2;
}
}
[/code]

AEM 6.2 User Migration

AEM Instance migration  is common in real world , Package manager does help when you want to move users and groups privileges from one AEM instance to another.

User Migration Steps :

  1. Go to package manager
  2. Create a package for user migration and add below filters and rules.
    • Add filter :  /home/users
    • Exclude Tokens : AEM implemented user token based authentication , all tokens will be stored under appropriate user node as rep:token node type.So we have to exclude tokens from package otherwise CRX will not allow to install package and throws javax.jcr.nodetype.ConstraintViolationException Exception.
    • Exclude Admin & Anonymous users : CRX doesn’t allow to move or delete admin users,As these users has lockable node property hence cannot be copied on destination instance.
    • Add rep:policy : All  Users ,resource based permissions will be stored in rep:policy nodes ,So add root rep:policy user permission node to package.migration
    1. Click save.
    2. Build the package and download.
  3. Unzip the package and open META-INF/vault/filter.xml in a text editor
    Add mode=”merge” to the filter tag, for example:
    [code language=”xml”]
    <?xml version="1.0" encoding="UTF-8"?>
    <workspaceFilter version="1.0">
    <filter root="/home/users" mode="merge">
    <exclude pattern="/home/users/a/admin"/>
    <exclude pattern="/home/users/a/anonymous"/>
    </filter>
    </workspaceFilter>
    [/code]
  4. re-zip the package and install in new AEM instance .

Run Modes in AEM

Run modes in AEM allow you to configure AEM instances for specific purposes.
For example, We can configure environment specific OSGI Services meta data manually from felix console, But the problem here is whenever new build is deployed the OSGI meta data reset to default values , so again we have to configure. Instead of doing manually in felix console, we can create run mode config nodes in repository, sling will take these configuration automatically when we start the instance or config node update  based on run mode values.

Topics :

Run Mode types in AEM:

There are two types of run modes.

  1. Standard run modes – author,publish,samplecontent,nosamplecontent
  2. Custom run modes –  dev,qa,stage,prod ..etc.

Standard run modes set up:

We can configure standard run modes directly by renaming jar file ,Standard run modes are used at installation time and then fixed for the entire lifetime of the instance, they cannot be changed.

The naming convention to for AEM 5.6.1 and later is:

aem-<optional-version-or-indentifier>-<standard-run-mode>-<port-number>

1. author – Run mode for author instance.
2. publish – Run mode for publish instance.
3. samplecontent – Run mode will install sample content.
4. nosamplecontent – Run mode will not install sample content.

Custom run modes set up:

We can define custom run modes different ways ,below are ways .

Using the sling.properties file :

The sling.properties file can be used to define the required run mode:

  1. Edit the configuration file:
    <cq-installation-dir>/crx-quickstart/conf/sling.properties
  2. Add the following properties; the following example is for author:
    sling.run.modes=author

Using the  -R option :

A custom run mode can be activated by using the -r option when launching the quickstart. For example, use the following command to launch a AEM instance with run mode set to dev.

java -jar cq-56-p4545.jar -r dev

Using a system property in the start script:

  • A system property in the start script can be used to specify the run mode.
    For example use the following to launch an instance as a production publish instance located in the US:
    -Dsling.run.modes=publish,prod,us

Order of precedence of run modes:

Here my question is what happens if we did all above custom run mode configuration at a time,which one will take precedence .

below are the order of precedence of run modes.

  1. Start jar (by double clicking) – In this you do not have option to set run mode in sling.properties, start script first time. JAR name takes precedence.
  2. Unpack jar and specify run mode as system properties in start script – JAR name doesn’t comes to picture here. In this you do not have option to set run mode in sling.properties. System properties takes precedence.
  3. Even if we change run mode in JAR name, it doesn’t changes the installation time run mode. For custom run mode, JAR file name is not applicable. Order of precedence is sling.properties -> specifying -r option (command line jar option) -> system properties (start script).

Read Sling run modes in Java:

We can read sling run modes directly from SlingSettingsService OSGI service.

[code language=”java”] import org.apache.sling.settings.SlingSettingsService;[/code]

[code language=”java”]@Reference
private SlingSettingsService slingSettingsService;[/code]

[code language=”java”]slingSettingsService.getRunModes(); [/code]

 

Powered by WordPress.com.

Up ↑