KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > JMdbEndpointFactory


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JMdbEndpointFactory.java,v 1.19 2005/04/22 11:15:07 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container;
27
28 import java.lang.reflect.Method JavaDoc;
29 import java.lang.reflect.Proxy JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.ListIterator JavaDoc;
34
35 import javax.ejb.EJBException JavaDoc;
36 import javax.ejb.MessageDrivenBean JavaDoc;
37 import javax.ejb.MessageDrivenContext JavaDoc;
38 import javax.ejb.Timer JavaDoc;
39 import javax.ejb.TimerService JavaDoc;
40 import javax.naming.Context JavaDoc;
41 import javax.resource.spi.ActivationSpec JavaDoc;
42 import javax.resource.spi.UnavailableException JavaDoc;
43 import javax.resource.spi.endpoint.MessageEndpoint JavaDoc;
44 import javax.resource.spi.endpoint.MessageEndpointFactory JavaDoc;
45 import javax.transaction.SystemException JavaDoc;
46 import javax.transaction.xa.XAResource JavaDoc;
47
48 import org.objectweb.jonas_ejb.deployment.api.MessageDrivenDesc;
49 import org.objectweb.jonas_ejb.deployment.api.MethodDesc;
50 import org.objectweb.jonas_ejb.deployment.api.ActivationConfigPropertyDesc;
51
52 import org.objectweb.jonas.resource.Rar;
53 import org.objectweb.jotm.Current;
54
55 import org.objectweb.util.monolog.api.BasicLevel;
56
57 /**
58  * This class is a factory for a Message Driven Bean Endpoints There is one such
59  * class per MDB class. Contains all information related to the bean
60  * @author Eric Hardesty
61  */

