KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > umo > FutureMessageResult


1 /*
2  * $Id: FutureMessageResult.java 3798 2006-11-04 04:07:14Z aperepel $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 package org.mule.umo;
12
13 import edu.emory.mathcs.backport.java.util.concurrent.Callable;
14 import edu.emory.mathcs.backport.java.util.concurrent.ExecutionException;
15 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
16 import edu.emory.mathcs.backport.java.util.concurrent.Executors;
17 import edu.emory.mathcs.backport.java.util.concurrent.FutureTask;
18 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
19 import edu.emory.mathcs.backport.java.util.concurrent.TimeoutException;
20
21 import org.mule.impl.MuleMessage;
22 import org.mule.umo.transformer.TransformerException;
23 import org.mule.umo.transformer.UMOTransformer;
24 import org.mule.util.concurrent.DaemonThreadFactory;
25
26 /**
27  * <code>FutureMessageResult</code> is an UMOMessage result of a remote invocation
28  * on a Mule Server. This object makes the result available to the client code once
29  * the request has been processed. This execution happens asynchronously.
30  */

31 // @ThreadSafe
32
public class FutureMessageResult extends FutureTask
33 {
34     /**
35      * This is a simple default Executor for FutureMessageResults. Instead of
36      * spawning a Thread for each invocation it uses a single daemon Thread with an
37      * unbounded queue, so "truly" concurrent operation of multiple Futures or
38      * otherwise customized execution behaviour requires calling the
39      * {@link #setExecutor(Executor)} method and passing in a custom {@link Executor}.
40      * This is strongly recommended in order to provide better control over
41      * concurrency, resource consumption and possible overruns.
42      * <p>
43      * Reasons for these defaults:
44      * <ul>
45      * <li> a daemon thread does not block the VM on shutdown; lifecycle control
46      * should be done elsewhere (e.g. the provider of the custom ExecutorService),
47      * otherwise this class would become too overloaded
48      * <li> a single thread provides for conservative & predictable yet async
49      * behaviour from a client's point of view
50      * <li> the unbounded queue is not optimal but probably harmless since e.g. a
51      * MuleClient would have to create a LOT of Futures for an OOM. Cancelled/timed
52      * out invocations are GC'ed so the problem is rather unlikely to occur.
53      * </ul>
54      */

55     private static final Executor DefaultExecutor = Executors.newSingleThreadExecutor(new DaemonThreadFactory(
56         "MuleDefaultFutureMessageExecutor"));
57
58     // @GuardedBy(this)
59
private Executor executor;
60     // @GuardedBy(this)
61
private UMOTransformer transformer;
62
63     public FutureMessageResult(Callable callable)
64     {
65         super(callable);
66         this.executor = DefaultExecutor;
67     }
68
69     /**
70      * @deprecated Please use {@link #FutureMessageResult(Callable)} and configure
71      * e.g with {@link #setExecutor(Executor)} or
72      * {@link #setTransformer(UMOTransformer)}
73      */

74     public FutureMessageResult(Callable callable, UMOTransformer transformer)
75     {
76         this(callable);
77         this.transformer = transformer;
78     }
79
80     /**
81      * Set a post-invocation transformer.
82      *
83      * @param t UMOTransformer to be applied to the result of this invocation. May be
84      * null.
85      */

86     public void setTransformer(UMOTransformer t)
87     {
88         synchronized (this)
89         {
90             this.transformer = t;
91         }
92     }
93
94     /**
95      * Set an ExecutorService to run this invocation.
96      *
97      * @param e the executor to be used.
98      * @throws IllegalArgumentException when the executor is null or shutdown.
99      */

100     public void setExecutor(Executor e)
101     {
102         if (e == null)
103         {
104             throw new IllegalArgumentException JavaDoc("Executor must not be null.");
105         }
106
107         synchronized (this)
108         {
109             this.executor = e;
110         }
111     }
112
113     public UMOMessage getMessage() throws InterruptedException JavaDoc, ExecutionException, TransformerException
114     {
115         return this.getMessage(this.get());
116     }
117
118     public UMOMessage getMessage(long timeout)
119         throws InterruptedException JavaDoc, ExecutionException, TimeoutException, TransformerException
120     {
121         return this.getMessage(this.get(timeout, TimeUnit.MILLISECONDS));
122     }
123
124     private UMOMessage getMessage(Object JavaDoc obj) throws TransformerException
125     {
126         if (obj != null)
127         {
128             if (obj instanceof UMOMessage)
129             {
130                 return (UMOMessage)obj;
131             }
132
133             synchronized (this)
134             {
135                 if (transformer != null)
136                 {
137                     obj = transformer.transform(obj);
138                 }
139             }
140
141             return new MuleMessage(obj);
142         }
143         else
144         {
145             return null;
146         }
147     }
148
149     /**
150      * Start asynchronous execution of this task
151      */

152     public void execute()
153     {
154         synchronized (this)
155         {
156             executor.execute(this);
157         }
158     }
159
160 }
161
Popular Tags