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.