62 public class JMdbEndpointFactory extends JFactory implements MessageEndpointFactory JavaDoc {
63
64     /**
65      * pool of JMessageEndpoint objects
66      */

67     private List JavaDoc endpool = new ArrayList JavaDoc();
68
69     /**
70      * count of the instances
71      */

72     protected int instanceCount = 0;
73
74     /**
75      * minimum pool size
76      */

77     protected int minPoolSize = 0;
78
79     /**
80      * maximum number of instances in the cache
81      */

82     protected int maxCacheSize = 0;
83
84     /**
85      * ActivationSpec associated with this factory
86      */

87     private ActivationSpec JavaDoc as = null;
88
89     /**
90      * Message listener type
91      */

92     private String JavaDoc msglistenType = null;
93
94     /**
95      * Associated RAR object
96      */

97     private Rar rar = null;
98
99     /**
100      * activated indicator
101      */

102     private boolean activated = false;
103
104     /**
105      * JMessageEndpointIntf class string
106      */

107     private static String JavaDoc JMESSAGEENDPOINT_CLASS = "org.objectweb.jonas_ejb.container.JMessageEndpointIntf";
108
109     /**
110      * MessageEndpoint class string
111      */

112     private static String JavaDoc MESSAGEENDPOINT_CLASS = "javax.resource.spi.endpoint.MessageEndpoint";
113
114     /**
115      * MessageDrivenContext class string
116      */

117     private static String JavaDoc MESSAGEDRIVENCONTEXT_CLASS = "javax.ejb.MessageDrivenContext";
118
119     /**
120      * Constructor
121      * @param dd Message Driven Descriptor
122      * @param cont Container where this bean is defined
123      * @param as ActivationSpec to link the Container to
124      */

125     public JMdbEndpointFactory(MessageDrivenDesc dd, JContainer cont, ActivationSpec JavaDoc as) {
126         super(dd, cont);
127         String JavaDoc dest = dd.getDestinationJndiName();
128         // Set the AS properties and validate the required config properties
129
List JavaDoc acpl = null;
130         if (dd.getMdActivationConfigDesc() != null) {
131             acpl = dd.getMdActivationConfigDesc().getActivationConfigPropertyList();
132         }
133         List JavaDoc jAcpl = null;
134         if (dd.getJonasMdActivationConfigDesc() != null) {
135             jAcpl = dd.getJonasMdActivationConfigDesc().getActivationConfigPropertyList();
136         }
137         mdbEFInit(dd, dest, acpl, jAcpl, as);
138     }
139
140     /**
141      * Constructor
142      * @param dd Message Driven Descriptor
143      * @param destination String of desired destination
144      * @param cont Container where this bean is defined
145      * @param as ActivationSpec to link the Container to
146      */

147     public JMdbEndpointFactory(MessageDrivenDesc dd, String JavaDoc destination, JContainer cont,
148                                ActivationSpec JavaDoc as) {
149         super(dd, cont);
150
151         // Build Activation spec linked list from variables
152

153         List JavaDoc jAcpl = new LinkedList JavaDoc();
154         List JavaDoc acpl = null;
155         if (dd.getMdActivationConfigDesc() != null) {
156             acpl = dd.getMdActivationConfigDesc().getActivationConfigPropertyList();
157         }
158         buildACL(dd, jAcpl);
159
160         mdbEFInit(dd, destination, acpl, jAcpl, as);
161     }
162
163     /**
164      * Create the ActivationConfigProperty List
165      * @param dd MessageDrivenDesc
166      * @param jacl List to update
167      */

168     private void buildACL(MessageDrivenDesc dd, List JavaDoc jacl) {
169
170         String JavaDoc [] aclNames = {"destination", "destinationType", "messageSelector",
171                               "acknowledgeMode", "subscriptionDurability" };
172
173         ActivationConfigPropertyDesc acp = null;
174
175         acp = new ActivationConfigPropertyDesc();
176         acp.setActivationConfigPropertyName("destination");
177         acp.setActivationConfigPropertyValue(dd.getDestinationJndiName());
178         jacl.add(acp);
179
180         acp = new ActivationConfigPropertyDesc();
181         acp.setActivationConfigPropertyName("destinationType");
182         if (dd.isTopicDestination()) {
183             acp.setActivationConfigPropertyValue("javax.jms.Topic");
184         } else {
185             acp.setActivationConfigPropertyValue("javax.jms.Queue");
186         }
187         jacl.add(acp);
188
189         acp = new ActivationConfigPropertyDesc();
190         acp.setActivationConfigPropertyName("messageSelector");
191         acp.setActivationConfigPropertyValue(dd.getSelector());
192         jacl.add(acp);
193
194         acp = new ActivationConfigPropertyDesc();
195         acp.setActivationConfigPropertyName("acknowledgeMode");
196         if (dd.getAcknowledgeMode() == MessageDrivenDesc.AUTO_ACKNOWLEDGE) {
197             acp.setActivationConfigPropertyValue("Auto-acknowledge");
198         } else {
199             acp.setActivationConfigPropertyValue("Dups-ok-acknowledge");
200         }
201         jacl.add(acp);
202
203         acp = new ActivationConfigPropertyDesc();
204         acp.setActivationConfigPropertyName("subscriptionDurability");
205         if (dd.getSubscriptionDurability() == MessageDrivenDesc.SUBS_DURABLE) {
206             acp.setActivationConfigPropertyValue("Durable");
207         } else {
208             acp.setActivationConfigPropertyValue("NonDurable");
209         }
210         jacl.add(acp);
211
212         if (dd.getSubscriptionDurability() == MessageDrivenDesc.SUBS_DURABLE) {
213             acp = new ActivationConfigPropertyDesc();
214             acp.setActivationConfigPropertyName("subscriptionName");
215             acp.setActivationConfigPropertyValue(dd.getEjbName());
216             jacl.add(acp);
217         }
218
219         // Check existing list to determine if additional items are configured, then pass them along also
220
List JavaDoc acpl = null;
221         if (dd.getJonasMdActivationConfigDesc() != null) {
222             acpl = dd.getJonasMdActivationConfigDesc().getActivationConfigPropertyList();
223
224             String JavaDoc acpName = null;
225             boolean found = false;
226             for (int i = 0; i < acpl.size(); i++) {
227                 acp = (ActivationConfigPropertyDesc) acpl.get(i);
228                 acpName = acp.getActivationConfigPropertyName();
229                 found = false;
230                 for (int j = 0; j < aclNames.length; j++) {
231                     if (acpName.equals(aclNames[j])) {
232                         found = true;
233                         break;
234                     }
235                 }
236                 if (!found) {
237                     jacl.add(acp);
238                 }
239             }
240
241         }
242     }
243
244     /**
245      * Init this endpointfactory
246      * @param dd Message Driven Descriptor
247      * @param dest String destination desired
248      * @param acpl List of activation properites
249      * @param jAcpl List of JOnAS activation properites
250      * @param aSpec ActivationSpec to link the Container to
251      */

252     private void mdbEFInit(MessageDrivenDesc dd, String JavaDoc dest, List JavaDoc acpl,
253                            List JavaDoc jAcpl, ActivationSpec JavaDoc aSpec) {
254
255         String JavaDoc methName = "mdbEFInit: ";
256         String JavaDoc ejbName = dd.getEjbName();
257
258         // Check if tx managed by the bean or the container
259
txbeanmanaged = dd.isBeanManagedTransaction();
260
261         // Set ActivationSpec
262
as = aSpec;
263
264         minPoolSize = dd.getPoolMin();
265         maxCacheSize = dd.getCacheMax();
266         if (TraceEjb.isDebugJms()) {
267             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "maxCacheSize = " + maxCacheSize + " minPoolSize = " + minPoolSize);
268         }
269
270         // Get the associated Resource Adapter and messagelistenerType
271
rar = Rar.getRar(dest);
272         if (rar == null) {
273             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot retrieve associated Resource Adapter ");
274             throw new EJBException JavaDoc("cannot retrieve associated Resource Adapter ");
275         }
276         msglistenType = rar.getInterface(dest);
277
278         try {
279             rar.configureAS(as, acpl, jAcpl, dest, ejbName);
280         } catch (Exception JavaDoc ex) {
281             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot configure activationspec " + ex);
282             ex.printStackTrace();
283             throw new EJBException JavaDoc("cannot configure activationspec ", ex);
284         }
285
286         // pre-allocate a set of Endpoints
287
synchronized (endpool) {
288             for (int i = 0; i < minPoolSize; i++) {
289                 JMessageEndpoint ep = null;
290                 try {
291                     ep = createNewInstance();
292                     endpool.add(ep);
293                 } catch (Exception JavaDoc e) {
294                     TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot init pool of instances ");
295                     throw new EJBException JavaDoc("cannot init pool of instances ", e);
296                 }
297             }
298         }
299         if (minPoolSize != 0) {
300             TraceEjb.mdb.log(BasicLevel.INFO, methName + "pre-allocate a set of " + minPoolSize
301                                  + " message driven bean instances");
302         }
303
304         // Call to register an XAResource with JOTM
305
try {
306             ActivationSpec JavaDoc [] asArray = new ActivationSpec JavaDoc[1];
307             asArray[0] = as;
308             XAResource JavaDoc [] xar = rar.getResourceAdapter().getXAResources(asArray);
309             if (xar != null && xar.length > 0) {
310                 ((Current) tm).getTransactionRecovery().
311                            registerResourceManager(ejbName+msglistenType,
312                                                    xar[0], "", null);
313             }
314         } catch (Exception JavaDoc ex) {
315             TraceEjb.mdb.log(BasicLevel.ERROR, ex.getMessage(), ex);
316         }
317
318         activated = true;
319         // EndpointActivation
320
try {
321             rar.getResourceAdapter().endpointActivation(this, as);
322         } catch (Exception JavaDoc ex) {
323             activated = false;
324             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot activate endpoint ", ex);
325             throw new EJBException JavaDoc("cannot activate endpoint ", ex);
326         }
327     }
328
329     // ---------------------------------------------------------------
330
// Specific BeanFactory implementation
331
// ---------------------------------------------------------------
332

