Dispatching a request from a workflow process (5.6.1)
Hello,
We are creating a simple workflow process to automate a process that would generally be executed by a content manager. The process is to click a button on the Page tab of the Sidekick. The button is provided by ClayTablet (an integrated translation platform), but this is a superfluous detail; the important part is that the button results in a GET request to a path/servlet on the current author environment.
We've tried a few approaches:
- urlcaller process (out of the box) to make the HTTP request
- Custom WorkflowProcess which does nearly the same as urlcaller; uses Apache Commons HttpClient to submit the request
- Custom WorkflowProcess which creates a SyntheticResource bound to the path, attempting to dispatch that way; this was unsuccessful
We are currently reasonably happy with approach #2, included here:
package com.snip.workflow.process; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpState; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Properties; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.adobe.granite.workflow.WorkflowException; import com.adobe.granite.workflow.WorkflowSession; import com.adobe.granite.workflow.exec.WorkItem; import com.adobe.granite.workflow.exec.WorkflowData; import com.adobe.granite.workflow.exec.WorkflowProcess; import com.adobe.granite.workflow.metadata.MetaDataMap; /** * The UpdateTranslationMemory workflow process step to support ClayTablet needs. */ @Component(enabled = true, immediate = true) @Service @Properties({ @Property(name = "process.label", value = "ClayTablet Update Translation Memory") }) public class UpdateTranslationMemoryProcessStep implements WorkflowProcess { private static final Logger LOG = LoggerFactory.getLogger(UpdateTranslationMemoryProcessStep.class); @Override public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException { LOG.debug("Running UpdateTranslationMemoryProcessStep"); WorkflowData workflowData = item.getWorkflowData(); String path = workflowData.getPayload().toString(); String url = "<need hostname>/content/ctctranslation/updatetm/pagechangeinfo.html?action=submitUTM&path=" + path; HttpClient httpClient = new HttpClient(); GetMethod getMethod = new GetMethod(url); HttpClientParams httpClientParams = new HttpClientParams(); httpClientParams.setAuthenticationPreemptive(true); httpClient.setParams(httpClientParams); HttpState httpState = new HttpState(); httpState.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("updateTM", "superSecretPassword")); httpClient.setState(httpState); try { int responseCode = httpClient.executeMethod(getMethod); if (responseCode == 200) { LOG.debug("200 response for Update TM request for path: " + path); } else { LOG.error("Non-200 response while submitting Update TM request for path: " + path); } } catch (Exception e) { LOG.error("Exception while submitting Update TM request for path: " + path, e); } } }In order to make the request with HttpClient, we've had to create a dummy user for submitting the GET request. We would, however, prefer if the request were submitted by the same user that begins the workflow which includes this step. Is this possible, either with this implementation, or with a completely different approach?
We would also like to determine if it is possible to make a request to the same hostname as the server, without using the Link Externalizer (which is not currently configured with the hostnames for all of our environments). Is there a way to submit a domain-relative request, so this code does not need to determine the hostname? Is there a way to dispatch a request internal to AEM/Sling, without going over HTTP?
Overall, is there a better way to solve the problem than the approach that I have posted?
Thanks,
Dave