Thursday, August 15, 2013

Dynamic Email Attachments In Bpel 11g

Dynamic Attachments For Email Activity

By using Email activity to send an Email with 1 Attachment can be achieved without shredding a single drop of sweat J. But if we need to send multiple attachments and the number of attachments are dynamic along with their names then ………………….

Here is the solution to save the time and sweat again J..

Before implementing the solution we would like to explain how the email activity works and then we will start enhancing it step by step

Assumption is that your SMTP server is configured on soa server. If not, you can look here where you can use gmail as your smtp server.

Step1 :Create a BPEL Process and drag an email activity and map the mail attributes as shown below:





 Step 2: Deploy the service and test it. You should get an email on the mentioned email id

This is basic email service. If you see more in the email activity, you would see the assign service and invoke activity calling the internal notification service whose wsdls and xsds are in MDS and are also copied to your project.

Step 3:In the assign activity, I would like to draw your attention towards one mapping where actual logic of dynamic attachments revolves.





The content is below:

<Content xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">
   <MimeType xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">multipart/mixed</MimeType>
   <ContentBody xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">
      <MultiPart xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">
                  <BodyPart xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">
                  <MimeType xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/>
                  <ContentBody xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/>
                  <BodyPartName xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/></BodyPart>
                  <BodyPart xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService">
                  <MimeType xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/>
                  <ContentBody xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/>
                  <BodyPartName xmlns="http://xmlns.oracle.com/ias/pcbpel/NotificationService"/></BodyPart>
                  </MultiPart>
   </ContentBody>
</Content>

First body part is for actual content of body and second body part is for attachment details. If you had 2 attachments, this mapping would have another body part automatically (Email activity adds it)


[Note :] To make the email attachments, the trick was to have one body part for your mail body and same number of additional body parts which you need for attachments.

Step 4: Now we start tweaking the service to achieve dynamic attachment functionality. Please have a look at the notificationservice.xsd



We created an extra element called CustomMultiPartType of type MultiPartType in the above mentioned xsd.
<xsd:complexType name="CustomMultiPartType">
    <xsd:sequence>
      <xsd:element name="MultiPart" type="MultiPartType" maxOccurs="unbounded"/>
    </xsd:sequence>

  </xsd:complexType>

Step 5:  In email activity add a transformation after assign activity wherein we will map the variable to the notification service usually created by name varNotificationReq

My input xsd to the service is defined as below:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
            targetNamespace="http://xmlns.oracle.com/Demo/SendEmail/SendEmailWithMultipleAttachment"
            xmlns:tns="http://xmlns.oracle.com/Demo/SendEmail/SendEmailWithMultipleAttachment"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="sendEmail" type="tns:EmailPayloadType"></xsd:element>
  <xsd:complexType name="EmailPayloadType">
    <xsd:sequence>
      <xsd:element name="FromAccountName" minOccurs="0" type="xsd:string"/>
      <xsd:element name="To" type="xsd:string" minOccurs="1"/>
      <xsd:element name="Cc" minOccurs="0" type="xsd:string"/>
      <xsd:element name="Bcc" minOccurs="0" type="xsd:string"/>
      <xsd:element name="ReplyToAddress" minOccurs="0" type="xsd:string"/>
      <xsd:element name="Subject" type="xsd:string"/>
      <xsd:element name="EmailBody" type="tns:EmailBodyType"/>
      <xsd:element name="Attachments" type="tns:AttachmentsType" minOccurs="0"
                   maxOccurs="unbounded"/>
      <xsd:element name="EmailHeaders" type="tns:ArrayOfEmailHeaderType"
                   minOccurs="0"/>
      <xsd:element name="EditFlag" type="xsd:boolean" minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="ArrayOfEmailHeaderType">
    <xsd:sequence maxOccurs="1">
      <xsd:element name="EmailHeader" maxOccurs="unbounded"
                   type="tns:EmailHeaderType" minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="EmailHeaderType">
    <xsd:sequence>
      <xsd:element name="HeaderName" type="xsd:string" minOccurs="0"/>
      <xsd:element name="HeaderValue" type="xsd:string" minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="EmailBodyType">
    <xsd:sequence>
      <xsd:element name="MimeType" default="text/plain" type="xsd:string"
                   minOccurs="0"/>
      <xsd:element name="Body" nillable="true" type="xsd:string"/>
      <xsd:element name="ContentEncoding" nillable="true" type="xsd:string"
                   minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="AttachmentsType">
    <xsd:sequence minOccurs="1">
      <xsd:element name="MimeType" default="text/plain" type="xsd:string"
                   minOccurs="0"/>
      <xsd:element name="AttachmentContent" nillable="true" type="xsd:string"
                   minOccurs="0"/>
      <xsd:element name="AttachmentName" type="xsd:string" minOccurs="0"/>
      <xsd:element name="ContentEncoding" nillable="true" type="xsd:string"
                   minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:element name="sendEmailResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="messageId" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>


