Tuesday 19 February 2013

How BPEL Gets Execute


By default  BPEL will create a new transaction on request basis - that is if one already exists, it will be suspended, and a new one created. Upon completion of the child, the master one resumes. 
                         
However, if the request is async (that is one-way) we either inherit the transaction for the insert into the dehydration store (that is dlv_message in this case) or if one exists enlist transparently into it. So we guarantee you zero message loss. Either the invocation message is in the dehydration store, to be processed, or otherwise the consumer is notified via a fault.
One only needs to set the (new) transaction flag on the calee bpel component. This can be done in the composite editor's source by adding bpel.config.transaction into a bpel component - as shown below


  <component name="SampleProject">

    <implementation.bpel src="SampleProject.bpel"/>

    <property name="bpel.config.transaction"

         many="false" type="xs:string">required | requiresNew</property>

  </component>
The two possible values are 
1> required, which makes BPEL inherit the tx that is already thereor if not creating a new one
2> requiresNew which makes BPEL suspending one if exists, and ALWAYS create a new one 
                     

Implications of setting the above (the default is requiresNew)


Case one - BPELCaller calls BPELCallee (the latter has requiresNew set)

a) BPELCallee replies (that is uses <reply>) with a fault: BPELCallee transaction is saved, BPELCaller get's the fault and can catch it.
b) BPELCallee throws (that is uses <throw>) a fault, that is NOT handled: BPELCallee tx get's rolled back, BPELCaller get's the fault and can catch it
c) BPELCallee replies back with a fault (FaultOne), and then throws a fault (FaultTwo): BPELCallee tx get's rolled back, and BPELCaller get's FaultOne
d) BPELCallee throws (that is uses <throw>) a bpelx:rollback fault: BPELCallee tx get's rolled back, BPELCaller get's a remote fault

Example:--

Create two processes (BPELMaster and BPELChild), both sync, each using the same db adapter reference that inserts the same record (and hence causes a PK violation). (And of course has set xADatasourceName). In this case
                 
Once the fault occurs, and is not handled - the BPELChild will rollback. If the BPELMaster has a catch block his transaction will commit, so you end up with the record from the Master in the db.If you don't catch the fault in the master as well - you get a second rollback - two different transactions though.

Case two - BPELCaller calls BPELCallee (the latter has required set)
a) BPELCallee replies (that is uses <reply>) with a fault: BPELCaller get's the fault and can catch it, BPELCaller owns the transaction - hence if he catches it - tx is committed, if BPELCaller does not handle it - global rollback.
b) BPELCallee throws (that is uses <throw>) a fault BPELCaller get's the fault and can catch it
c) BPELCallee replies back with a fault (FaultOne), and then throws a fault (FaultTwo): BPELCaller get's FaultOne
d) BPELCallee throws (that is uses <throw>) a bpelx:rollback fault: BPELCaller tx get's rolled back, no way to catch it.

Example :--

Create two processes (BPELMaster and BPELChild), both sync, each using the same db adapter reference that inserts the same record (and hence causes a PK violation). (And of course has set xADatasourceName). In this case
 If no fault handlers are in place - the whole tx will rollback, based on the BPELMaster's unhandled fault.With a fault handler in the BPELMaster to catch the Fault from the BPELClient - and throw up a rollback fault. Globally the tx will rollback as well.


For more info: http://www.soabyte.com/2011/05/soa-suite-11g-transaction-semantics.html#ixzz2LL1f3t00

Wednesday 6 February 2013

Return a fault from an Asynchronous Web Service

In an asynchronous web service we can't return a soap fault like a synchronous service but that does not mean you can't report back the fault to the calling asynchronous process.

basically you got three options.

  • Off course handle the fault in the error hospital and give back the response. 
  • In the response message you can add a section ( a XSD choice with success and fault section) which can be used for faults.
  • Do a callback to a common fault operation of the calling process. This can be a JMS message with the messageId/correlationId or a Web Service invocation where we use the correlation of BPEL to match the fault message with the right process. 

In this blogpost I will show how to implement the last two options in Oracle BPEL.

First we start with returning the fault in a response message.

For this I added a status element to the response and a choice for a success and a fault .


In the catch section you can also invoke the callback response and in the Assign activity you can fill the fault section of the response message.




Do a fault callback to the calling process,  for this we need to do the following.

Create an Asynchronous BPEL process.

