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
>

Reply via email to