333     /**
334      * Init pool of instances
335      */

336     public void initInstancePool() {
337     }
338
339     /**
340      * @return the size of the EndpointPool
341      */

342     public int getPoolSize() {
343         return endpool.size();
344     }
345
346     /**
347      * stop this EJB. call deactivate on the Endpoint Stop the threads and
348      * remove the beans
349      */

350     public void stop() {
351         String JavaDoc methName = "stop: ";
352         if (TraceEjb.isDebugJms()) {
353             TraceEjb.mdb.log(BasicLevel.DEBUG, methName);
354         }
355         try {
356             // Deactivate the endpoint
357
rar.getResourceAdapter().endpointDeactivation(this, as);
358             // Loop thru the endpool and release them
359
synchronized (endpool) {
360                 if (TraceEjb.isDebugJms()) {
361                     TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "stopping " + this);
362                 }
363                 JMessageEndpoint ep = null;
364                 while (endpool.size() > 0) {
365                     ep = (JMessageEndpoint) endpool.remove(0);
366                     instanceCount--;
367                     try {
368                         ep.mdb.ejbRemove();
369                     } catch (Exception JavaDoc e) {
370                         TraceEjb.mdb.log(BasicLevel.ERROR, methName + "Cannot remove mdb: "
371                                + ep.mdb, e);
372                     }
373                 }
374             }
375         } catch (Exception JavaDoc e) {
376             TraceEjb.mdb.log(BasicLevel.WARN, methName + "Cannot deactivate the endpoint", e);
377         }
378     }
379
380     /**
381      * synchronize bean instances if needed
382      */

