KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > MessageDrivenContainer


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Hashtable JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import javax.ejb.CreateException JavaDoc;
31 import javax.ejb.EJBMetaData JavaDoc;
32 import javax.ejb.EJBObject JavaDoc;
33 import javax.ejb.Handle JavaDoc;
34 import javax.ejb.HomeHandle JavaDoc;
35 import javax.ejb.RemoveException JavaDoc;
36 import javax.ejb.TimedObject JavaDoc;
37 import javax.ejb.Timer JavaDoc;
38 import javax.ejb.EJBException JavaDoc;
39 import javax.management.ObjectName JavaDoc;
40
41 import org.jboss.invocation.Invocation;
42 import org.jboss.metadata.MessageDrivenMetaData;
43 import org.jboss.util.NullArgumentException;
44
45 /**
46  * The container for <em>MessageDriven</em> beans.
47  *
48  * @author <a HREF="mailto:peter.antman@tim.se">Peter Antman</a>.
49  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
50  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
51  * @author <a HREF="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
52  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
53  * @author <a HREF="mailto:Scott.Stark@jboss.org">Scott Stark</a>
54  * @version $Revision: 41236 $
55  *
56  * @jmx:mbean extends="org.jboss.ejb.ContainerMBean"
57  */

58 public class MessageDrivenContainer
59       extends Container
60       implements EJBProxyFactoryContainer, InstancePoolContainer, MessageDrivenContainerMBean
61 {
62    /**
63     * These are the mappings between the remote interface methods
64     * and the bean methods.
65     */

66    protected Map JavaDoc beanMapping;
67
68    /** This is the instancepool that is to be used. */
69    protected InstancePool instancePool;
70
71    /**
72     * This is the first interceptor in the chain.
73     * The last interceptor must be provided by the container itself.
74     */

75    protected Interceptor interceptor;
76
77    protected long messageCount;
78
79    public LocalProxyFactory getLocalProxyFactory()
80    {
81       return localProxyFactory;
82    }
83
84    public void setInstancePool(final InstancePool instancePool)
85    {
86       if (instancePool == null)
87          throw new NullArgumentException("instancePool");
88
89       this.instancePool = instancePool;
90       this.instancePool.setContainer(this);
91    }
92
93    public InstancePool getInstancePool()
94    {
95       return instancePool;
96    }
97
98    public void addInterceptor(Interceptor in)
99    {
100       if (interceptor == null)
101       {
102          interceptor = in;
103       }
104       else
105       {
106          Interceptor current = interceptor;
107
108          while (current.getNext() != null)
109          {
110             current = current.getNext();
111          }
112
113          current.setNext(in);
114       }
115    }
116
117    public Interceptor getInterceptor()
118    {
119       return interceptor;
120    }
121
122    /**
123     * @jmx:managed-attribute
124     * @return the number of messages delivered
125     */

126    public long getMessageCount()
127    {
128       return messageCount;
129    }
130
131    /**
132     * EJBProxyFactoryContainer - not needed, should we skip inherit this
133     * or just throw Error??
134     */

135    public Class JavaDoc getHomeClass()
136    {
137       //throw new Error("HomeClass not valid for MessageDriven beans");
138
return null;
139    }
140
141    public Class JavaDoc getRemoteClass()
142    {
143       //throw new Error("RemoteClass not valid for MessageDriven beans");
144
return null;
145    }
146
147    public Class JavaDoc getLocalClass()
148    {
149       return null;
150    }
151
152    public Class JavaDoc getLocalHomeClass()
153    {
154       //throw new Error("LocalHomeClass not valid for MessageDriven beans");
155
return null;
156    }
157
158    // Container implementation - overridden here ----------------------
159

160    protected void createService() throws Exception JavaDoc
161    {
162       // Associate thread with classloader
163
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
164       SecurityActions.setContextClassLoader(getClassLoader());
165
166       try
167       {
168          // Call default init
169
super.createService();
170
171          // Map the bean methods
172
Map JavaDoc map = new HashMap JavaDoc();
173          MessageDrivenMetaData mdMetaData = (MessageDrivenMetaData)metaData;
174          Class JavaDoc clazz = getClassLoader().loadClass(mdMetaData.getMessagingType());
175          Method JavaDoc[] methods = clazz.getDeclaredMethods();
176          for (int i = 0; i < methods.length; i++)
177          {
178             Method JavaDoc m = methods[i];
179             map.put(m, beanClass.getMethod(m.getName(), m.getParameterTypes()));
180             log.debug("Mapped " + m.getName() + " " + m.hashCode() + " to " + map.get(m));
181          }
182          if( TimedObject JavaDoc.class.isAssignableFrom( beanClass ) ) {
183              // Map ejbTimeout
184
map.put(
185                 TimedObject JavaDoc.class.getMethod( "ejbTimeout", new Class JavaDoc[] { Timer JavaDoc.class } ),
186                 beanClass.getMethod( "ejbTimeout", new Class JavaDoc[] { Timer JavaDoc.class } )
187              );
188          }
189          beanMapping = map;
190
191          // Try to register the instance pool as an MBean
192
try
193          {
194             ObjectName JavaDoc containerName = super.getJmxName();
195             Hashtable JavaDoc props = containerName.getKeyPropertyList();
196             props.put("plugin", "pool");
197             ObjectName JavaDoc poolName = new ObjectName JavaDoc(containerName.getDomain(), props);
198             server.registerMBean(instancePool, poolName);
199          }
200          catch(Throwable JavaDoc t)
201          {
202             log.debug("Failed to register pool as mbean", t);
203          }
204          // Initialize pool
205
instancePool.create();
206
207          for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext();)
208          {
209             String JavaDoc invokerBinding = (String JavaDoc) it.next();
210             EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
211             // Try to register the container invoker as an MBean
212
try
213             {
214                ObjectName JavaDoc containerName = super.getJmxName();
215                Hashtable JavaDoc props = containerName.getKeyPropertyList();
216                props.put("plugin", "invoker");
217                props.put("binding", invokerBinding);
218                ObjectName JavaDoc invokerName = new ObjectName JavaDoc(containerName.getDomain(), props);
219                server.registerMBean(ci, invokerName);
220             }
221             catch(Throwable JavaDoc t)
222             {
223                log.debug("Failed to register invoker binding as mbean", t);
224             }
225             ci.create();
226          }
227
228          // Initialize the interceptor by calling the chain
229
Interceptor in = interceptor;
230          while (in != null)
231          {
232             in.setContainer(this);
233             in.create();
234             in = in.getNext();
235          }
236
237       }
238       finally
239       {
240          // Reset classloader
241
SecurityActions.setContextClassLoader(oldCl);
242       }
243    }
244
245    protected void startService() throws Exception JavaDoc
246    {
247       // Associate thread with classloader
248
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
249       SecurityActions.setContextClassLoader(getClassLoader());
250
251       try
252       {
253          // Call default start
254
super.startService();
255
256          // Start the instance pool
257
instancePool.start();
258
259          // Start all interceptors in the chain
260
Interceptor in = interceptor;
261          while (in != null)
262          {
263             in.start();
264             in = in.getNext();
265          }
266
267          // Start container invoker
268
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext();)
269          {
270             String JavaDoc invokerBinding = (String JavaDoc) it.next();
271             EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
272             ci.start();
273          }
274          
275          // Restore persisted ejb timers
276
restoreTimers();
277       }
278       finally
279       {
280          // Reset classloader
281
SecurityActions.setContextClassLoader(oldCl);
282       }
283    }
284
285    protected void stopService() throws Exception JavaDoc
286    {
287       // Associate thread with classloader
288
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
289       SecurityActions.setContextClassLoader(getClassLoader());
290
291       try
292       {
293          // Call default stop
294
super.stopService();
295
296          // Stop container invoker
297
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext();)
298          {
299             String JavaDoc invokerBinding = (String JavaDoc) it.next();
300             EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
301             ci.stop();
302          }
303
304          // Stop the instance pool
305
instancePool.stop();
306
307          // Stop all interceptors in the chain
308
Interceptor in = interceptor;
309          while (in != null)
310          {
311             in.stop();
312             in = in.getNext();
313          }
314       }
315       finally
316       {
317          // Reset classloader
318
SecurityActions.setContextClassLoader(oldCl);
319       }
320    }
321
322    protected void destroyService() throws Exception JavaDoc
323    {
324       // Associate thread with classloader
325
ClassLoader JavaDoc oldCl = SecurityActions.getContextClassLoader();
326       SecurityActions.setContextClassLoader(getClassLoader());
327
328       try
329       {
330          // Destroy container invoker
331
for (Iterator JavaDoc it = proxyFactories.keySet().iterator(); it.hasNext();)
332          {
333             String JavaDoc invokerBinding = (String JavaDoc) it.next();
334             EJBProxyFactory ci = (EJBProxyFactory) proxyFactories.get(invokerBinding);
335             ci.destroy();
336             ci.setContainer(null);
337             try
338             {
339                ObjectName JavaDoc containerName = super.getJmxName();
340                Hashtable JavaDoc props = containerName.getKeyPropertyList();
341                props.put("plugin", "invoker");
342                props.put("binding", invokerBinding);
343                ObjectName JavaDoc invokerName = new ObjectName JavaDoc(containerName.getDomain(), props);
344                server.unregisterMBean(invokerName);
345             }
346             catch(Throwable JavaDoc ignore)
347             {
348             }
349          }
350
351          // Destroy the pool
352
instancePool.destroy();
353          instancePool.setContainer(null);
354          try
355          {
356             ObjectName JavaDoc containerName = super.getJmxName();
357             Hashtable JavaDoc props = containerName.getKeyPropertyList();
358             props.put("plugin", "pool");
359             ObjectName JavaDoc poolName = new ObjectName JavaDoc(containerName.getDomain(), props);
360             server.unregisterMBean(poolName);
361          }
362          catch(Throwable JavaDoc ignore)
363          {
364          }
365
366          // Destroy all the interceptors in the chain
367
Interceptor in = interceptor;
368          while (in != null)
369          {
370             in.destroy();
371             in.setContainer(null);
372             in = in.getNext();
373          }
374
375          // Call default destroy
376
super.destroyService();
377       }
378       finally
379       {
380          // Reset classloader
381
SecurityActions.setContextClassLoader(oldCl);
382       }
383    }
384
385    /**
386     * @throws Error Not valid for MDB
387     */

