MyFaces Core
  1. MyFaces Core
  2. MYFACES-2290

Add OSGi bundle information and bundle classloader / activator

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 1.2.8-SNAPSHOT
    • Fix Version/s: 2.0.5
    • Component/s: General
    • Labels:
      None
    • Environment:
      OSGi (Equinox, Apache Felix, ...)

      Description

      The provided patch will add OSGi information to bundle manifest. A bundle activator class makes the MyFaces framework aware that it is running in a bundle environment. A bundle classloader is used to load classes and resources from the bundle classpath. The patch doesn't require any new runtime dependencies and doesn't affect class loading in a non-OSGi environment. Though, small modifications to classloading were needed. This was mainly replacing Thread.currentThread.getContextClassLoader() with ClassUtils methods.

      To run MyFaces in an OSGi environment both bundles (myfaces-api and myfaces-impl) have to be started in the OSGi container. Additionally, the myfaces-impl bundle has to be made available to myfaces-api. Use a fragment bundle with myfaces-api as Fragment-Host and myfaces-impl as Required-Bundle.

      1. myfaces-test-helloworld-osgi-springdm.zip
        13 kB
        Leonardo Uribe
      2. myfaces-test-helloworld-osgi-pax-web.zip
        32 kB
        Leonardo Uribe
      3. myfaces-shared.diff.txt
        13 kB
        Felix Röthenbacher
      4. myfaces-core.diff.txt
        24 kB
        Felix Röthenbacher
      5. MYFACES-2290-no-activator-2.patch
        6 kB
        Leonardo Uribe
      6. MYFACES-2290-no-activator.patch
        6 kB
        Leonardo Uribe
      7. allow-ee6-versioned-apis.diff
        2 kB
        David Jencks

        Issue Links

          Activity

          Felix Röthenbacher created issue -
          Felix Röthenbacher made changes -
          Field Original Value New Value
          Attachment myfaces-core.diff.txt [ 12413516 ]
          Attachment myfaces-shared.diff.txt [ 12413517 ]
          Martin Marinschek made changes -
          Assignee Leonardo Uribe [ lu4242 ]
          Martin Marinschek made changes -
          Priority Major [ 3 ] Critical [ 2 ]
          Leonardo Uribe made changes -
          Attachment MYFACES-2290-no-activator.patch [ 12423491 ]
          Leonardo Uribe made changes -
          Status Open [ 1 ] Patch Available [ 10002 ]
          Leonardo Uribe made changes -
          Attachment myfaces-test-helloworld-osgi-springdm.zip [ 12423936 ]
          Attachment MYFACES-2290-no-activator-2.patch [ 12423937 ]
          Leonardo Uribe made changes -
          Link This issue incorporates MYFACES-1885 [ MYFACES-1885 ]
          Leonardo Uribe made changes -
          Link This issue incorporates MYFACES-1878 [ MYFACES-1878 ]
          Leonardo Uribe made changes -
          Link This issue is related to MYFACES-1158 [ MYFACES-1158 ]
          David Jencks made changes -
          Attachment allow-ee6-versioned-apis.diff [ 12428613 ]
          David Jencks made changes -
          Link This issue blocks GERONIMO-4996 [ GERONIMO-4996 ]
          Leonardo Uribe made changes -
          Link This issue incorporates MYFACES-2442 [ MYFACES-2442 ]
          Leonardo Uribe made changes -
          Leonardo Uribe made changes -
          Link This issue incorporates MYFACES-2550 [ MYFACES-2550 ]
          Leonardo Uribe made changes -
          Link This issue incorporates MYFACES-2995 [ MYFACES-2995 ]
          Leonardo Uribe made changes -
          Comment [ Unfortunately, the patch has some problems. I see some code already committed, but fortunately it does not contains too much changes.

          Let's start with the idea of MyFacesClassLoader. Look this code:

              @Override
              public URL getResource(String s)
              {
                  // context classloader
                  URL url = super.getResource(s);

                  if (url == null)
                  {
                      // try api
                      url = apiClassLoader.getResource(s);

                      if (url == null)
                      {
                          // try impl
                          url = implClassLoader.getResource(s);
                      }

          It is ok, but note if we are using myfaces-bundle, we'll scan on the same classloader twice (because api and impl are the same bundle classloader)

          This code will not work correctly:

              @Override
              public Enumeration<URL> getResources(String s) throws IOException
              {
                  // use all 3 classloaders and merge without duplicates
                  Set<URL> urls = new HashSet<URL>(); // no duplicates

                  // context classloader
                  urls.addAll(Collections.list(super.getResources(s)));

                  // api classlaoder
                  urls.addAll(Collections.list(apiClassLoader.getResources(s)));

                  // impl classlaoder
                  urls.addAll(Collections.list(implClassLoader.getResources(s)));

                  return Collections.enumeration(urls);

          Why? the class loader IS NOT unique per class. Really it depends on the environment. In some scenarios, the same classloader is returned from different classes. In OSGi case, since it is expected myfaces-bundle is used we are adding the same resources 2 times, and if the TCCL can locate resources of myfaces bundle jar, the final result is have 3 times the same files.

          Look this issue: MYFACES-3055 META-INF/faces-config.xml files in JARs are loaded twice . The problem is caused because somebody decide to do the same the patch here is proposing.

          Unfortunately, by the previous reason it is not possible to use a MyFacesClassLoader. The best we can do here is let the code as we had before, so we can differentiate between use TCCL and class ClassLoader. Instead, it is better to have utility methods that handle the case we require (retrieve resource from TCCL and myfaces-bundle CL). There is no need to worry about myfaces-api/myfaces-impl, because that's one reason to have just one jar file in OSGi case (myfaces-bundle).

          Really there is one problem about MyFaces and OSGi. Sometimes, MyFaces requires to instantiate/load resources or classes inside/outside MyFaces. For example, I have one JSF component library that has some resources under META-INF/resources/my.custom.library and MyFaces requires to serve this resource on a page. First MyFaces should scans on its bundle classloader and it does not found the files required. Then, it uses the TCCL to locate the files, and that one "contacts" the custom JSF component library jar to see if this bundle has the files and if that so it serves the required resources.

          Right now, MyFaces REQUIRES the TCCL to work as expected. That was one lesson learned trying to close MYFACES-2290. The problem in that time was FactoryFinder imposes that restriction. Note right now, it is probably we'll commit soon a solution to override FactoryFinder behavior. But the problem we need to think is if there is other way in OSGi to make MyFaces load some resource files in a web context or app context. For now, it is supposed the TCCL do the job (and it does fine), but we don't have any report indicating it is necessary to suppose the opposite. ]
          Leonardo Uribe made changes -
          Status Patch Available [ 10002 ] Resolved [ 5 ]
          Fix Version/s 2.0.5-SNAPSHOT [ 12316168 ]
          Resolution Fixed [ 1 ]
          Leonardo Uribe made changes -
          Fix Version/s 2.0.5 [ 12316346 ]
          Fix Version/s 2.0.5-SNAPSHOT [ 12316168 ]
          Leonardo Uribe made changes -
          Status Resolved [ 5 ] Closed [ 6 ]

            People

            • Assignee:
              Leonardo Uribe
              Reporter:
              Felix Röthenbacher
            • Votes:
              2 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development