Parlons de l'extraction, de la transformation et du chargement, également appelés ETL. Si vous êtes un professionnel AEM, c'est quelque chose que vous avez déjà traité. Il peut s'agir de produits, de biographies d'utilisateurs ou d'emplacements de magasins.
Les parties d'extraction et de transformation peuvent différer en fonction de votre source et de vos besoins. La partie chargement se fera presque toujours dans AEM. Bien qu'il puisse y avoir plusieurs façons de le faire, parlons de ce qui est prêt à l'emploi pour vous.
Sling Post Servlet
En tant que développeur AEM, le Sling Post Servlet est quelque chose que vous devriez connaître. En particulier, il existe une opération d'importation. Cela nous permet de faire ce qui suit :
curl -L https://www.boredapi.com/api/activity | curl -u admin:admin -F":contentFile=@-" -F":nameHint=activité" -F":operation=import" -F":contentType=json" http://localhost:4502/content/mysite/us/en/jcr:content/root/container
Vous pouvez l'exécuter plusieurs fois. Vous obtiendrez des nœuds activity_*
sous /content/mysite/us/en/jcr:content/root/container
. Cela suppose que la source est déjà dans le format que vous désirez. Cela signifie que vous avez déjà effectué la partie transformation.
Et l'opération d'importation peut traiter des structures JSON plus complexes, même XML. Voici une sortie possible qui pourrait être fournie par une transformation :
{ "jcr:primaryType": "cq:Page", "jcr:content": { "jcr:primaryType": "cq:PageContent", "jcr:title": "Ma page", "sling:resourceType": "monsite/composants/page", "cq:template": "/conf/mysite/settings/wcm/templates/page-content", "racine": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "monsite/composants/conteneur", "layout": "responsiveGrid", "récipient": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "monsite/composants/conteneur" } } } }
Enregistrez-le dans un fichier nommé mypage.json
et exécutez la commande curl
suivante.
curl -u admin:admin -F":nom=ma-page" -F":contentFile=@mypage.json" -F":operation=import" -F":contentType=json" -F":replace=true" -F":replaceProperties=true" http://localhost:4502/content/mysite/us/en
Et boum ! Vous avez une page instantanée. Cette fois, au lieu de :nameHint
j'ai utilisé les propriétés :name
et :replace
. Exécuter à nouveau cette commande mettra à jour la page. La partie de chargement devient vraiment triviale et vous n'avez qu'à vous soucier de l'extraction et de la transformation. Heureusement, il est open source. Vous n'aurez pas à faire de décompilation aujourd'hui ! Lisons la fonction doPost de l'implémentation. Il y a trop de goodies dans lesquels nous pourrions plonger. Restons concentrés. Nous recherchons pour l'opération d'importation. L'avez-vous trouvé ?
Vous auriez dû vous retrouver avec la fonction doRun de ImportOperation.java
. C'est là que tous ces paramètres de requête des commandes curl ci-dessus entrent en jeu. Descendez plus bas. Vous trouverez un appel à ContentImporter.importContent(Node, String, String, InputStream, ImportOptions, ContentImportListener). Pouvez-vous trouver son implémentation ?
Enfin, vous devriez vous retrouver avec l'implémentation DefaultContentImporter.java. Un composant OSGi qui implémente l'interface ContentImporter
.
Utilisation par programme de l'importateur de contenu
Oui ! Faire des choses par programme . Maintenant que nous savons que le ContentImporter
est disponible en tant que composant OSGi, tout ce dont nous avons besoin est :
@Reference private ContentImporter contentImporter;
Et en supposant que vous ayez votre contenu via InputStream
nous pouvons importer le contenu sous n'importe quel nœud. À titre d'exemple, j'utilise le SimpleServlet
généré dans le cadre de l'AEM Maven Archtype. J'utilise Lombok pour accélérer un peu les choses.
@Component(service = { Servlet.class }) @SlingServletResourceTypes(resourceTypes = "monsite/composants/page", méthodes = HttpConstants.METHOD_GET, extensions = "txt") @ServiceDescription("Servlet de démonstration simple") @Slf4j la classe publique SimpleServlet étend SlingSafeMethodsServlet { privé statique final long serialVersionUID = 1L; @Référence privé ContentImporter contentImporter; @Passer outre DoGet void protégé (demande SlingHttpServletRequest finale, réponse finale SlingHttpServletResponse) jette IOException { final MyContentImportListener contentImportListener = new MyContentImportListener(); nœud de nœud final = request.getResource().adaptTo(Node.class); if (nœud != null) { finale MyImportOptions importOptions = MyImportOptions.builder() .overwrite(true) .propertyOverwrite(true) .construire(); essayez (InputStream inputStream = IOUtils.toInputStream("{"foo":"bar"}", StandardCharsets.UTF_8)) { this.contentImporter.importContent(node, "ma-structure-importée", "application/json", inputStream, importOptions, contentImportListener); } catch (final RepositoryException e) { log.error(e.getMessage(),e); } } response.setContentType("text/plain"); response.getWriter().println(contentImportListener); } @Constructeur @Gettre classe finale statique privée MyImportOptions étend ImportOptions { enregistrement booléen final privé ; autoCheckout booléen final privé; écrasement booléen final privé ; private final boolean propertyOverwrite; @Passer outre public boolean isIgnoredImportProvider (extension de chaîne finale) { return false; } } @Gettre @ToString classe finale statique privée MyContentImportListener implémente ContentImportListener { modifications finales privées de com.google.common.collect.Multimap = com.google.common.collect.ArrayListMultimap.create(); @Passer outre public void onReorder(final StringorderPath, final String beforeSibbling) {this.changes.put("onReorder", String.format("%s, %s",orderPath, beforeSibbling)); } @Passer outre public void onMove(final String srcPath, final String destPath) { this.changes.put("onMove", String.format("%s, %s", srcPath, destPath)); } @Passer outre public void onModify(final String srcPath) { this.changes.put("onModify", srcPath); } @Passer outre public void onDelete(final String srcPath) { this.changes.put("onDelete", srcPath); } @Passer outre public void onCreate(final String srcPath) { this.changes.put("onCreate", srcPath); } @Passer outre public void onCopy(final String srcPath, final String destPath) { this.changes.put("onCopy", String.format("%s, %s", srcPath, destPath)); } @Passer outre public void onCheckin(final String srcPath) { this.changes.put("onCheckin", srcPath); } @Passer outre public void onCheckout(final String srcPath) { this.changes.put("onCheckout", srcPath); } } }
Conclusion
Tout d'abord, extrayez et transformez votre contenu dans la structure JSON souhaitée. Il doit représenter le contenu tel que vous le souhaitez. Ensuite, vous pouvez tirer parti de la fonction d'importation de Sling Post Servlet pour le rediriger vers AEM. Si vous devez être dans le contexte de l'instance AEM, vous pouvez utiliser le service Content Importer à la place.
Source link