Define a fault response schema. The EmployeeId element is necessary, we need this for the correlation of the BPEL processes.


Then make a new WSDL with the fault callback operation and add a fake endpoint. ( we will override this endpoint from BPEL, because we don't know the endpoint of the calling process).


Add a FaultCallback reference web service based on this WSDL and add a wire to the BPEL process.


In the BPEL receive activity, we need to capture the fault callback url. We can optional use this for the fault response endpoint.  Go the properties tab and capture the value of the faultToAddress property. Put the value in the faultCallBackUrl variable.



In the Catch section of the BPEL process we can invoke the fault reference service. Off course use an assign to add the EmployeeId and provide a fault message.


Open the fault invoke activity and go to the properties tab.


We need to set the endpointURI property with the faultCallBackUrl variable value.


That is all for the Asynchronous Service.

Next step is to use this Asynchronous Fault Service in an other asynchronous BPEL process.

We need to make a WSDL ( contract first ) with a portType which also contains the fault operation, this must match with the reference WSDL of the Asynchronous Fault Process. So operationName, Message and namespace must match.

Create a new BPEL process which is based on this WSDL ( expose this BPEL as a service ) and also add wire the Asynchronous Fault process.


This is the process with InvokeEmployee activity which calls the Asynchronous Service.



Open this invoke activity and go to the properties tab where we set the faultToAddress property. This is the endpoint of this BPEL process and will be used for the fault callback.


After the invoke we need to use a pick activity and add an extra onMessage to the pick activity.
First OnMessage will be used for the normal callback situation.


The second will be used for the fault Response.


The last step is to setup correlation in this BPEL for the returning fault message.

on the receive add a correlation set and initiate this ( I got a NPE when I tried to set it on the invoke ). The Set is based on the employeeId element.



Add two Property Aliases , first is based on the employeeId element of the Fault Message and second is the employeeId of the request message.


On the fault OnMessage we need to add the same correlation set and this time we don't need to initiate it.



If everything is Ok we will see the following in the Enterprise Manager.

on the invoke we set the faultToAddress, the normal response OnMessage is cancelled and the fault OnMessage gets a response with the fault message.



On github you can download this example https://github.com/biemond/soa11g_examples/tree/master/AsynchronousFaultHandling

Lets SOA Suite UMS do your Application Messaging

 With User Messaging Service you can let Soa Suite 11g do all your Messaging. And UMS can do a lot: like Email with Attachments, Instant Messaging (XMPP, like Google Talk), SMS Text messages (SMPP), Fax or Voice Messages and deliver messages to the Soa & Webcenter Task List. Besides this, UMS keeps track of delivery status information provided by messaging gateways and makes this information available to applications so that they can respond to a failed delivery.
In Patch Set 2 of Soa Suite 11g Oracle added a simple java API for UMS and in this blogpost I will use this API in a EJB Session Bean with a Remote Interface and also expose this Session Bean as a Web Service. This Session Bean & Web Service can be used in your custom applications so you don't need to have or build your own messaging methods because Soa Suite can do more and much better and even keeps track of your messages. Just call the Web Service or the Session Bean, deliver a list of Receivers with names and the media delivery type and it will return a MessageId with this you can check the status of your send messages.

In this blogpost I will use the email and instant messaging driver to deliver my messages. And as a demo I can send email attachements, deliver a message to IM and Email Client. ( Multi part Message , plain text part for IM and HTML part for Email ) and at last get retrieve the status of these messages. And you can use this in SoapUI, a web service proxy or in a EJB java client.

First you need to enable and configure the UMS Email and Instant Messaging Driver ( XMPP).
Go to the Weblogic console of your Soa Domain probably http://xxxxx:7001/console and select the XMPP UMS driver and go the the target tab and enable the Soa servers or soa cluster.


You need to reboot the Soa Server managed Servers.
In the User Messaging Service part of the Enterprise Manager Website http://xxxx:7001/em you can select the xmpp driver and go the XMPP Driver Properties.
In my case I will use Google Talk as IM service. Provide the server and a Talk user account.
Do the Same for your UMS Email driver. Provide the SMTP server.
And enable all the Work Flow communications in the WorkFlow Notifications Properties page of the Soa Infrastructure part..

You need to reboot the Soa Server managed Servers.

Now you can go to the developer part and create a JDeveloper project and add an new Application. Your project needs to have the UMS library located at jdeveloper\communications\modules\oracle.sdp.messaging_11.1.1\sdpmessaging.jar and your application also needs to have a reference to the oracle.sdp.messaging shared library. Do this in the weblogic-application.xml.
This EJB / WS needs to deployed on the Soa Suite Managed Servers.

To make things more simple I made two entities Receiver and Status.
The Receiver just needs an email address and type ( EMAIL or IM )
  1. package nl.whitehorses.soa.ums.entities;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. public class Receiver implements Serializable{  
  6.     public Receiver() {  
  7.   
  8.     }  
  9.   
  10.     private String receiver;  
  11.     private String channel;  
  12.   
  13.     public Receiver(String receiver, String channel) {  
  14.         super();  
  15.         this.receiver = receiver;  
  16.         this.channel = channel;  
  17.     }  
  18.   
  19.     public void setReceiver(String receiver) {  
  20.         this.receiver = receiver;  
  21.     }  
  22.   
  23.     public String getReceiver() {  
  24.         return receiver;  
  25.     }  
  26.   
  27.     public void setChannel(String channel) {  
  28.         this.channel = channel;  
  29.     }  
  30.   
  31.     public String getChannel() {  
  32.         return channel;  
  33.     }  
  34. }  
The Status entity gives some simple info about the send messages.
  1. package nl.whitehorses.soa.ums.entities;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Date;  
  5.   
  6. public class Status implements Serializable {  
  7.     public Status() {  
  8.     }  
  9.         
  10.     private String messageId;  
  11.     private Date   sendTime;  
  12.     private String receiver;  
  13.     private String status;  
  14.   
  15.     public Status(String messageId, Date sendTime, String receiver,  
  16.                   String status) {  
  17.         super();  
  18.         this.messageId = messageId;  
  19.         this.sendTime = sendTime;  
  20.         this.receiver = receiver;  
  21.         this.status = status;  
  22.     }  
  23.   
  24.     public void setMessageId(String messageId) {  
  25.         this.messageId = messageId;  
  26.     }  
  27.   
  28.     public String getMessageId() {  
  29.         return messageId;  
  30.     }  
  31.   
  32.     public void setSendTime(Date sendTime) {  
  33.         this.sendTime = sendTime;  
  34.     }  
  35.   
  36.     public Date getSendTime() {  
  37.         return sendTime;  
  38.     }  
  39.   
  40.     public void setReceiver(String receiver) {  
  41.         this.receiver = receiver;  
  42.     }  
  43.   
  44.     public String getReceiver() {  
  45.         return receiver;  
  46.     }  
  47.   
  48.     public void setStatus(String status) {  
  49.         this.status = status;  
  50.     }  
  51.   
  52.     public String getStatus() {  
  53.         return status;  
  54.     }  
  55.       
  56.     public String toString() {  
  57.       return "message id: "+ messageId+" time: "+sendTime.toString()+ " status: " +status + " receiver: " + receiver;    
  58.     }  
  59. }  
Here the main code with three method sendMailAttachmentMsg, sendMixedMsg and getMessageStatus.
The sendMailAttachmentMsg method will only send Mail with Attachments and sendMixedMsg method can send messages to Google Talk and Email, it depends on the receivers and getMessageStatus returns the Statusses of the send messages.
  1. package nl.whitehorses.soa.ums.services;  
  2.   
  3.   
  4. import javax.ejb.Remote;  
  5. import javax.ejb.Stateless;  
  6.   
  7. import java.util.HashMap;  
  8. import java.util.Map;  
  9.   
  10. import java.util.ArrayList;  
  11. import java.util.List;  
  12.   
  13. import javax.activation.DataHandler;  
  14.   
  15. import javax.jws.WebMethod;  
  16. import javax.jws.WebParam;  
  17. import javax.jws.WebResult;  
  18. import javax.jws.WebService;  
  19.   
  20. import javax.mail.internet.MimeBodyPart;  
  21. import javax.mail.internet.MimeMultipart;  
  22.   
  23. import nl.whitehorses.soa.ums.entities.Receiver;  
  24. import nl.whitehorses.soa.ums.utilities.ReceiverConvertor;  
  25.   
  26. import oracle.sdp.messaging.Address;  
  27. import oracle.sdp.messaging.ApplicationInfo;  
  28. import oracle.sdp.messaging.DeliveryType;  
  29. import oracle.sdp.messaging.Message;  
  30. import oracle.sdp.messaging.MessagingFactory;  
  31. import oracle.sdp.messaging.MessagingClient;  
  32. import oracle.sdp.messaging.MessagingClientFactory;  
  33. import oracle.sdp.messaging.MessagingException;  
  34. import oracle.sdp.messaging.Status;  
  35. import oracle.sdp.messaging.util.ByteArrayDataSource;  
  36. import oracle.sdp.messaging.util.StringDataSource;  
  37.   
  38. @Stateless(name="SessionEJB", mappedName = "SoaUMSMessaging-SessionEJB")  
  39. @Remote  
  40. @WebService(name        = "UMSMessagingService",   
  41.             serviceName = "UMSMessagingService",  
  42.             portName    = "UMSMessagingServicePort")  
  43. public class SessionEJBBean implements SessionEJB {  
  44.   
  45.     MessagingClient mClient = null;  
  46.     Map<String, Object> params = new HashMap<String, Object>();  
  47.   
  48.     public SessionEJBBean() {  
  49.       params.put(ApplicationInfo.APPLICATION_NAME, "CompanyMsgr");  
  50.       params.put(ApplicationInfo.APPLICATION_INSTANCE_NAME, "CompanyInstance");  
  51.     }  
  52.   
  53.     @WebMethod  
  54.     @WebResult(name = "messageId")  
  55.     public String sendMailAttachmentMsg(  
  56.                                         @WebParam(name = "sender")    String sender,   
  57.                                         @WebParam(name = "receivers") List<Receiver> receivers,  
  58.                                         @WebParam(name = "subject")   String subject,  
  59.                                         @WebParam(name = "message")   String message,  
  60.                                         @WebParam(name = "data"byte[] data,  
  61.                                         @WebParam(name = "mimetype") String mimetype,  
  62.                                         @WebParam(name = "filename") String fileName) {  
  63.   
  64.       MimeMultipart mp = null;  
  65.   
  66.       try {  
  67.           // plain msg for the body  
  68.           MimeBodyPart mp_partPlain = new MimeBodyPart();  
  69.           mp_partPlain.setText(message);  
  70.           
  71.           // binary attachement  
  72.           MimeBodyPart mp_partBinary = new MimeBodyPart();  
  73.           ByteArrayDataSource dataSource = new ByteArrayDataSource(data, mimetype);  
  74.           mp_partBinary.setDataHandler(new DataHandler(dataSource));  
  75.           mp_partBinary.setFileName(fileName);  
  76.   
  77.           mp = new MimeMultipart("alternative");  
  78.           mp.addBodyPart(mp_partPlain);  
  79.           mp.addBodyPart(mp_partBinary);  
  80.         
  81.       } catch (javax.mail.MessagingException e) {  
  82.           e.printStackTrace();  
  83.       }     
  84.   
  85.         try {  
  86.           Message soaMessage = MessagingFactory.createMessage();  
  87.           Address soaSender =  
  88.               MessagingFactory.buildAddress(sender,   
  89.                                             DeliveryType.EMAIL,  
  90.                                             null);  
  91.   
  92.           soaMessage.setSubject(subject);  
  93.           soaMessage.setContent(mp, "multipart/alternative");  
  94.             
  95.           soaMessage.addSender(soaSender);  
  96.           soaMessage.addAllRecipients(ReceiverConvertor.convertReceiver(receivers));  
  97.   
  98.           mClient = MessagingClientFactory.createMessagingClient(params);  
  99.           String messageId = mClient.send(soaMessage);  
  100.           return messageId;  
  101.   
  102.         } catch (MessagingException e) {  
  103.              e.printStackTrace();  
  104.         }  
  105.    
  106.         return null;  
  107.     }  
  108.   
  109.   
  110.     @WebMethod  
  111.     @WebResult(name = "statusses")      
  112.     public List<nl.whitehorses.soa.ums.entities.Status> getMessageStatus(  
  113.             @WebParam(name = "messageId") String messageId) {  
  114.   
  115.         try {  
  116.             mClient = MessagingClientFactory.createMessagingClient(params);  
  117.             Status[] msgStatuses = mClient.getStatus(messageId);  
  118.             List<nl.whitehorses.soa.ums.entities.Status> statusses =  
  119.                 new ArrayList<nl.whitehorses.soa.ums.entities.Status>();  
  120.   
  121.             for (Status msgStatus : msgStatuses) {  
  122.                 nl.whitehorses.soa.ums.entities.Status status =  
  123.                     new nl.whitehorses.soa.ums.entities.Status();  
  124.                 status.setMessageId(msgStatus.getMessageId());  
  125.                 status.setReceiver(msgStatus.getAddress().toString());  
  126.                 status.setStatus(msgStatus.getType().toString());  
  127.                 status.setSendTime(msgStatus.getDate().getTime());  
  128.                 statusses.add(status);  
  129.             }  
  130.             return statusses;  
  131.         } catch (MessagingException e) {  
  132.             e.printStackTrace();  
  133.         }  
  134.         return null;  
  135.     }  
  136.   
  137.     @WebMethod  
  138.     @WebResult(name = "messageId")  
  139.     public String sendMixedMsg(@WebParam(name = "subject") String subject,  
  140.                                @WebParam(name = "message") String message,   
  141.                                @WebParam(name = "sender") String sender,   
  142.                                @WebParam(name = "receivers") List<Receiver> receivers) {  
  143.   
  144.   
  145.         Message soaMessage = MessagingFactory.createMessage();  
  146.         MimeMultipart part_mp = null;  
  147.   
  148.         try {  
  149.           // IM Message    
  150.           MimeBodyPart part_mp_partPlain = new MimeBodyPart();  
  151.           // set IM    
  152.           part_mp_partPlain.addHeader(soaMessage.HEADER_SDPM_PAYLOAD_PART_DELIVERY_TYPE,  
  153.                                       "IM");  
  154.           part_mp_partPlain.setText(message);  
  155.    
  156.           // Email Message               
  157.           MimeBodyPart part_mp_partRich = new MimeBodyPart();  
  158.           // set Email    
  159.           part_mp_partRich.addHeader(soaMessage.HEADER_SDPM_PAYLOAD_PART_DELIVERY_TYPE,  
  160.                                      "EMAIL");  
  161.           StringDataSource htmlDataSource =   
  162.               new StringDataSource("<html><head></head><body><b><i>"+  
  163.                                    message+   
  164.                                    "</i></b></body></html>",  
  165.                                    "text/html; charset=UTF-8");  
  166.           part_mp_partRich.setDataHandler(new DataHandler(htmlDataSource));  
  167.       
  168.           part_mp = new MimeMultipart("alternative");  
  169.           part_mp.addBodyPart(part_mp_partPlain);  
  170.           part_mp.addBodyPart(part_mp_partRich);  
  171.   
  172.         } catch (javax.mail.MessagingException b) {  
  173.               b.printStackTrace();  
  174.         }  
  175.   
  176.   
  177.         try {  
  178.             mClient = MessagingClientFactory.createMessagingClient(params);  
  179.   
  180.             soaMessage.setSubject(subject);  
  181.             soaMessage.setContent(part_mp, "multipart/alternative");  
  182.             // Enabled for IM and Email  
  183.             soaMessage.setMultiplePayload(true);  
  184.   
  185.             Address soaSender = MessagingFactory.buildAddress(sender,  
  186.                                                               DeliveryType.EMAIL,  
  187.                                                               null);  
  188.   
  189.             soaMessage.addSender(soaSender);  
  190.             soaMessage.addAllRecipients(ReceiverConvertor.convertReceiver(receivers));  
  191.   
  192.             String messageId = mClient.send(soaMessage);  
  193.             return messageId;  
  194.         } catch (oracle.sdp.messaging.MessagingException b) {  
  195.             b.printStackTrace();  
  196.         }  
  197.         return null;  
  198.     }  
  199.   
  200. }  

My EJB test client
  1. package nl.whitehorses.soa.ums;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5.   
  6. import java.io.IOException;  
  7.   
  8. import java.nio.ByteBuffer;  
  9. import java.nio.channels.FileChannel;  
  10.   
  11. import java.util.ArrayList;  
  12. import java.util.Hashtable;  
  13.   
  14. import java.util.List;  
  15.   
  16. import javax.naming.Context;  
  17. import javax.naming.InitialContext;  
  18. import javax.naming.NamingException;  
  19.   
  20. import nl.whitehorses.soa.ums.entities.Receiver;  
  21. import nl.whitehorses.soa.ums.entities.Status;  
  22. import nl.whitehorses.soa.ums.services.SessionEJB;  
  23.   
  24. public class SessionEJBClient {  
  25.     public static void main(String[] args) {  
  26.         try {  
  27.             final Context context = getInitialContext();  
  28.             SessionEJB sessionEJB =  
  29.                 (SessionEJB)context.lookup("SoaUMSMessaging-SessionEJB#nl.whitehorses.soa.ums.services.SessionEJB");  
  30.   
  31.             List<Receiver> receivers = new ArrayList<Receiver>();  
  32.             Receiver receiver  = new Receiver("xxx@gmail.com""EMAIL");  
  33.             Receiver receiver2 = new Receiver("xxxx@tiscali.nl""EMAIL");  
  34.             receivers.add(receiver);  
  35.             receivers.add(receiver2);  
  36.   
  37.   
  38.   
  39.             String messageId =  
  40.                 sessionEJB.sendMailAttachmentMsg( "xxxx@xs4all.nl",  
  41.                                                    receivers,  
  42.                                                    "hello subject",  
  43.                                                    "hello body"  
  44.                                                    ,doDownload("C:/temp/logo.png"),  
  45.                                                    "image/png",  
  46.                                                    "logo.png");  
  47.   
  48.             System.out.println("MessageId is " + messageId +  
  49.                                " lets wait 2 seconds for the status");  
  50.             Thread.sleep(2000);  
  51.   
  52.             if (messageId != null) {  
  53.               List<Status> statusses =  
  54.                   sessionEJB.getMessageStatus(messageId);  
  55.               for (Status status : statusses) {  
  56.                   System.out.println(status.toString());  
  57.               }  
  58.             }  
  59.   
  60.   
  61.             Receiver receiver3 = new Receiver("nl2en@bot.talk.google.com""IM");  
  62.             receivers.add(receiver3);  
  63.   
  64.             messageId = sessionEJB.sendMixedMsg("Hello",  
  65.                                                 "Hello world",  
  66.                                                 "xxxx@xs4all.nl",  
  67.                                                 receivers );  
  68.   
  69.   
  70.             System.out.println("MessageId is " + messageId +  
  71.                                " lets wait for the status");  
  72.             Thread.sleep(4000);  
  73.   
  74.             if (messageId != null) {  
  75.                 List<Status> statusses =  
  76.                     sessionEJB.getMessageStatus(messageId);  
  77.                 for (Status status : statusses) {  
  78.                     System.out.println(status.toString());  
  79.                 }  
  80.             }  
  81.   
  82.         } catch (Exception ex) {  
  83.             ex.printStackTrace();  
  84.         }  
  85.     }  
  86.   
  87.     private static Context getInitialContext() throws NamingException {  
  88.         Hashtable env = new Hashtable();  
  89.         env.put(Context.INITIAL_CONTEXT_FACTORY,  
  90.                 "weblogic.jndi.WLInitialContextFactory");  
  91.         env.put(Context.PROVIDER_URL, "t3://localhost:8001");  
  92.         return new InitialContext(env);  
  93.     }  
  94.   
  95.     public static byte[] doDownload(String fileName) {  
  96.         FileInputStream fis;  
  97.         byte[] data = null;  
  98.         FileChannel fc;  
  99.   
  100.         try {  
  101.             fis = new FileInputStream(fileName);  
  102.             fc = fis.getChannel();  
  103.             data = new byte[(int)(fc.size())];  
  104.             ByteBuffer bb = ByteBuffer.wrap(data);  
  105.             fc.read(bb);  
  106.         } catch (FileNotFoundException e) {  
  107.             // TODO  
  108.         } catch (IOException e) {  
  109.             // TODO  
  110.         }  
  111.         return data;  
  112.     }  
  113. }  
If you send messages with this EJB Session or WS then you can take a look at the application client in the UMS service overview.

Here you can download  Edwin Biemondworkspace

UMS adapter of SOA Suite PS5

Proces email with the new UMS adapter of SOA Suite PS5

With the release of Soa Suite Patch Set 5 we can now try out the new UMS adapter. UMS stands for User Messaging Service but in this case it only supports email. The UMS adapter allows you to listen for new mail or send a mail from a service component. Combined with BPEL it’s now relative  easy to process email bodies or attachments. Remember that in PS5 the UMS adapter is still a  preview version so you can’t claim support and you can only use the Oracle forums for your ums questions.
It’s important to know that the UMS adapter does not work like a JMS topic or like EDN. So you can’t have two UMS adapters which are polling on the same mailbox.
In this blogpost I will show you how to setup and configure UMS, Listen plus send a mail and handle attachments.
We start with configuring our SOA Suite domain.
1st step is to copy two UMS libraries to your SOA Suite domain folder. Copy sdpmessagingclient.jar and sdpmessagingcommon.jar to the lib folder of the SOA Suite WebLogic Domain. You can find these jars at MiddlewareHome\Oracle_SOA1\communications\modules\oracle.sdp.client_11.1.1
2nd Install the UMS resource adapter.  Open the WebLogic Console and deploy the UMSAdapter.rar, you can find this adapter at MiddlewareHome\Oracle_SOA1\soa\connectors . Make sure you targeted this Resource Adapter to the SOA managed WebLogic server. And restart the SOA Suite Server.
3rd Check if the usermessagingdriver-email and usermessagingserver applications are active and targeted to the to the SOA managed WebLogic server. You can check this in the deployments of the weblogic console.
4th Configure the UMS Email driver.  For this we need to go the Enterprise Manager application. When everything is Ok you should see the User Messaging Service. Here we can select usermessagingdriver-email and in the menu we can go the Email Driver Properties.

Here we can set some defaults, like the default mail address, Cost and Speed ( cpu priority )

The UMS settings for outgoing mail.

The incoming settings are more complex because I will read two mail accounts, this is because I need one mail account for every polling UMS adapter.

To make this work I can use a “,” between the values so for IncomingMailIDs I use this as value soa@local.nl,soa2@local.nl , do the same for IncomingUserIDs = soa,soa2  and for the IncomingUserPasswords, I use CleartextPassword and also use a “,” between the passwords.
Restart the SOA Suite server.

At last we must enable the UMS adapter in JDeveloper.  Go to the JDev11.1.1.6\jdeveloper\integration\seed\soa\configuration folder and open the soa-config.xml. Find the adapterType with this ${UMS_ADAPTER_COMPONENT_NAME_L}  as name and remove the preview = true attribute. Now You will see the new UMS adapter in your SOA Component Palette.


In the next part we can finally try this out.
Let’s start with an easy one. Sending a mail from a composite. For this we need to drag the UMS adapter to the External Reference of the Composite.
Don’t change Connection JNDI name.

Choose for Outbound Send Notification. You can choose to receive the Mail Message Id as response, else it will be One Way.

Provide the Mail Header settings.

For Message Schema you got 3 options ( this talks about the mail body ) , off course Opaque, Message is a big String or based on a XML Schema.


Next we can take a look at incoming part of the UMS adapter. Drag the UMS adapter to exposed Services side of the composite.
Don’t change the default Connection JNDI Name

Choose Listener as Operation Mode, Polling does not work in this Preview Adapter and the UMS email driver already polls every few seconds.

Provide the mail adress this must match with your incoming UMS configuration.

Also provide the message type.


We can also define a message filter which can accept or ignore the incoming mails. The pattern string should be a java regexp. To test this pattern you can use this url  http://www.regexplanet.com/advanced/java/index.html
Too bad this feature does not work yet in this technical preview.


And also you can do a custom Java Callout ( I didn’t test it and don’t know the possibilities of this feature).


To test this I need to add the employee xml in the body of the mail ( not as attachment)  and send it to soa@local.nl. As response I will get a mail.
The request I will receive in SOA Suite.

And the response


Last part of this blogpost is about, how to handle mail attachments.
For this I will use the second mail address soa2@local.nl and also change the message type to String. A BPEL service component will write these attachments to a server location.

This is the request I received in the BPEL component. You can see that we only get a reference to the attachments.

So in BPEL we need to use a ForEach to handle every attachment and write this to a file.

To load the attachment and assign it to the file adapter input variable I need to use ora:getAttachmentContent
<assign name=”AssignInput”>
<copy>
<from>ora:getAttachmentContent(‘ReceiveMail_InputVariable’,'body’
,’/ns3:message/ns3:attachment/ns3:Attachment[$ForEachCounter]‘)
</from>
<to>$InvokeWriteFile_InputVariable.opaque</to>
</copy>
</assign>
and this leads to two files.
Here you can download the UMS workspace https://github.com/biemond/soa11g_examples/tree/master/UmsSOA