Header Content Footer
Discover best selling sofas, Lounge chairs and get an extra 10% off using the code SEDONA10

Sometimes, when you are involved in AEM projects, it could come up a requirement that you will need to load some content from an external resource provided by the client in a component to be rendered in pages using some javascript logic.

In this post, we are going to show you the best solutions for avoiding cross site issues retrieving an external resource to be used on a HTML in AEM.  The example which we will use it’s based on the following statement: “You want to use an external XML for getting the necesary information and put it in a page.“, but it would be use for other cases.

So let’s see some options you have to achieve your goal.

DEVELOPMENT OF A QUARTZ JOB

Preparing a job on AEM which will be in charge of downloading an external resource file, put it in AEM and activate that resource for being updated on publish environment. Normally, the best choice for saving on AEM a resource is on DAM.  Check below a sample code for this job:

@Component(metatype = true, label = "Example - File importer task", description = "Example of a file importer job for AEM")
@Service(value = Runnable.class)
@Properties({
 @Property(name = "scheduler.expression", value = "*/30 * * * * ?", description = "Cron-job expression"),
 @Property(name = "scheduler.concurrent", boolValue = false, description = "Whether or not to schedule this task concurrently") 
})
public class FileImporterTask implements Runnable {

 private static final Logger LOG = LoggerFactory.getLogger(FileImporterTask.class);

 @Property(label = "External URL", description = "External resource to be importerd")
 public static final String EXTERNAL_RESOURCE = "externalResource";

 @Property(label = "Target path", description = "Path where save the external resource")
 public static final String TARGET_RESOURCE = "targetPath";
 
 @Reference
 private SlingRepository repo;
 @Reference
 private ResourceResolverFactory resourceResolverFactory;
 @Reference
 private Replicator replicator;

 private String externalResource;
 private String targetPath;

 @Activate
 protected void activate(final Map<String, Object> config) {
   configure(config);
 }

 @Override
 public void run() {
   LOG.info("FileImporterTask is now running");		
   InputStream inputStream = retrieveFile(externalResource);	
   if (inputStream != null) {
     writeToDam (inputStream, targetPath, "text/xml");
   }
 }

 private void configure(final Map<String, Object> config) {
   externalResource = PropertiesUtil.toString(config.get(EXTERNAL_RESOURCE), null);
   targetPath = PropertiesUtil.toString(config.get(TARGET_RESOURCE), null);
 }

 /**
 * retrieveFile
 * 
 * @param urlString
 *          - url of file
 * @return
 */
 private InputStream retrieveFile(String urlString) {
   InputStream is;
   //Retrieve the input stream from the external URL
   return is;
 }

 /**
 * writeToDam
 * 
 * @param is
 *          - input stream of file
 * @param path
 *          - target path to be saved
 * @param mimeType
 *          - Mimetype of the file to be saved
 * @return
 */
 private void writeToDam(InputStream is, String path, String mimeType) {
   //create asset coming from input stream in the path specified in the parameter
   //and replicate the asset using replicator for publish it.
 }
 
}

As you can see, it was defined some configuration properties you can set in System Console:

CONFIGURATION OF WEBSERVER

Instead of developing a job in AEM, it could be possible to do something much simpler if there is no requirement to process the external resource (you need only to show it). This option is to configure a webserver rule mapping a URL in your domain with the external one.

Check below a sample rewrite rule to be added for apache for this purpose:

RewriteRule ^myfolder/$ http://other.example.com/anotherfolder/ [P,NE,L]

With this rule, when a client is requesting /myfolder/ from your server, it will request http://other.example.com/anotherfolder/ and send the response from that server back to the client. The options inside [] means:

  • P(proxy): Force the substitution URL to be internally sent as a proxy request.
  • NE(noescape): Prevent mod_rewrite from applying hexcode escaping of special characters in the result of the rewrite.
  • L(last): Stop the rewriting process immediately and don’t apply any more rules.

In the following schema, we are going to show how it works the rewrite rule:

CONCLUSIONS

With both options, you are reducing a lot the requests on your AEM instances compared to developing a proxy servlet, that could maybe the first option in your mind.

First option could be more indicated if you need to elaborate data read from the external source (so you do not have to re-elaborate at every request, but could not be appropriate if the external resource is changing very often.

Second option could be your best choice if you just want to display the external resource as it is (no elaboration needed) or the external data is changing so often that you caching in a local resource, would result in displaying not updated data.

AUTHORS

Alessandro Paolinelli, Javier Reyes

1 Comment

  • Avatar
    Ashish

    Nice blog post.
    In my view an easier solution would be to leverage AEM’s importer framework. Authors can easily add or edit configurations (/etc/polling/importers), unlike Felix console which is only available to super/admin users.
    I believe some of AEM’s features (Sitecatalyst and other integrations) rely on this framework.

Leave a Reply