Index: osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/EJBExtender.java =================================================================== --- osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/EJBExtender.java (revision 36641) +++ osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/EJBExtender.java (working copy) @@ -90,8 +90,28 @@ public void stop() { if (started.getAndSet(false)) { - context.removeBundleListener(this); - if (c !=null) c.undeployAll(); + try { + context.removeBundleListener(this); + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while removing the " + + "EJB bundle listener.", t); + } + + if (c !=null) { + try { + c.undeployAll(); + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while undeploying " + + "EJB JAR bundles.", t); + } + + try { + c.closeEJBTracker(); + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while closing the " + + "EJB tracker."); + } + } } } Index: osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/OSGiEJBContainer.java =================================================================== --- osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/OSGiEJBContainer.java (revision 36641) +++ osgi-javaee/osgi-ejb-container/src/main/java/org/glassfish/osgiejb/OSGiEJBContainer.java (working copy) @@ -60,6 +60,9 @@ import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @author Sanjeeb.Sahoo@Sun.COM @@ -67,6 +70,8 @@ public class OSGiEJBContainer extends OSGiContainer { private EJBTracker ejbTracker; + private static final Logger logger = + Logger.getLogger(OSGiEJBContainer.class.getPackage().getName()); private final InitialContext ic; @@ -89,43 +94,65 @@ return new OSGiEJBDeploymentRequest(deployer, archiveFactory, env, reporter, b); } + void closeEJBTracker() { + ejbTracker.close(); + } + class EJBTracker extends ServiceTracker { + private Map> + serviceReferenceToEjbSvcRegQueueMap = + Collections.synchronizedMap( + new HashMap>()); + EJBTracker() { super(getBundleContext(), OSGiApplicationInfo.class.getName(), null); } @Override public Object addingService(ServiceReference reference) { - OSGiApplicationInfo osgiApplicationInfo = OSGiApplicationInfo.class.cast(context.getService(reference)); - String exportEJB = (String)osgiApplicationInfo.getBundle().getHeaders().get(Constants.EXPORT_EJB); - if (exportEJB != null) { - ApplicationInfo ai = osgiApplicationInfo.getAppInfo(); - Application app = ai.getMetaData(Application.class); - Collection ejbs = app.getEjbDescriptors(); - System.out.println("addingService: Found " + ejbs.size() + " no. of EJBs"); - Collection ejbsToBeExported = new ArrayList(); - if (Constants.EXPORT_EJB_ALL.equals(exportEJB)) { - ejbsToBeExported = ejbs; - } else { - StringTokenizer st = new StringTokenizer(exportEJB, ","); - while(st.hasMoreTokens()) { - String next = st.nextToken(); - for (EjbDescriptor ejb : ejbs) { - if (next.equals(ejb.getName())) { - ejbsToBeExported.add(ejb); + Object serviceObj = context.getService(reference); + + try { + OSGiApplicationInfo osgiApplicationInfo = (OSGiApplicationInfo)serviceObj; + String exportEJB = (String)osgiApplicationInfo.getBundle().getHeaders().get(Constants.EXPORT_EJB); + if (exportEJB != null) { + ApplicationInfo ai = osgiApplicationInfo.getAppInfo(); + Application app = ai.getMetaData(Application.class); + Collection ejbs = app.getEjbDescriptors(); + System.out.println("addingService: Found " + ejbs.size() + " no. of EJBs"); + Collection ejbsToBeExported = new ArrayList(); + if (Constants.EXPORT_EJB_ALL.equals(exportEJB)) { + ejbsToBeExported = ejbs; + } else { + StringTokenizer st = new StringTokenizer(exportEJB, ","); + while(st.hasMoreTokens()) { + String next = st.nextToken(); + for (EjbDescriptor ejb : ejbs) { + if (next.equals(ejb.getName())) { + ejbsToBeExported.add(ejb); + } } } } - } - for (EjbDescriptor ejb : ejbsToBeExported) { - registerEjbAsService(ejb, osgiApplicationInfo.getBundle()); + ConcurrentLinkedQueue ejbServiceRegistrationQueue = + getOrCreateEjbServiceRegistrationQueue(reference); + + for (EjbDescriptor ejb : ejbsToBeExported) { + registerEjbAsService(ejb, osgiApplicationInfo.getBundle(), + ejbServiceRegistrationQueue); + } } + } catch(Throwable t) { + logger.log(Level.SEVERE, + "An error occurred while adding a EJB JAR Bundle to " + + "the EJBTracker", t); } - return osgiApplicationInfo; + return serviceObj; } - private void registerEjbAsService(EjbDescriptor ejb, Bundle bundle) { + private void registerEjbAsService(EjbDescriptor ejb, Bundle bundle, + Queue ejbServiceRegistrationQueue) { System.out.println(ejb); if (EjbSessionDescriptor.TYPE.equals(ejb.getType())) { EjbSessionDescriptor sessionBean = EjbSessionDescriptor.class.cast(ejb); @@ -144,7 +171,12 @@ Properties props = new Properties(); props.put("jndi-name", jndiName); // Note: we register using the bundle context of the bundle containing the EJB. - ejbBundleContext.registerService(lbi, service, props); + ServiceRegistration ejbServiceRegistration = + ejbBundleContext.registerService(lbi, service, props); + + if(ejbServiceRegistration != null) { + ejbServiceRegistrationQueue.add(ejbServiceRegistration); + } } } } else { @@ -154,13 +186,84 @@ @Override public void removedService(ServiceReference reference, Object service) { - OSGiApplicationInfo osgiApplicationInfo = OSGiApplicationInfo.class.cast(context.getService(reference)); - ApplicationInfo ai = osgiApplicationInfo.getAppInfo(); - Application app = ai.getMetaData(Application.class); - Collection ejbs = app.getEjbDescriptors(); - System.out.println("removedService: Found " + ejbs.size() + " no. of EJBs"); - for (EjbDescriptor ejb : ejbs) { + try { + OSGiApplicationInfo osgiApplicationInfo = (OSGiApplicationInfo)service; + ApplicationInfo ai = osgiApplicationInfo.getAppInfo(); + Application app = ai.getMetaData(Application.class); + Collection ejbs = app.getEjbDescriptors(); + System.out.println("removedService: Found " + ejbs.size() + " no. of EJBs"); + for (EjbDescriptor ejb : ejbs) { + } + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while removing a " + + "EJB JAR bundle from the EJBTracker.", t); } + + try { + unregisterEjbServices(reference); + removeEjbServiceRegistrationQueueIfEmpty(reference); + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while unregistering " + + "EJB OSGi services exposed by the EJB JAR bundle.", t); + } + + context.ungetService(reference); } + + private void unregisterEjbServices(ServiceReference sr) { + ConcurrentLinkedQueue queue = + serviceReferenceToEjbSvcRegQueueMap.get(sr); + + if(queue != null) { + ServiceRegistration ejbServiceRegistration; + while((ejbServiceRegistration = queue.poll()) != null) { + try { + ejbServiceRegistration.unregister(); + } catch(IllegalStateException e) { + // If an IllegalStateException is thrown, the service + // has already been unregistered. We can ignore these + // exceptions here. + } catch(Throwable t) { + logger.log(Level.SEVERE, "An error occurred while unregistering " + + "an EJB OSGi service.", t); + } + } + } + } + + private ConcurrentLinkedQueue getOrCreateEjbServiceRegistrationQueue( + ServiceReference sr) { + if(sr == null) { + throw new NullPointerException(); + } + + Map> map = + serviceReferenceToEjbSvcRegQueueMap; + + ConcurrentLinkedQueue queue; + synchronized(map) { + queue = map.get(sr); + + if(queue == null) { + queue = new ConcurrentLinkedQueue(); + map.put(sr, queue); + } + } + return queue; + } + + private void removeEjbServiceRegistrationQueueIfEmpty(ServiceReference sr) { + Map> map = + serviceReferenceToEjbSvcRegQueueMap; + + synchronized(map) { + ConcurrentLinkedQueue queue = + map.get(sr); + + if(queue != null && queue.isEmpty()) { + map.remove(sr); + } + } + } } }