001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.lang;
027:
028: /**
029: * <p>Any component that implements this interface indicates it is able to
030: * accept method calls asynchronously. Clients and/or containers of the
031: * component have the option to call the <code>handle()</code> method rather
032: * than the work interface method directly.</p>
033: *
034: * <div style="float: right; border: 1px solid #003399; padding: 10px"
035: * class="toc"> <b>Table of contents</b> <ul> <li>Documentation <ul> <li><a
036: * href="#TheAsyncEnabledContract">The <code>AsyncEnabled</code>
037: * Contract</a></li> <li><a href="#DealingWithReturnValues">Dealing With Return
038: * Values</a></li> <li><a href="#ACompleteExample">A Complete Example</a></li>
039: * </ul></li> <li>API <ul> <!--<li>Fields: <a href="#field_summary">Summary</a>
040: * | <a href="#field_detail">Details</a></li> <li>Constructors: <a
041: * href="#constructor_summary">Summary</a> | <a href="#constructor_detail">Details</a></li>-->
042: * <li>Methods: <a href="#method_summary">Summary</a> | <a
043: * href="#method_detail">Details</a></li> </ul> </li> </ul> </div>
044: *
045: * <a name="TheAsyncEnabledcontract"></a> <h3>The <code>AsyncEnabled</code>
046: * contract</h3>
047: *
048: * <p>This interface is intentionally very broad. In fact, its method signature
049: * could be used for an <code>Interceptor</code> as well, and thus even be the
050: * basis of a generic Aspect-Oriented Programming tool. That's not the
051: * intention here: the contract surrounding AsyncEnabled is more specific.</p>
052: *
053: * <p>The invocation passed to the {@link #handle(Invocation)} method should be
054: * an invocation that should be directly applicable to the receiving instance.
055: * In other words, the following implementation should always produce correct
056: * behaviour:</p>
057: *
058: * <pre style="clear: both;">
059: * // FRAGMENT
060: * AsyncEnabled instance = new SomeAsyncEnabled()
061: * {
062: * public Object handle( Invocation invocation )
063: * {
064: * return invocation.getMethod().invoke( this, invocation.getArgs() );
065: * }
066: * public String someMethod()
067: * {
068: * return "Hello Asynchronous client";
069: * }
070: * }
071: * </pre>
072: *
073: * <p>This means that the first call in the code below is okay, while the
074: * second one is problematic.</p>
075: *
076: * <pre>
077: * // FRAGMENT
078: * // this is okay....
079: * Method m = instance.getClass().getMethod( "someMethod", new Object[0] );
080: * Object[] args = new Object[0];
081: * Invocation invocation = new Invocation( instance, null, m, args );
082: * instance.handle( invocation ); // returns "Hello Asynchronous client"
083: *
084: * // but this is not!
085: * Method m = SomeClass.getClass().getMethod( "doStuff", new Object[0] );
086: * Object[] args = new Object[0];
087: * Invocation invocation = new Invocation( instance, null, m, args );
088: * instance.handle( invocation );
089: * // exception: can't invoke SomeClass.doStuff() on instance!
090: * </pre>
091: *
092: * <p>Furthermore, you should not assume that all methods of an
093: * <code>AsyncEnabled</code> class can be invoked asynchronously. The mechanism
094: * to determine whether any particular method can indeed be invoked
095: * asynchronously is not specified by this interface, but I suggest clear API
096: * documentation in addition to any other mechanisms.</p>
097: *
098: * <a name="DealingWithReturnValues"></a> <h3>Dealing with return values</h3>
099: *
100: * <p>When a method is invoked asynchronously, it is not possible for the
101: * caller to receive the return value of that method directly. This is best
102: * solved by using a <b>callback</b>.</p>
103: *
104: * <p>A callback is an object that the caller supplies as an argument to the
105: * method call. The <code>AsyncEnabled</code> component will, on completion of
106: * the asynchronous call, provide the return value to the callback object. In
107: * the simplest case, the callback object is simply the caller itself, and the
108: * return value is provided through some kind of simple setter method. The
109: * below is a simple example; much more elaborate setups are possible.</p>
110: *
111: * <a name="ACompleteExample"></a> <h3>A Complete Example</h3>
112: *
113: * <p>In the below example, the <code>Client</code> class will send its
114: * commandline arguments asynchronously to an <code>AsyncService</code>. This
115: * service creates a thread (which sleeps for a random time just to demonstrate
116: * how asynchronous it all is) to process the argument, sending the result back
117: * to the <code>Client</code> via the <code>Callback</code> interface. Of
118: * course, this example is as contrived as any!</p>
119: *
120: * <pre>
121: * // SAMPLE CODE
122: * interface Callback
123: * {
124: * public void receiveResult( Object result, long uniqueIdentifier );
125: * }
126: * interface SomeService
127: * {
128: * public String doSomethingImmediately( String argument );
129: * }
130: * public void doSomething( String argument,
131: * Callback callback long uniqueIdentifier );
132: * }
133: * class AsyncService implements AsyncEnabled, SomeService
134: * {
135: * public Object handle( Invocation invocation )
136: * {
137: * new Thread( new Runnable()
138: * {
139: * public void run()
140: * {
141: * Thread.sleep((int)(Math.random()*1000));
142: * invocation.getMethod().invoke( this, invocation.getArgs() );
143: * } }.start();
144: * return null;
145: * }
146: * public String doSomethingImmediately( String argument )
147: * {
148: * return "task " + * argument + " done!";
149: * }
150: *
151: * public void doSomething( String argument, Callback callback,
152: * long uniqueIdentifier )
153: * {
154: * Object result = doSomethingImmediately( argument );
155: * callback.receiveResult( result, uniqueIdentifier );
156: * }
157: * }
158: * public class Client implements Callback
159: * {
160: * public static long uniqueIdentifier = 0;
161: *
162: * public void receiveResult( Object result, long uniqueIdentifier )
163: * {
164: * System.out.println("received results of invocation " +
165: * uniqueIdentifier + ": " + result;
166: * }
167: *
168: * public void main( String[] args )
169: * {
170: * AsyncService service = new AsyncService();
171: *
172: * for( int i = 0; i < args.length; i++ )
173: * {
174: * String arg = args[i];
175: * long id = uniqueIdentifier++;
176: * Invocation inv = new Invocation( service, null,
177: * service.getClass().getMethod("doSomething",
178: * new Class[] { String.class, Callback.class, Long.class } ),
179: * new Object[] { args[i], this, id } );
180: * service.handle( inv );
181: * }
182: * }
183: * }
184: * </pre>
185: *
186: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
187: * @version $Id: AsyncEnabled.java,v 1.1 2004/03/23 13:37:56 lsimons Exp $
188: */
189: public interface AsyncEnabled {
190: /**
191: * Asynchronously deal with a 'method call'.
192: *
193: * @param invocation
194: *
195: * @return the value to return to the calling object. Usually this will be
196: * null as asynchronous communication is likely to work using
197: * callbacks.
198: * @throws UnsupportedInvocationException
199: */
200: public Object handle(Invocation invocation)
201: throws UnsupportedInvocationException, InterruptedException;
202: }
|