383     public void sync() {
384     }
385
386     /**
387      * @return the home if exist
388      */

389     public JHome getHome() {
390         return null;
391     }
392
393     /**
394      * @return the local home if exist
395      */

396     public JLocalHome getLocalHome() {
397         return null;
398     }
399
400     // ---------------------------------------------------------------
401
// MessageEndpointFactory implementation
402
// ---------------------------------------------------------------
403

404     /**
405      * Create the message endpoint
406      *
407      * @param xaResource XAResource object to attach
408      * @return MessageEndpoint to deliver messages to
409      * @throws UnavailableException exception to throw
410      */

411     public MessageEndpoint JavaDoc createEndpoint(XAResource JavaDoc xaResource) throws UnavailableException JavaDoc {
412         String JavaDoc methName = "createEndpoint: ";
413         if (TraceEjb.isDebugJms()) {
414             TraceEjb.mdb.log(BasicLevel.DEBUG, methName);
415         }
416
417         if (!activated) {
418             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "mdb is not usuable either initial deployment or undeployment ");
419             throw new UnavailableException JavaDoc("mdb is not usuable either initial deployment or undeployment ");
420         }
421
422         JMessageEndpoint ep = null;
423         try {
424             ep = getNewInstance(xaResource);
425         } catch (Exception JavaDoc ex) {
426             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot create an endpoint ");
427             throw new UnavailableException JavaDoc("cannot create an endpoint ", ex);
428         }
429         return ep.mep;
430     }
431
432     /**
433      * Determine if the method is transacted
434      *
435      * @param method Method to check
436      * @return boolean whether the specified method is transacted
437      * @throws NoSuchMethodException exception to throw
438      */

439     public boolean isDeliveryTransacted(Method JavaDoc method) throws NoSuchMethodException JavaDoc {
440         int txAttribute = 0;
441         try {
442             txAttribute = dd.getMethodDesc(method).getTxAttribute();
443         } catch (Exception JavaDoc ex) {
444             TraceEjb.mdb.log(BasicLevel.ERROR, "isDeliveryTransacted: No such method exists. " + method.getName(), ex);
445             throw new NoSuchMethodException JavaDoc("No such method exists. " + method.getName());
446         }
447         return txAttribute == MethodDesc.TX_REQUIRED ? true : false;
448     }
449
450     // ---------------------------------------------------------------
451
// Other methods
452
// ---------------------------------------------------------------
453

