1 22 package org.jboss.ejb3.mdb; 23 24 import org.jboss.annotation.ejb.ResourceAdapter; 25 import org.jboss.aop.AspectManager; 26 import org.jboss.aop.MethodInfo; 27 import org.jboss.aop.advice.Interceptor; 28 import org.jboss.deployment.DeploymentException; 29 import org.jboss.ejb3.*; 30 import org.jboss.ejb3.mdb.inflow.JBossMessageEndpointFactory; 31 import org.jboss.ejb3.interceptor.InterceptorInfoRepository; 32 import org.jboss.ejb3.jms.JMSDestinationFactory; 33 import org.jboss.ejb3.timerservice.TimedObjectInvoker; 34 import org.jboss.ejb3.timerservice.TimerServiceFactory; 35 import org.jboss.jms.jndi.JMSProviderAdapter; 36 import org.jboss.logging.Logger; 37 import org.jboss.metadata.ActivationConfigPropertyMetaData; 38 39 import javax.ejb.*; 40 import javax.ejb.Timer ; 41 import javax.jms.*; 42 import javax.jms.Queue ; 43 import javax.management.MalformedObjectNameException ; 44 import javax.management.ObjectName ; 45 import javax.naming.Context ; 46 import javax.naming.InitialContext ; 47 import javax.naming.NamingException ; 48 import java.lang.reflect.Field ; 49 import java.lang.reflect.Method ; 50 import java.util.*; 51 52 56 public abstract class MessagingContainer extends EJBContainer implements TimedObjectInvoker 57 { 58 private static final Logger log = Logger.getLogger(MessagingContainer.class); 59 60 protected TimerService timerService; 61 protected ActivationSpec activationSpec = new ActivationSpec(); 62 protected JBossMessageEndpointFactory messageEndpointFactory; 63 64 69 protected final static String DEFAULT_DESTINATION_TYPE = "javax.jms.Topic"; 70 71 public MessagingContainer(String ejbName, AspectManager manager, ClassLoader cl, String beanClassName, Hashtable ctxProperties, 72 InterceptorInfoRepository interceptorRepository, Ejb3Deployment deployment) 73 { 74 super(Ejb3Module.BASE_EJB3_JMX_NAME + ",name=" + ejbName, manager, cl, beanClassName, ejbName, ctxProperties, interceptorRepository, deployment); 75 76 beanContextClass = MDBContext.class; 77 78 messageEndpointFactory = new JBossMessageEndpointFactory(); 79 messageEndpointFactory.setContainer(this); 80 } 81 82 public abstract Class getMessagingType(); 83 84 public abstract Map getActivationConfigProperties(); 85 86 protected abstract void populateActivationSpec(); 87 88 public abstract MethodInfo getMethodInfo(Method method); 89 90 public void setMessageEndpointFactory(JBossMessageEndpointFactory messageEndpointFactory) 91 { 92 this.messageEndpointFactory = messageEndpointFactory; 93 } 94 95 public String getResourceAdaptorName() 96 { 97 ResourceAdapter annotation = (ResourceAdapter) resolveAnnotation(ResourceAdapter.class); 98 if (annotation == null) 99 return JMS_ADAPTOR; 100 101 return annotation.value(); 102 } 103 104 protected void addActivationSpecProperty(Map result, ActivationConfigProperty property) 105 { 106 if (!property.propertyName().equals("messagingType")) 107 { 108 ActivationConfigPropertyMetaData metaData = new ActivationConfigPropertyMetaData(); 109 try 110 { 111 Field nameField = ActivationConfigPropertyMetaData.class.getDeclaredField("name"); 112 nameField.setAccessible(true); 113 nameField.set(metaData, property.propertyName()); 114 Field valueField = ActivationConfigPropertyMetaData.class.getDeclaredField("value"); 115 valueField.setAccessible(true); 116 valueField.set(metaData, property.propertyValue()); 117 } 118 catch (Exception e) 119 { 120 throw new RuntimeException (e); 121 } 122 123 129 result.put(property.propertyName(), metaData); 130 } 131 } 132 133 142 public void start() throws Exception 143 { 144 super.start(); 145 146 populateActivationSpec(); 147 148 innerStart(); 149 150 timerService = TimerServiceFactory.getInstance().createTimerService(this.getObjectName(), this); 151 152 startProxies(); 153 154 TimerServiceFactory.getInstance().restoreTimerService(timerService); 155 } 156 157 protected void innerStart() throws Exception 158 { 159 log.debug("Initializing"); 160 161 if (getResourceAdaptorName().equals(JMS_ADAPTOR)) 162 jmsCreate(); 163 } 164 165 public ObjectName getJmxName() 166 { 167 ObjectName jmxName = null; 168 String jndiName = ProxyFactoryHelper.getLocalJndiName(this); 169 String name = org.jboss.ejb.Container.BASE_EJB_CONTAINER_NAME + ",jndiName=" + jndiName; 171 try 172 { 173 jmxName = org.jboss.mx.util.ObjectNameConverter.convert(name); 174 } 175 catch (MalformedObjectNameException e) 176 { 177 e.printStackTrace(); 178 throw new RuntimeException ("Failed to create ObjectName, msg=" + e.getMessage()); 179 } 180 181 return jmxName; 182 } 183 184 protected void startProxies() throws Exception 185 { 186 messageEndpointFactory.start(); 187 } 188 189 196 protected String parseJndiSuffix(final String jndiname, 197 final String defautSuffix) 198 { 199 String jndiSuffix = ""; 203 204 if (jndiname != null) 205 { 206 int indexOfSlash = jndiname.indexOf("/"); 207 if (indexOfSlash != -1) 208 { 209 jndiSuffix = jndiname.substring(indexOfSlash + 1); 210 } 211 else 212 { 213 jndiSuffix = jndiname; 214 } 215 } 216 else 217 { 218 jndiSuffix = defautSuffix; 220 } 221 222 return jndiSuffix; 223 } 224 225 public Object localInvoke(Method method, Object [] args) throws Throwable 226 { 227 MethodInfo info = getMethodInfo(method); 228 if (info == null) 229 { 230 throw new RuntimeException ("Could not resolve beanClass method from proxy call: " + method.toString()); 231 } 232 return localInvoke(info, args); 233 234 } 235 236 public Object localInvoke(MethodInfo info, Object [] args) throws Throwable 237 { 238 ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); 239 ThreadLocalENCFactory.push(enc); 240 try 241 { 242 Interceptor[] aspects = info.getInterceptors(); 243 EJBContainerInvocation nextInvocation = new EJBContainerInvocation(info, aspects); 244 nextInvocation.setAdvisor(this); 245 nextInvocation.setArguments(args); 246 return nextInvocation.invokeNext(); 247 } 248 finally 249 { 250 Thread.currentThread().setContextClassLoader(oldLoader); 251 ThreadLocalENCFactory.pop(); 252 } 253 } 254 255 public TimerService getTimerService() 256 { 257 return timerService; 258 } 259 260 public TimerService getTimerService(Object pKey) 261 { 262 assert timerService != null : "Timer Service not yet initialized"; 263 return timerService; 264 } 265 266 public void callTimeout(Timer timer) throws Exception 267 { 268 Method timeout = callbackHandler.getTimeoutCallback(); 269 if (timeout == null) throw new EJBException("No method has been annotated with @Timeout"); 270 Object [] args = {timer}; 271 try 272 { 273 localInvoke(timeout, args); 274 } 275 catch (Throwable throwable) 276 { 277 if (throwable instanceof Exception ) throw (Exception ) throwable; 278 throw new RuntimeException (throwable); 279 } 280 } 281 282 283 public void stop() throws Exception 284 { 285 if (timerService != null) 286 { 287 TimerServiceFactory.getInstance().removeTimerService(timerService); 288 } 289 290 stopProxies(); 291 } 292 293 protected void stopProxies() throws Exception 294 { 295 messageEndpointFactory.stop(); 296 } 297 298 public void destroy() throws Exception 299 { 300 } 301 302 protected static final String JMS_ADAPTOR = "jms-ra.rar"; 304 protected static final String DESTINATION = "destination"; 305 protected static final String DESTINATION_TYPE = "destinationType"; 306 protected static final String PROVIDER_ADAPTER_JNDI = "providerAdapterJNDI"; 307 protected static final String MAX_SESSION = "maxSession"; 308 309 public void initializePool() throws Exception 310 { 311 super.initializePool(); 312 313 String maxSession = getMaxSession(); 314 if (maxSession != null) 315 { 316 pool.setMaxSize(Integer.parseInt(maxSession)); 317 } 318 } 319 320 protected String getProviderAdapterJNDI() 321 { 322 ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(PROVIDER_ADAPTER_JNDI); 323 if (property != null) 324 return property.getValue(); 325 return "java:/DefaultJMSProvider"; 326 } 327 328 protected String getMaxSession() 329 { 330 ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(MAX_SESSION); 331 if (property != null) 332 return property.getValue(); 333 return null; 334 } 335 336 protected String getDestination() 337 { 338 ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(DESTINATION); 339 if (property != null) 340 return property.getValue(); 341 return null; 342 } 343 344 protected String getDestinationType() 345 { 346 ActivationConfigPropertyMetaData property = (ActivationConfigPropertyMetaData)getActivationConfigProperties().get(DESTINATION_TYPE); 347 if (property != null) 348 return property.getValue(); 349 return null; 350 } 351 352 protected void jmsCreate() throws Exception 353 { 354 JMSProviderAdapter adapter = getJMSProviderAdapter(); 357 log.debug("Provider adapter: " + adapter); 358 359 Context context = adapter.getInitialContext(); 361 log.debug("context: " + context); 362 363 if (context == null) 365 { 366 throw new RuntimeException ("Failed to get the root context"); 367 } 368 369 String destinationType = getDestinationType(); 373 if (destinationType == null) 374 { 375 log.warn("No message-driven-destination given; using; guessing type"); 376 destinationType = getDestinationType(context, getDestination()); 377 } 378 379 if ("javax.jms.Topic".equals(destinationType)) 380 { 381 innerCreateTopic(context); 382 383 } 384 else if ("javax.jms.Queue".equals(destinationType)) 385 { 386 innerCreateQueue(context); 387 388 } 389 else 390 throw new DeploymentException("Unknown destination-type " + destinationType); 391 392 log.debug("Initialized with config " + toString()); 393 394 context.close(); 395 } 396 397 protected void innerCreateQueue(Context context) 398 throws Exception 399 { 400 log.debug("Got destination type Queue for " + ejbName); 401 402 String jndiSuffix = parseJndiSuffix(getDestination(), ejbName); 404 log.debug("jndiSuffix: " + jndiSuffix); 405 406 Queue queue = null; 408 try 409 { 410 if (getDestination() != null) 412 queue = (Queue ) context.lookup(getDestination()); 413 } 414 catch (NamingException e) 415 { 416 log.warn("Could not find the queue destination-jndi-name=" + getDestination()); 417 } 418 catch (ClassCastException e) 419 { 420 throw new DeploymentException("Expected a Queue destination-jndi-name=" + getDestination()); 421 } 422 423 if (queue == null) 424 queue = (Queue ) createDestination(Queue .class, 425 context, 426 "queue/" + jndiSuffix, 427 jndiSuffix); 428 } 429 430 protected void innerCreateTopic(Context context) 431 throws Exception 432 { 433 log.debug("Got destination type Topic for " + ejbName); 434 435 String jndiSuffix = parseJndiSuffix(getDestination(), ejbName); 437 log.debug("jndiSuffix: " + jndiSuffix); 438 439 Topic topic = null; 441 try 442 { 443 if (getDestination() != null) 445 topic = (Topic) context.lookup(getDestination()); 446 } 447 catch (NamingException e) 448 { 449 log.warn("Could not find the topic destination-jndi-name=" + getDestination()); 450 } 451 catch (ClassCastException e) 452 { 453 throw new DeploymentException("Expected a Topic destination-jndi-name=" + getDestination()); 454 } 455 456 if (topic == null) 457 topic = (Topic) createDestination(Topic.class, 458 context, 459 "topic/" + jndiSuffix, 460 jndiSuffix); 461 } 462 463 474 private Destination createDestination(final Class <? extends Destination> type, 475 final Context ctx, 476 final String jndiName, 477 final String jndiSuffix) 478 throws Exception 479 { 480 try 481 { 482 return (Destination) ctx.lookup(jndiName); 484 } 485 catch (NamingException e) 486 { 487 if (getDestination() == null) 489 { 490 return null; 491 } 492 else 493 { 494 log.warn("destination not found: " + jndiName + " reason: " + e); 496 log.warn("creating a new temporary destination: " + jndiName); 497 498 createTemporaryDestination(type, jndiSuffix); 499 500 return (Destination) ctx.lookup(jndiName); 502 } 503 } 504 } 505 506 private void createTemporaryDestination(Class <? extends Destination> type, String jndiSuffix) throws Exception 507 { 508 515 517 536 557 558 JMSDestinationFactory.getInstance().createDestination(type, jndiSuffix); 560 } 561 562 567 protected JMSProviderAdapter getJMSProviderAdapter() 568 throws NamingException 569 { 570 Context context = getInitialContext(); 571 String providerAdapterJNDI = getProviderAdapterJNDI(); 573 try 574 { 575 log.debug("Looking up provider adapter: " + providerAdapterJNDI); 576 577 return (JMSProviderAdapter) context.lookup(providerAdapterJNDI); 578 } 579 finally 580 { 581 context.close(); 582 } 583 } 584 585 595 protected String getDestinationType(Context ctx, String destinationJNDI) 596 { 597 String destType = null; 598 599 if (destinationJNDI != null) 600 { 601 try 602 { 603 Destination dest = (Destination) ctx.lookup(destinationJNDI); 604 if (dest instanceof javax.jms.Topic ) 605 { 606 destType = "javax.jms.Topic"; 607 } 608 else if (dest instanceof javax.jms.Queue ) 609 { 610 destType = "javax.jms.Queue"; 611 } 612 } 613 catch (NamingException ex) 614 { 615 log.debug("Could not do heristic lookup of destination ", ex); 616 } 617 618 } 619 if (destType == null) 620 { 621 log.warn("Could not determine destination type, defaults to: " + 622 DEFAULT_DESTINATION_TYPE); 623 624 destType = DEFAULT_DESTINATION_TYPE; 625 } 626 627 return destType; 628 } 629 } | Popular Tags |