Stardust/Knowledge Base/Integration/Camel/Email Trigger with Process Attachments
This article discusses an integration scenario where a Stardust process is kicked off by an incoming mail in a POP3 account that is being monitored by Camel. The incoming mail is parsed for certain keywords and the process to be invoked is selected dynamically based on the value of the keyword. Certain process data is also selected dynamically by parsing the mail contents. Any attachments that are part of the mail are converted into Documents and associated with the newly created Process Instance.
All the artifacts discussed in this article can be downloaded from here.
The model above contains two processes viz. Purchase and Redemption. For simplicity, both the processes have been designed to be identical. We define two simple primitives viz. "Client" and "MailBody", both of type String. The "Client" data will be populated based on the value of a lookup made from within the Camel route depending on certain process data, while "MailBody" will contain the text of the Email. The first activity named "Wait for Doc Sync" is a Route activity which is set to Hibernate initially. We will discuss the reasons for this decision later in the article. The subsequent activity displays the contents of the data above in the Stardust portal. Note that both the processes need to be able to support "Process Attachments". This can be enabled by changing the process properties.
We next look at the details of the Camel route employed.While the default Stardust camel-context.xml file already ships with a few bean definitions and a "do-nothing" route, we will restrict ourselves to only discuss those beans and endpoints used in this integration.
The "ippServiceFactoryAccess" bean belongs to the ISB component and is used within our custom bean to pass ServiceFactory credentials when invoking the Stardust services. We employ two custom beans in this integration viz. "mailProcessDataExtractor" and "ippProcessRouter". As seen above, the Camel Mail component is responsible for monitoring a POP3 inbox. The default polling interval is used here (60s). The "delete" attribute on the Endpoint ensures that the mail is processed only once by the Camel route and deleted upon successful execution of the route (mail deletion may not work on all servers). The Exchange is routed from the Mail endpoint to our custom bean. Note that since no method is explicitly specified, the method with the "@Handler" annotation will be invoked. We will discuss the code in our custom beans later in the article and limit ourselves to a higher level discussion in this section. If the mail happens to contain the right keywords, the mailProcessDataExtractor sets the "ippProcessId" header which identifies the process to be started to the "ipp" endpoint later in the route. This bean also sets a couple of custom headers viz. "dataValue" and "dataID". The "dataID" header contains the Id of the data within our process model that will contain the "dataValue" (in this case "Client"). The "dataValue" is the value to be set for "dataID". The bean parses the mail contents, scans certain keywords and matches these against a couple of property lookup files to determine these values.
If the mail does not happen to contain any valid keyword, the bean is unable to set the custom headers. The route terminates at this point (exit choice above).
If the mail does appear to contain valid keywords, the route then invokes our second custom bean viz. "ippProcessRouter". This bean is responsible for dynamically replacing the placeholder [header.dataID] in the IPP endpoint with the value computed by the mailProcessDataExtractor bean. This is explained in greater detail in the following section. The "ipp:authenticate' endpoint simply sets the proper user credentials to start the process and the subsequent step "ipp:process:start" actually starts off the process and sets the data values expected by the model. Note that at this point, no process attachments have been created due to the fact that we do not have a ProcessInstanceOID to associate the documents with until the process is started. The header "ippProcessInstanceOid" is set on the exchange body after the process is started. We make use of this value by calling the "moveDocumentstoPI" method on the mailProcessDataExtractor bean. This method moves the documents to the correct location under the Document Repository associated with the newly created Process Instance and sets the "PROCESS_ATTACHMENTS" header with a Document List that contains these Documents. The next endpoint in the route "ipp:process:setProperties" maps this header to the "PROCESS_ATTACHMENTS" data path of the process thereby associating the documents with the new Process Instance. At this point the need for a hibernated activity in the process model above becomes clear. We would like to ensure that the documents are associated with the correct Process Instance before we let the process continue any further. The above steps ensure that we achieve this goal. We are now free to complete the awaken the hibernated Route activity and let the next activity in the process execute. This is achieved by the final call to "ipp:process:continue" in the route.