454     /**
455      * Return an MessageEndpoint from the pool. If pool is empty, creates a new
456      * one.
457      * @return an MessageEndpoint from the pool.
458      * @exception Exception - if an application server fails to return an
459      * MessageEndpoint out of its pool.
460      */

461     public JMessageEndpoint getMessageEndpoint() throws Exception JavaDoc {
462         if (TraceEjb.isDebugJms()) {
463             TraceEjb.mdb.log(BasicLevel.DEBUG, "getMessageEndpoint: ");
464         }
465
466         return getNewInstance(null);
467     }
468
469     /**
470      * put the JMessageEndpoint back to the pool
471      * @param ep the MessageEndpoint
472      */

473     public void releaseEndpoint(JMessageEndpoint ep) {
474         String JavaDoc methName = "releaseEndpoint: ";
475         if (TraceEjb.isDebugJms()) {
476             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + ep);
477         }
478
479         ep.setReleasedState(true);
480         synchronized (endpool) {
481             endpool.add(ep);
482             if (TraceEjb.isDebugJms()) {
483                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "notifyAll " );
484             }
485             endpool.notifyAll();
486         }
487         if (TraceEjb.isDebugJms()) {
488             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "nb instances " + getCacheSize());
489             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "nb free cached instances " + getPoolSize());
490         }
491
492     }
493
494     // ---------------------------------------------------------------
495
// other public methods
496
// ---------------------------------------------------------------
497

498     /**
499      * Obtains the TimerService associated for this Bean
500      * @return a JTimerService instance.
501      */

502     public TimerService JavaDoc getTimerService() {
503         if (myTimerService == null) {
504             // TODO : Check that instance implements TimedObject ?
505
myTimerService = new JTimerService(this);
506         }
507         return myTimerService;
508     }
509
510     /**
511      * @return min pool size for Jmx
512      */

513     public int getMinPoolSize() {
514         return minPoolSize;
515     }
516
517     /**
518      * @return max cache size for Jmx
519      */

520     public int getMaxCacheSize() {
521         return maxCacheSize;
522     }
523
524     /**
525      * @return current cache size ( = nb of instance created) for Jmx
526      */

527     public int getCacheSize() {
528         return instanceCount;
529     }
530
531     /**
532      * @return the Transaction Attribute
533      */

534     public int getTransactionAttribute() {
535         return ((MessageDrivenDesc) dd).getTxAttribute();
536     }
537
538     /**
539      * For Message Driven Beans, only 2 cases are possible:
540      * TX_REQUIRED or TX_NOT_SUPPORTED
541      * @param rctx The Request Context
542      */

543     public void checkTransaction(RequestCtx rctx) {
544         String JavaDoc methName = "checkTransaction: ";
545         if (rctx.txAttr == MethodDesc.TX_REQUIRED) {
546             try {
547                 if (txbeanmanaged) {
548                     if (tm.getTransaction() == null) {
549                         TraceEjb.mdb.log(BasicLevel.ERROR, methName + "No transaction and need one");
550                         return;
551                     }
552                 } else {
553                     if (tm.getTransaction() == null) {
554                         tm.begin();
555                     }
556                 }
557                 rctx.mustCommit = true;
558                 rctx.currTx = tm.getTransaction();
559             } catch (Exception JavaDoc e) {
560                 // No exception raised in case of MDB
561
TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot start tx:", e);
562                 return;
563             }
564         } else {
565             if (rctx.txAttr != MethodDesc.TX_NOT_SUPPORTED) {
566                 TraceEjb.mdb.log(BasicLevel.ERROR, methName + "Bad transaction attribute: " + rctx.txAttr);
567             }
568             try {
569                 rctx.currTx = tm.getTransaction();
570                 if (rctx.currTx != null) {
571                     if (TraceEjb.isDebugJms()) {
572                         TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "Suspending client tx");
573                     }
574                     rctx.clientTx = tm.suspend();
575                     rctx.currTx = null;
576                 }
577             } catch (SystemException JavaDoc e) {
578                 TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot suspend transaction", e);
579                 return;
580             }
581         }
582     }
583
584     /**
585      * Reduce number of instances in memory in the free list we reduce to the
586      * minPoolSize
587      */

