Wednesday, November 6, 2013

Oracle SOA: How to Configure Transaction Timeout for BPEL on SOA 11g

During runtime of your BPEL process you may be seeing errors like this:

Transaction Rolledback.: weblogic.transaction.internal.TimedOutException: 
Transaction timed out after 30 seconds 
BEA1-484455D7A39364D50D1F
 at 
weblogic.transaction.internal.ServerTransactionImpl.wakeUp(ServerTransactionImpl.java:1788)

 at 
weblogic.transaction.internal.ServerTransactionManagerImpl.processTimedOutTransactions(ServerTransactionManagerImpl.java:1676)

 at 
weblogic.transaction.internal.TransactionManagerImpl.wakeUp(TransactionManagerImpl.java:1988)

 at 
weblogic.transaction.internal.ServerTransactionManagerImpl.wakeUp(ServerTransactionManagerImpl.java:1586)

 at 
weblogic.transaction.internal.WLSTimer.timerExpired(WLSTimer.java:35)
 at weblogic.timers.internal.TimerImpl.run(TimerImpl.java:273)
 at 
weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:545)

 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
; nested exception is: weblogic.transaction.internal.TimedOutException: 
Transaction timed out after 30 seconds 
BEA1-484455D7A39364D50D1F

The solution is typically to increase the transaction timeout for the process.
But how do we could configure transaction timeout for BPEL on SOA 11g?

In the first, before we start changing, we should keep in mind two generall rules:
  • This solution is ONLY applicable to Sync Processes
  • syncMaxWaitTime < BPEL EJB's transaction timeout < Global Transaction Timeout

Let's start from syncMaxWaitTime. This property controls the maximum time the process result receiver will wait for a result before returning for Sync processes.

To change default value you should run Enterprise Manager and go to Farm -> SOA -> "soa-infra" branch and next select from context menu: SOA Administration -> BPEL Properties and expand "More BPEL Configuration Properties...".


Next thing you can change is BPEL EJB's transaction timeout. You can/should update the timeout for following EJB's:
  • BPELActivityManagerBean
  • BPELDeliveryBean
  • BPELDispatcherBean
  • BPELEngineBean
  • BPELFinderBean
  • BPELInstanceManagerBean
  • BPELProcessManagerBean
  • BPELSensorValuesBean
  • BPELServerManagerBean
The timeout properties for the EJBs control the particular timeout setting for the SOA application, overriding the global setting specified by the JTA timeou.

To perform changes you have to run Administration Console, stop SOA server/cluster and next go to Deployments -> soa-infra and expand this position:


For each of cited EJB's you can change default timeout value in Configuration tab (you have to click on selected EJB to view its properties and next select second tab described as Configuration).

To modify Global Transaction Timeout go to Services -> JTA in Administration Console, as shown below:


After applying this change you have to restart Weblogic Domain.


Tuesday, November 5, 2013

New and usefull services in WebcenterContent 11.1.1.8

In last version of WebcenterContent (UCM) I found two, new, very usefull services. The first of them is COPY_REVISION service.

The COPY_REVISION service copies one document revision, creating a new rev class from it. As says "Services Reference for Oracle WebCenter Content" most of the document metadata from the original revision will be carried over. The caller can also overwrite any metadata value by setting it in the request parameters.

You can use COPY_REVISION service as shown below:

// Databinder for Creating the clone request

DataBinder dataBinder = idcClient.createBinder();
dataBinder.putLocal("IdcService", "COPY_REVISION");

//Original Content dID and Content Id (dDocname)
dataBinder.putLocal("dID","1001");
dataBinder.putLocal("dDocName","001001");

//clone item Content ID - this is not mandatory - If set to Auto Content ID this need not be added 
//dataBinder.putLocal("newdDocName","Cloned_item");

//The user only needs READ permissions to the original document revision. 
//However, because the new revision inherits the metadata of the original, new security metadata values 
//must be set if the user does not have WRITE permissions to the original revision. By example you can modify group and ACL
dataBinder.putLocal("dSecurityGroup","New_better_group");
dataBinder.putLocal("xClbraUserList","your_user(RW)");

//If the original content is in a Contribution Folder (Folders_g) then below parameter is mandatory - Either blank Collection ID or set a new Folder ID
//In case of Framework Folder this parameter is not needed
dataBinder.putLocal("xCollectionID","1214234324324324");

//Clone Item's Content Title
dataBinder.putLocal("dDocTitle","Title-cloned");

