001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package javax.util.concurrent;
018
019 import java.util.Map;
020
021 /**
022 * The ContextService provides methods for creating <i>contextual dynamic proxy</i>
023 * objects.
024 * <p>
025 *
026 * The proxy objects follow the same rules as defined for the
027 * {@link java.lang.reflect.Proxy} class with the following additions:
028 * <ul>
029 * <li>The proxy instance will retain the context of the application
030 * container's thread (creator's context).
031 * <li>The proxy instance will implement all of the interfaces specified on the
032 * <code>createContextObject</code> methods.
033 * <li>All interface method invocations on a proxy instance run in the
034 * creator's context.
035 * <li>Invocation of the <code>hashCode</code>, <code>equals</code>, and
036 * <code>toString</code> methods declared in <code>java.lang.Object</code>
037 * on a sproxy instance will not run in the creator's context.
038 * <li>The proxy instance must implement <code>java.io.Serializable</code>.
039 * <li>The proxied object instance must implement
040 * <code>java.io.Serializable</code> if the proxy instance is serialized.
041 * <li>Context properties can be stored with the proxy instance. Custom
042 * property keys must not begin with "ctxsvc.".
043 * <li>Context properties are to be used for controlling how various contextual
044 * information is retreived and applied to the thread. Although application
045 * components can store arbitrary property keys and values, it is not
046 * recommended. Java EE product providers may impose limits to the size of the
047 * keys and values.
048 * <li>Context property keys and values must all be of type
049 * <code>java.lang.String</code>. Use of the <code>put</code> and
050 * <code>putAll</code> methods on the <code>java.util.Hashtable</code>
051 * superclass are discouraged.
052 * </ul>
053 *
054 */
055 public interface ContextService {
056 /**
057 * A contextual object property that disables the normal transaction
058 * suspension and UserTransaction access from the proxied methods.
059 * <p>
060 *
061 * If "false" (the default if unspecified), any transaction that is
062 * currently active on the thread will be suspended and a UserTransaction
063 * (accessible in the local JNDI namespace as "java:comp/UserTransaction")
064 * will be available. When the proxied method returns the original
065 * transaction is restored.
066 * <p>
067 *
068 * If "true", the proxied method will run within the transaction (if any) of
069 * the current thread. A UserTransaction will only be available if the the
070 * container thread (for example, a Servlet or Bean Managed Transaction
071 * EJB).
072 */
073 public String USE_PARENT_TRANSACTION = "ctxsvc.useparenttran";
074
075 /**
076 * Creates a new contextual object proxy for the input object instance.
077 * <p>
078 *
079 * Each method invocation will have the context of the application component
080 * instance that created the context object.
081 * <p>
082 *
083 * The contextual object is useful when developing or using Java SE
084 * threading mechanisms spraying events to other component instances or
085 * communicating with component instances on different Java processes.
086 * <p>
087 *
088 * If the application component that created the proxy is started or
089 * deployed, all methods on reflected interfaces will throw a
090 * <code>java.lang.IllegalState</code> exception.
091 * <p>
092 *
093 * For example, to call a normal Runnable with the correct context using a
094 * Java™ ExecutorService:
095 * <P>
096 *
097 * <pre>
098 * public class MyRunnable implements Runnable {
099 * public void run() {
100 * System.out.println("MyRunnable.run with J2EE Context available.");
101 * }
102 * }
103 *
104 * InitialContext ctx = new InitialContext();
105 *
106 * ThreadFactory threadFactory = (ThreadFactory) ctx
107 * .lookup("java:comp/env/concurrent/ThreadFactory");
108 *
109 * ContextService ctxService = (ContextService) ctx
110 * .lookup("java:comp/env/concurrent/ContextService");
111 *
112 * Object rProxy = ctxService.createContextObject(myRunnableInstance,
113 * new Class[] { Runnable.class });
114 *
115 * ExecutorService exSvc = Executors.newThreadPool(10, threadFactory);
116 *
117 * Future f = exSvc.submit((Runnable) rProxy);
118 * </pre>
119 *
120 * @param instance
121 * the instance of the object to proxy.
122 * @param interfaces
123 * the interfaces that the proxy should implement.
124 * @return a proxy for the input object that implements all of the specified
125 * interfaces.
126 * @throws IllegalArgumentException
127 * if the Class does not have an interface or there is not an
128 * accessible default constructor.
129 */
130 public Object createContextObject(Object instance, Class<?>[] interfaces);
131
132 /**
133 * Creates a new contextual object proxy for the input object instance.
134 * <p>
135 *
136 * The contextual object is useful when developing or using Java SE
137 * threading mechanisms spraying events to other component instances or
138 * communicating with component instances on different Java processes.
139 * <p>
140 *
141 * If the application component that created the proxy is started or
142 * deployed, all methods on reflected interfaces will throw a
143 * <code>java.lang.IllegalState</code> exception.
144 * <p>
145 *
146 * This method accepts a {@link Properties} object which allows the
147 * contextual object creator to define what contexts or behaviors to capture
148 * when creating the contextual object. The specified properties will remain
149 * with the contextual object until the properties are updated or removed
150 * using the {@link #setProperties(Object, Properties)} method.
151 * <p>
152 *
153 * For example, to call a Message Driven Bean (MDB) with the sender's
154 * context, but within the MDB's transaction:
155 * <P>
156 *
157 * <pre>
158 * public class MyServlet ... {
159 * public void doPost() throws NamingException, JMSException {
160 * InitialContext ctx = new InitialContext();
161 *
162 * // Get the ContextService that only propagates
163 * // security context.
164 * ContextService ctxSvc = (ContextService)
165 * ctx.lookup("java:comp/env/SecurityContext");
166 *
167 * // Set any custom context data.
168 * Properties ctxProps = new Properties();
169 * ctxProps.setProperty("vendor_a.security.tokenexpiration", "15000");
170 *
171 * ProcessMessage msgProcessor =
172 * (ProcessMessage) ctxSvc.createContextObject(new MessageProcessor(),
173 * new Class[]{ProcessMessage.class},
174 * ctxProps);
175 *
176 * ConnectionFactory cf = (ConnectionFactory)
177 * ctx.lookup("java:comp/env/MyTopicConnectionFactory");
178 * Destination dest = (Destination) ctx.lookup("java:comp/env/MyTopic");
179 * Connection con = cf.createConnection();
180 *
181 * Session session = con.createSession(true, Session.AUTO_ACKNOWLEDGE);
182 * MessageProducer producer = session.createProducer(dest);
183 *
184 * Message msg = session.createObjectMessage((Serializable)msgProcessor);
185 * producer.send(dest, msg);
186 * ...
187 *
188 * }
189 *
190 * public class MyMDB ... {
191 * public void onMessage(Message msg) {
192 * // Get the ProcessMessage context object from the message.
193 * ObjectMessage omsg = (ObjectMessage)msg;
194 * ProcessMessage msgProcessor = (ProcessMessage)omsg.getObject();
195 *
196 * // Update the context object and verify that the processMessage()
197 * // method runs inside the current transaction. If we have a failure,
198 * // we don't want to consume the message.
199 * InitialContext ctx = new InitialContext();
200 * ContextService ctxSvc = (ContextService)
201 * ctx.lookup("java:comp/env/SecurityContext");
202 * Properties ctxProps = ctxSvc.getProperties(msgProcessor);
203 * ctxProps.setProperty(ContextService.USE_PARENT_TRANSACTION, "true");
204 * ctxSvc.setProperties(msgProcessor, ctxProps);
205 *
206 * // Process the message in the specified context.
207 * msgProcessor.processMessage(msg);
208 * }
209 * }
210 *
211 * public interface ProcessMessage {
212 * public void processMessage(Message msg);
213 * }
214 *
215 * public class MessageProcessor implements ProcessMessage, Serializable {
216 * public void processMessage(Message msg) {
217 * // Process the message with the application container
218 * // context that sent the message.
219 *
220 * }
221 * }
222 * </pre>
223 *
224 * @param instance
225 * the instance of the object to proxy.
226 * @param interfaces
227 * the interfaces that the proxy should implement.
228 * @param contextProperties
229 * the properties to use when creating and running the context
230 * object.
231 * @return a proxy for the input object that implements all of the specified
232 * interfaces.
233 * @throws IllegalArgumentException
234 * if the Class does not have an interface or there is not an
235 * accessible default constructor.
236 * @throws ClassCastException
237 * thrown if one of the keys or values in the specified
238 * Properties object are not of type String.
239 */
240 public Object createContextObject(Object instance, Class<?>[] interfaces,
241 Map<String, String> contextProperties);
242
243 /**
244 * Sets the properties on the context proxy instance.
245 * <p>
246 *
247 * All property keys and values must be strings. Storing other class types
248 * may result in a <code>java.lang.ClassCastException</code>.
249 *
250 * @param contextObject
251 * the contextual proxy instance to set the properties.
252 * @param contextProperties
253 * the properties to use when running the context object. Specify
254 * an empty Properties object to erase all current properties.
255 * @throws IllegalArgumentException
256 * thrown if the input contextObject is not a valid contextual
257 * object proxy created with the
258 * <code>createContextObject</code> method.
259 * @throws ClassCastException
260 * thrown if one of the keys or values in the specified
261 * Properties object are not of type String.
262 */
263 public void setProperties(Object contextObject, Map<String, String> contextProperties);
264
265 /**
266 * Gets the current properties on the context proxy instance.
267 *
268 * @param contextObject
269 * the contextual proxy instance to set the properties.
270 * @return the current context object properties
271 * @throws IllegalArgumentException
272 * thrown if the input contextObject is not a valid contextual
273 * object proxy created with the
274 * <code>createContextObject</code> method.
275 */
276 public Map<String, String> getProperties(Object contextObject);
277 }