588     public void reduceCache() {
589         String JavaDoc methName = "reduceCache: ";
590         if (TraceEjb.isDebugJms()) {
591             TraceEjb.mdb.log(BasicLevel.DEBUG, methName);
592         }
593         // reduce the pool to the minPoolSize
594
int poolsz = minPoolSize;
595         synchronized (endpool) {
596             if (TraceEjb.isDebugJms()) {
597                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "try to reduce " + endpool.size() + " to " + poolsz);
598             }
599             while (endpool.size() > poolsz) {
600                 ListIterator JavaDoc i = endpool.listIterator();
601                 if (i.hasNext()) {
602                     i.next();
603                     i.remove();
604                     instanceCount--;
605                 }
606             }
607         }
608         if (TraceEjb.isDebugJms()) {
609             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "cacheSize= " + getCacheSize());
610         }
611
612     }
613
614     /**
615      * Notify a timeout for this bean
616      * @param timer timer whose expiration caused this notification.
617      */

618     public void notifyTimeout(Timer JavaDoc timer) {
619         String JavaDoc methName = "notifyTimeout: ";
620         if (TraceEjb.isDebugJms()) {
621             TraceEjb.mdb.log(BasicLevel.DEBUG, methName);
622         }
623
624         // We need an instance from the pool to process the timeout.
625
JMessageEndpoint ep = null;
626         try {
627             ep = getNewInstance(null);
628         } catch (Exception JavaDoc e) {
629             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "exception:" + e);
630             throw new EJBException JavaDoc("Cannot deliver the timeout", e);
631         }
632
633         // deliver the timeout to the bean
634
ep.deliverTimeout(timer);
635
636         // release the instance
637
releaseEndpoint(ep);
638     }
639
640     // ---------------------------------------------------------------
641
// private methods
642
// ---------------------------------------------------------------
643

644     /**
645      * return a new instance of the bean. Try to get one from the pool, and
646      * create a new one if the pool is empty.
647      *
648      * @param xaResource XAResource to use
649      * @return JMessageEndpoint to return
650      * @throws Exception to throw
651      */

652     private JMessageEndpoint getNewInstance(XAResource JavaDoc xaResource) throws Exception JavaDoc {
653         String JavaDoc methName = "getNewInstance: ";
654         if (TraceEjb.isDebugJms()) {
655             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "Factory: " + this + " XAResource: " + xaResource);
656         }
657
658         // try to get one from the Pool
659
JMessageEndpoint ep = null;
660
661         // try to find a free entry in the pool
662
synchronized (endpool) {
663             if (!endpool.isEmpty()) {
664                 try {
665                     ep = (JMessageEndpoint) endpool.remove(0);
666                 } catch (Exception JavaDoc ex) {
667                     // This should never happen
668
TraceEjb.mdb.log(BasicLevel.ERROR, methName + "Exception:" + ex);
669                     throw new EJBException JavaDoc("Cannot get an instance from the pool", ex);
670                 }
671             } else {
672                 if (TraceEjb.isDebugJms()) {
673                     TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "pool is empty");
674                 }
675                 if (maxCacheSize == 0 || instanceCount < maxCacheSize) {
676                     // Pool has free slots, create a new MessageEndpoint object
677
try {
678                         ep = createNewInstance();
679                     } catch (Exception JavaDoc e) {
680                         TraceEjb.mdb.log(BasicLevel.ERROR, methName + "exception:" + e);
681                         throw new EJBException JavaDoc("Cannot create a new instance", e);
682                     }
683                 } else {
684                     while (endpool.isEmpty()) {
685                         if (TraceEjb.isDebugJms()) {
686                             TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "endpool.isEmpty() = true --> wait()");
687                         }
688                         try {
689                             endpool.wait();
690                             if (TraceEjb.isDebugJms()) {
691                                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "endpool notified");
692                             }
693                         } catch (InterruptedException JavaDoc e) {
694                             if (TraceEjb.isDebugJms()) {
695                                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "endpool waiting interrupted", e);
696                             }
697                         } catch (Exception JavaDoc e) {
698                             throw new EJBException JavaDoc("synchronization pb", e);
699                         }
700                     }
701                     try {
702                         ep = (JMessageEndpoint) endpool.remove(0);
703                     } catch (Exception JavaDoc ex) {
704                         // This should never happen
705
TraceEjb.mdb.log(BasicLevel.ERROR, methName + "Exception:" + ex);
706                         throw new EJBException JavaDoc("Cannot get an instance from the pool", ex);
707                     }
708                 }
709
710             }
711             if (TraceEjb.isDebugJms()) {
712                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "nb instances " + getCacheSize());
713             }
714             ep.setXAResource(xaResource);
715             ep.setReleasedState(false);
716             if (TraceEjb.isDebugJms()) {
717                 TraceEjb.mdb.log(BasicLevel.DEBUG, methName + "Returning " + ep);
718             }
719             return ep;
720         }
721     }
722
723     /**
724      * Create a new instance of the bean
725      *
726      * @return JMessageEndpoint to return
727      * @throws Exception to throw
728      */