388    public Object JavaDoc internalInvokeHome(Invocation mi)
389          throws Exception JavaDoc
390    {
391       throw new Error JavaDoc("invokeHome not valid for MessageDriven beans");
392    }
393
394    /**
395     * This method does invocation interpositioning of tx and security,
396     * retrieves the instance from an object table, and invokes the method
397     * on the particular instance
398     */

399    public Object JavaDoc internalInvoke(Invocation mi) throws Exception JavaDoc
400    {
401       // Invoke through interceptors
402
return getInterceptor().invoke(mi);
403    }
404
405
406    // EJBHome implementation ----------------------------------------
407

408    public EJBObject JavaDoc createHome()
409          throws java.rmi.RemoteException JavaDoc, CreateException JavaDoc
410    {
411       throw new Error JavaDoc("createHome not valid for MessageDriven beans");
412    }
413
414
415    public void removeHome(Handle JavaDoc handle)
416          throws java.rmi.RemoteException JavaDoc, RemoveException JavaDoc
417    {
418       throw new Error JavaDoc("removeHome not valid for MessageDriven beans");
419       // TODO
420
}
421
422    public void removeHome(Object JavaDoc primaryKey)
423          throws java.rmi.RemoteException JavaDoc, RemoveException JavaDoc
424    {
425       throw new Error JavaDoc("removeHome not valid for MessageDriven beans");
426       // TODO
427
}
428
429    public EJBMetaData JavaDoc getEJBMetaDataHome()
430          throws java.rmi.RemoteException JavaDoc
431    {
432       // TODO
433
//return null;
434
throw new Error JavaDoc("getEJBMetaDataHome not valid for MessageDriven beans");
435    }
436
437    public HomeHandle JavaDoc getHomeHandleHome()
438          throws java.rmi.RemoteException JavaDoc
439    {
440       // TODO
441
//return null;
442
throw new Error JavaDoc("getHomeHandleHome not valid for MessageDriven beans");
443    }
444
445    Interceptor createContainerInterceptor()
446    {
447       return new ContainerInterceptor();
448    }
449
450    /**
451     * This is the last step before invocation - all interceptors are done
452     */