[Note:]Before starting transformation, we need to replace the CustomMultipartType in the content body which is of anytype as below:


After doing this content body will look something like this as shown below:




As discussed earlier, first element in body part would be email body and then you can loop over input attachments and map the other body parts.
The content body mapping part in xsl would look something like this as below:

   <ns0:ContentBody>
          <xsl:attribute name="xsi:type">
            <xsl:text disable-output-escaping="no">ns0:CustomMultiPartType</xsl:text>
          </xsl:attribute>
          <ns0:MultiPart>
           <ns0:BodyPart>
            <ns0:MimeType>
              <xsl:text disable-output-escaping="no">text/html; charset=UTF-8</xsl:text>
            </ns0:MimeType>
            <ns0:ContentBody>
              <xsl:attribute name="xsi:type">
                <xsl:text disable-output-escaping="no">xsd:string</xsl:text>
              </xsl:attribute>
              <xsl:value-of select="/client:sendEmail/client:EmailBody/client:Body"/>
            </ns0:ContentBody>
            <ns0:ContentEncoding>
              <xsl:value-of select="/client:sendEmail/client:EmailBody/client:ContentEncoding"/>
            </ns0:ContentEncoding>
          </ns0:BodyPart>
            <xsl:for-each select="/client:sendEmail/client:Attachments">
              <ns0:BodyPart>
                <ns0:MimeType>
                  <xsl:value-of select="client:MimeType"/>
                </ns0:MimeType>
                <ns0:ContentBody>
              <xsl:attribute name="xsi:type">
                <xsl:text disable-output-escaping="no">xsd:string</xsl:text>
              </xsl:attribute>
             
            </ns0:ContentBody>
                <ns0:BodyPartName>
                  <xsl:value-of select="client:AttachmentName"/>
                </ns0:BodyPartName>
              </ns0:BodyPart>
            </xsl:for-each>
          </ns0:MultiPart>
        </ns0:ContentBody>

Note: the highlighted part is performing multiple attachments. Also the mapping in the assign activity is not required except XML fragment one.

After this you should be able to test this.

I have the sample code with me. Email us if you need the sample. 

Thanks and Happy Coding J J J

Cheers,
LetsLearnOracleSOA Team



10 comments:

  1. Hi

    Could you please send me this sampele to abusoa@gmail.com

    ReplyDelete
  2. Sorry for the delay. I have forwarded the code. Thanks

    ReplyDelete
  3. Thanks Vikas.. I is so helpful. Thanks again for the code.

    Could you please let us knnow how the same can be achieved through OSB.

    Regards,
    Abdul Khader

    ReplyDelete
  4. Hi Abdul,

    Sending email through OSB is done in a different way. Here this service is developed from Notification service available in SOA environment, though you can call this service from OSB.

    ReplyDelete
  5. Hi Sir, Please Send the code agrittyagi95@gmail.com

    ReplyDelete
  6. Hello sir, could you send me the code please?, hector.mike92@gmail.com

    ReplyDelete
  7. HI SIR,

    Can you please send the code to anandshankar.shankar@gmail.com

    ReplyDelete
  8. Thank u very much for the solution

    ReplyDelete
  9. HI SIR,

    Can you please send the code to eng.ahmedreda.87@gmail.com

    ReplyDelete
  10. Hi Sir,

    Can you please send the code to soumyatbhat11@gmail.com

    ReplyDelete