729     private JMessageEndpoint createNewInstance() throws Exception JavaDoc {
730         String JavaDoc methName = "createNewInstance: ";
731         if (TraceEjb.isDebugJms()) {
732             TraceEjb.mdb.log(BasicLevel.DEBUG, methName);
733         }
734         JMessageEndpointProxy epProxy = null;
735         MessageEndpoint JavaDoc ep = null;
736         JMessageEndpoint jep = null;
737         MessageDrivenDesc mdd = (MessageDrivenDesc) dd;
738         ClassLoader JavaDoc cls = myClassLoader();
739
740         // Set ContextClassLoader with the ejbclassloader.
741
// This is necessary in case ejbCreate calls another bean in the same
742
// jar.
743
Thread.currentThread().setContextClassLoader(cls);
744
745         // Creates the new instance
746
MessageDrivenBean JavaDoc mdb = null;
747         try {
748             mdb = (MessageDrivenBean JavaDoc) beanclass.newInstance();
749         } catch (Exception JavaDoc e) {
750             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "failed to create instance:", e);
751             throw new EJBException JavaDoc("Container failed to create instance of Message Driven Bean", e);
752         }
753
754         // Instanciates a new JMessageEndpoint object
755
jep = new JMessageEndpoint(this, mdb);
756         epProxy = new JMessageEndpointProxy(this, mdb, jep);
757         Class JavaDoc endpointClass = cls.loadClass(MESSAGEENDPOINT_CLASS);
758         Class JavaDoc msgListenerClass = cls.loadClass(msglistenType);
759         ep = (MessageEndpoint JavaDoc) Proxy.newProxyInstance(cls, new Class JavaDoc[] {endpointClass, msgListenerClass}, epProxy);
760
761         jep.setProxy(ep);
762         // starts the bean instance: setMessageDrivenContext() + ejbCreate()
763
// see EJB spec. 2.0 page 322.
764
// Both operations must be called with the correct ComponentContext
765
Context JavaDoc ctxsave = setComponentContext();
766         mdb.setMessageDrivenContext((MessageDrivenContext JavaDoc) jep);
767         try {
768             beanclass.getMethod("ejbCreate", (Class JavaDoc[]) null).invoke(mdb, (Object JavaDoc[]) null);
769         } catch (Exception JavaDoc e) {
770             TraceEjb.mdb.log(BasicLevel.ERROR, methName + "cannot call ejbCreate on message driven bean instance ", e);
771             throw new EJBException JavaDoc(" Container fails to call ejbCreate on message driven bean instance", e);
772         } finally {
773             resetComponentContext(ctxsave);
774         }
775
776         synchronized (endpool) {
777             instanceCount++;
778         }
779         return jep;
780     }
781
782 }
783
Popular Tags