453    class ContainerInterceptor
454          extends AbstractContainerInterceptor
455    {
456       /**
457        * @throws Error Not valid for MDB
458        */

459       public Object JavaDoc invokeHome(Invocation mi) throws Exception JavaDoc
460       {
461          throw new Error JavaDoc("invokeHome not valid for MessageDriven beans");
462       }
463
464       /**
465        * FIXME Design problem, who will do the acknowledging for
466        * beans with bean managed transaction?? Probably best done in the
467        * listener "proxys"
468        */

469       public Object JavaDoc invoke(Invocation mi)
470             throws Exception JavaDoc
471       {
472          EnterpriseContext ctx = (EnterpriseContext) mi.getEnterpriseContext();
473
474          // wire the transaction on the context,
475
// this is how the instance remember the tx
476
if (ctx.getTransaction() == null)
477          {
478             ctx.setTransaction(mi.getTransaction());
479          }
480
481          // Get method and instance to invoke upon
482
Method JavaDoc m = (Method JavaDoc) beanMapping.get(mi.getMethod());
483          if( m == null )
484          {
485             // This is a configuration error that should have been caught earlier
486
String JavaDoc msg = MessageDrivenContainer.this.getBeanMetaData().getEjbName()
487                + " Invalid invocation, check your deployment packaging, interfaces, method=" + mi.getMethod();
488             throw new EJBException JavaDoc(msg);
489          }
490
491          // we have a method that needs to be done by a bean instance
492
try
493          {
494             messageCount++;
495             return mi.performCall(ctx.getInstance(), m, mi.getArguments());
496          }
497          catch (Exception JavaDoc e)
498          {
499             rethrow(e);
500          }
501
502          // We will never get this far, but the compiler does not know that
503
throw new org.jboss.util.UnreachableStatementException();
504       }
505    }
506 }
507
Popular Tags