001// 002// Name 003// $RCSfile: Asynchronous.java,v $ 004// 005// Copyright 006// Copyright 2010-2015 Cloud Software Group, Inc. ALL RIGHTS RESERVED. 007// Cloud Software Group, Inc. Confidential Information 008// 009// History 010// $Revision: 1.1.2.5 $ $Date: 2015/01/27 03:23:59 $ 011// 012package com.kabira.platform.annotation; 013 014import com.kabira.platform.Transaction; 015 016import java.lang.annotation.Documented; 017import java.lang.annotation.ElementType; 018import java.lang.annotation.Inherited; 019import java.lang.annotation.Retention; 020import java.lang.annotation.RetentionPolicy; 021import java.lang.annotation.Target; 022 023/** 024 * Annotation to indicate whether a method should be executed 025 * asynchronously. 026 * <p> 027 * The default behavior is to execute a Managed object method synchronously 028 * within the calling transaction. When annotated as @Asynchronous, a method 029 * runs asynchronously in a separate transaction. A new transaction is 030 * transparently started for the method, and deadlocks are automatically 031 * retried. 032 * <p> 033 * If the work done in an asynchronous method is supposed to be rolled 034 * back, the method should throw a {@link 035 * com.kabira.platform.Transaction.Rollback} exception. 036 * <p> 037 * A method annotated as @Asynchronous must have a void return and 038 * parameters are restricted to those types supported for Managed objects. 039 * <p> 040 * The {@link com.kabira.platform.Transaction.Result} of an asynchronous 041 * method is not available to an application. Applications that need to 042 * keep track of this need to implement a separate non-transactional 043 * mechanism to track this. 044 * <p> 045 * Execution of asynchronous methods have the following behavior: 046 * <ul> 047 * <li> The method is executed and the enclosed transaction started after 048 * the calling transaction commits. 049 * <li> If the calling transaction is rolled back, the method is not 050 * executed. 051 * <li> The runtime guarantees that the method executes to completion 052 * once and only once. 053 * <li> Multiple calls to an asynchronous method on a same Managed object 054 * instance are guaranteed to execute in the same order. Given: 055 *<pre>@Managed 056class MyClass 057{ 058 @Asynchronous 059 void asyncOp(int val); 060} 061new Transaction() 062{ 063 @Override 064 public void run() 065 { 066 ... 067 myObj.asyncOp(1); 068 myObj.asyncOp(2); 069 } 070}.execute();</pre> 071 * The runtime insures that asyncOp() is called with val==1 first. 072 * Execution of asynchronous methods on different instances have no 073 * order guarantees. 074 * </ul> 075 * <p> 076 * It is important to note that execution of an asynchronous method and 077 * its associated transaction only happen after the calling transaction 078 * commits, <b>it is not executed</b> if the calling transaction is 079 * rolled back for any reason. 080 * <p> 081 * If the @Asynchronous annotation is used on a method for a class that 082 * isn't @Managed, the annotation is ignored. 083 * @see com.kabira.platform.annotation.Managed 084 * @see com.kabira.platform.Transaction 085 * @see com.kabira.platform.Transaction.Rollback 086 */ 087@Documented 088@Inherited 089@Retention(RetentionPolicy.RUNTIME) 090@Target(ElementType.METHOD) 091public @interface Asynchronous 092{ 093 /** 094 * Define the transaction isolation level used when running 095 * this transaction. 096 @return IsolationLevel 097 */ 098 Transaction.IsolationLevel isolationLevel() 099 default Transaction.IsolationLevel.SERIALIZABLE; 100}