Hi, 2015-03-18 11:35 GMT+02:00 Mark Thomas <ma...@apache.org>: > > On 18/03/2015 09:00, Violeta Georgieva wrote: > > Hi, > > > > I have an issue that I investigate and it led me to the implementation > > of org.apache.catalina.startup.WebappServiceLoader.load(Class<T>) > > > > So I have two scenarios: > > - web application with web fragment inside the archive (WEB-INF/lib) > > - web application with functionality of the fragment copied directly to the > > WEB-INF classes i.e. there is no web fragment. > > > > In the first scenario we (WebappServiceLoader.load) will search for SCIs in > > the web fragment using web app loader and then on row 121 we will switch to > > the paren loader and then continue searching the SCIs in other locations. > > In the second scenario we will search for SCIs always with the web app > > loader. > > > > The problem that I'm investigating is in OSGi environment where the parent > > loader of the web app loader does not mean the same as in non OSGi > > environment. When there is no web fragment I can find the container SCIs > > (e.g. Web Socket implementation), but when there is web fragment I cannot > > find the SCIs anymore because of the switch of the loaders. > > > > Can you give me an advice how to overcome this issue? > > I'm trying to use as much as possible from Tomcat implementation and to > > plug only here and there in order to support OSGi environment. > > Hmm. Either we find a way to patch the WebappServiceLoader so it works > with non-OSGI and OSGI environments or it looks like you'd have to use a > custom ContextConfig implementation that used a different > WebappServiceLoader. > > I've no objections to considering patching - with the usual caveats > about the final decision coming down to what the actual patch looks like. > > If I have understood you correctly, the problematic line is: > loader = loader.getParent() > > In the non-OSGI case loader.getParent() is the shared class loader (the > Tomcat 5.5 class loader docs [1] are probably the better ones to look at > in this case as it shows the full hierarchy which was collapsed in later > versions). > > If this line was changed to: > loader = context.getParentClassLoader()
I tried with quick patches in Tomcat and on my side and with one very basic scenario and it is working. I'll test a little bit more but at the moment this is the change that I made in WebappServiceLoader (based on Tomcat 7 trunk): Index: java/org/apache/catalina/startup/ContextConfig.java =================================================================== --- java/org/apache/catalina/startup/ContextConfig.java (revision 1667469) +++ java/org/apache/catalina/startup/ContextConfig.java (working copy) @@ -1278,7 +1278,7 @@ // Step 3. Look for ServletContainerInitializer implementations if (ok) { - processServletContainerInitializers(context.getServletContext()); + processServletContainerInitializers(); } if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) { @@ -1567,13 +1567,13 @@ /** * Scan JARs for ServletContainerInitializer implementations. */ - protected void processServletContainerInitializers(ServletContext servletContext) { + protected void processServletContainerInitializers() { List<ServletContainerInitializer> detectedScis; try { WebappServiceLoader<ServletContainerInitializer> loader = new WebappServiceLoader<ServletContainerInitializer>( - servletContext, context.getContainerSciFilter()); + context, context.getContainerSciFilter()); detectedScis = loader.load(ServletContainerInitializer.class); } catch (IOException e) { log.error(sm.getString( Index: java/org/apache/catalina/startup/WebappServiceLoader.java =================================================================== --- java/org/apache/catalina/startup/WebappServiceLoader.java (revision 1667469) +++ java/org/apache/catalina/startup/WebappServiceLoader.java (working copy) @@ -33,6 +33,8 @@ import javax.servlet.ServletContext; +import org.apache.catalina.Context; + /** * A variation of Java's JAR ServiceLoader that respects exclusion rules for * web applications. @@ -57,7 +59,8 @@ private static final String SERVICES = "META-INF/services/"; private static final Charset UTF8 = Charset.forName("UTF-8"); - private final ServletContext context; + private final ServletContext servletContext; + private final Context context; private final Pattern containerSciFilterPattern; /** @@ -65,8 +68,9 @@ * * @param context the context to use */ - public WebappServiceLoader(ServletContext context, String containerSciFilter) { + public WebappServiceLoader(Context context, String containerSciFilter) { this.context = context; + this.servletContext = context.getServletContext(); if (containerSciFilter != null && containerSciFilter.length() > 0) { containerSciFilterPattern = Pattern.compile(containerSciFilter); } else { @@ -87,17 +91,17 @@ LinkedHashSet<String> applicationServicesFound = new LinkedHashSet<String>(); LinkedHashSet<String> containerServicesFound = new LinkedHashSet<String>(); - ClassLoader loader = context.getClassLoader(); + ClassLoader loader = servletContext.getClassLoader(); // if the ServletContext has ORDERED_LIBS, then use that to specify the // set of JARs from WEB-INF/lib that should be used for loading services @SuppressWarnings("unchecked") List<String> orderedLibs = - (List<String>) context.getAttribute(ServletContext.ORDERED_LIBS); + (List<String>) servletContext.getAttribute(ServletContext.ORDERED_LIBS); if (orderedLibs != null) { // handle ordered libs directly, ... for (String lib : orderedLibs) { - URL jarUrl = context.getResource(LIB + lib); + URL jarUrl = servletContext.getResource(LIB + lib); if (jarUrl == null) { // should not happen, just ignore continue; @@ -118,7 +122,7 @@ } // and the parent ClassLoader for all others - loader = loader.getParent(); + loader = context.getParentClassLoader(); } Enumeration<URL> resources; @@ -180,7 +184,7 @@ private List<T> loadServices(Class<T> serviceType, LinkedHashSet<String> servicesFound) throws IOException { - ClassLoader loader = context.getClassLoader(); + ClassLoader loader = servletContext.getClassLoader(); List<T> services = new ArrayList<T>(servicesFound.size()); for (String serviceClass : servicesFound) { try { Thanks, Violeta > > it would have the same effect for non-OSGI. Would it help in OSGI? > > If this doesn't help, would something along similar lines help? If so, what? > > Mark > (who knows next to nothing about class loading in OSGI environments) > > > [1] http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org >