The best way to allow communication between two AEM instance is by:
- Exposing a service from the AEM instance which acts a source of information (say Source-AEM)
- Consuming the exported service in the required remote AEM (Consumer-AEM).
In case, you have a use-case where:
- A Service cannot be exposed via source AEM
- A utility needs to be deployed in Consumer-AEM to access Source-AEM’s information
Then, you can use the following steps to achieve the same.
Please note: AEM does not allow remote connection OOTB. Hence, we would be embedding jcr2dav bundles. No performance testing has been conducted for the shared code.
Step-1: Create a user in Source-AEM Instance.
Create a user in source-AEM Instance with bare minimum access needed by the utility.
Step-2: Add dependencies to your maven project
Add following dependencies to the maven project of the utility.
<dependency> | |
<groupId>org.apache.jackrabbit</groupId> | |
<artifactId>jackrabbit-jcr2dav</artifactId> | |
<version>2.4.0</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.jackrabbit</groupId> | |
<artifactId>jackrabbit-jcr2spi</artifactId> | |
<version>2.4.0</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.jackrabbit</groupId> | |
<artifactId>jackrabbit-spi2dav</artifactId> | |
<version>2.4.0</version> | |
<scope>provided</scope> | |
</dependency> |
Since, the above bundles are not available in AEM, embed dependency for the above bundles in your pom.xml.
<plugin> | |
<groupId>org.apache.felix</groupId> | |
<artifactId>maven-bundle-plugin</artifactId> | |
<extensions>true</extensions> | |
<configuration> | |
<instructions> | |
<!– <Embed-Dependency> artifactId1, artifactId2;inline=true </Embed-Dependency> –> | |
<Export-Package> | |
blog.techrevel.service | |
</Export-Package> | |
<Embed-Dependency> | |
jackrabbit-jcr2dav,jackrabbit-jcr2spi,jackrabbit-spi2dav</Embed-Dependency> | |
<Embed-Transitive>true</Embed-Transitive> | |
<Sling-Model-Packages> | |
blog.techrevel | |
</Sling-Model-Packages> | |
</instructions> | |
</configuration> | |
</plugin> |
Step-3: Access source AEM instance from utlity.
Create an instance of “Jcr2davRepositoryFactory” to access the source AEM Instance.
package blog.techrevel.servlet; | |
import java.io.IOException; | |
import java.util.HashMap; | |
import java.util.Map; | |
import javax.jcr.Node; | |
import javax.jcr.NodeIterator; | |
import javax.jcr.Repository; | |
import javax.jcr.RepositoryException; | |
import javax.jcr.Session; | |
import javax.jcr.SimpleCredentials; | |
import javax.jcr.query.Query; | |
import javax.jcr.query.QueryManager; | |
import javax.servlet.Servlet; | |
import javax.servlet.ServletException; | |
import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory; | |
import org.apache.sling.api.SlingHttpServletRequest; | |
import org.apache.sling.api.SlingHttpServletResponse; | |
import org.apache.sling.api.servlets.SlingSafeMethodsServlet; | |
import org.osgi.service.component.annotations.Component; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
@Component(service = Servlet.class, property = { "sling.servlet.paths=/bin/testRemoteConnection", | |
"sling.servlet.methods=GET" }) | |
public class RemoteConnectionServlet extends SlingSafeMethodsServlet { | |
private static final Logger LOG = LoggerFactory.getLogger(RemoteConnectionServlet.class); | |
@Override | |
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) | |
throws ServletException, IOException { | |
resp.setContentType("text/html"); | |
try { | |
//Connect to repository | |
Jcr2davRepositoryFactory repoFactory = new Jcr2davRepositoryFactory(); | |
Map<String, String> params = new HashMap<String, String>(); | |
params.put("org.apache.jackrabbit.repository.uri", "http://localhost:4502/crx/server"); | |
Repository repository = repoFactory.getRepository(params); | |
Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()), "crx.default"); | |
//Execute Query | |
QueryManager qm = session.getWorkspace().getQueryManager(); | |
String stmt = "select * from [cq:Component] where isdescendantnode('/apps')"; | |
Query q = qm.createQuery(stmt, Query.JCR_SQL2); | |
NodeIterator results = q.execute().getNodes(); | |
while (results.hasNext()) { | |
Node node = (Node) results.next(); | |
resp.getWriter().write("<br />" + node.getPath()); | |
} | |
session.logout(); | |
} catch (RepositoryException e) { | |
LOG.error("Exception while connecting to AEM", e); | |
} | |
} | |
} |
For the sample code, access the servlet via URL (http://<Processor-AEM-HOST:Processor-AEM-port>/bin/testRemoteConnection), to get list of all components below “/apps/” folder on Source-AEM Instance.