//Any other new / custom metadata for Clone Item
dataBinder.putLocal("Custom","Clone Item Metadata");

Service returns two ResultSets:
  • NewDocInfo: Information about the newly created document.
  • OriginalDocInfo: Information about the original document that was copied.
Next interesting service is RESTORE_REVISION. The service restores the document revision corresponding to the supplied dID as a new (latest) revision.

To call this service you should supply only dID of source revision:


// Databinder for Creating the restore request

DataBinder dataBinder = idcClient.createBinder();
dataBinder.putLocal("IdcService", "RESTORE_REVISION");

//Original Content dID
dataBinder.putLocal("dID","1001");

As the results the service returns:
  • dID: The document ID of the new revision created.
  • dDocName: The document name of the new revision created.
  • dDocTitle: The document title of the new revision created.

HowTo: How to create JAX_WS WebMethod which returns a complex type, by example java.util.HashMap

In simple words, you can't do this directly. The only way is use of workaround.

But one by one. I decided to write this post after reading a few threads on Oracle's Forum. By example this thread: https://forums.oracle.com/message/7015500. I found also many other posts with issues "what to do when WebMethod returns null value instedad of complex type" - which is a typical symptom when you try to return an unacceptable type.

As says Java EE 6 Tutorial:

"JAX-WS delegates the mapping of Java programming language types to and from XML definitions to JAXB. Application developers don’t need to know the details of these mappings but should be aware that not every class in the Java language can be used as a method parameter or return type in JAX-WS."

next we have a list of Schema-to-Java mappings:

XML Schema Type Java Data Type
xsd:string java.lang.String
xsd:integer java.math.BigInteger
xsd:int int
xsd.long long
xsd:short short
xsd:decimal java.math.BigDecimal
xsd:float float
xsd:double double
xsd:boolean boolean
xsd:byte byte
xsd:QName javax.xml.namespace.QName
xsd:dateTime javax.xml.datatype.XMLGregorianCalendar
xsd:base64Binary byte[]
xsd:hexBinary byte[]
xsd:unsignedInt long
xsd:unsignedShort int
xsd:unsignedByte short
xsd:time javax.xml.datatype.XMLGregorianCalendar
xsd:date javax.xml.datatype.XMLGregorianCalendar
xsd:g javax.xml.datatype.XMLGregorianCalendar
xsd:anySimpleType java.lang.Object
xsd:anySimpleType java.lang.String
xsd:duration javax.xml.datatype.Duration
xsd:NOTATION javax.xml.namespace.QName

and Java-to-Schema mappings:

Java Class XML Data Type
java.lang.String xs:string
java.math.BigInteger xs:integer
java.math.BigDecimal xs:decimal
java.util.Calendar xs:dateTime
java.util.Date xs:dateTime
javax.xml.namespace.QName xs:QName
java.net.URI xs:string
javax.xml.datatype.XMLGregorianCalendar xs:anySimpleType
javax.xml.datatype.Duration xs:duration
java.lang.Object xs:anyType
java.awt.Image xs:base64Binary
javax.activation.DataHandler xs:base64Binary
javax.xml.transform.Source xs:base64Binary
java.util.UUID xs:string

If your desired type wasn't listed above, you have to come up with some workaround. For types like lists and maps you can convert those types to array of simple java types. By example:

/**
* We need return Map<String,String> but because we can't do this, 
* we would use workaround and return an two-dimensional array of Strings
*/

@WebMethod()
@WebResult(name="MyMethod",targetNamespace="http://my-java-planet.blogspot.com/my-java-planet")
public String[][] MyMethod(
        @WebParam(name="Symbol",targetNamespace="http://my-java-planet.blogspot.com/my-java-planet") 
        String projectSymbol,             
        @WebParam(name="Year",targetNamespace="http://my-java-planet.blogspot.com/my-java-planet") 
        String projectYear)
{

      try
      {
             LinkedHashMap<String,String> re = getData(projectSymbol, projectYear); 
             
             String ra[][] = new String[re.size()][2]; 
             int i = 0; 
             for(Map.Entry<String,String> entry : re.entrySet())
             { 
                         ra[i][0] = entry.getKey(); 
                         ra[i][1] = entry.getValue(); 
                         i++; 
             } 
             return ra; 
      } 
      catch (Exception ex) 
      { 
             String methodName=Thread.currentThread().getStackTrace()[1].getMethodName();
             logger.severe("Exception "+ex.getMessage()+" in "+methodName );
             String re[][] = new String[][]{{"ERROR",ex.getMessage()}};
      }
}