Page 2 of 2 FirstFirst 12
Results 11 to 18 of 18

Thread: Loader constraint violation in bundles with different versions

  1. #11
    Join Date
    May 2006
    Posts
    16

    Default

    Hi Costin,

    thanks a lot for your fast answer!

    You need to do following to be able to run my example:

    1. Import the whole projects as a new workspace. Just use springdm-example as your Eclipse workspace.

    2. Define the target platform from the included target platform: Window -> Preferences -> Target Platform and choose the directory of:
    springdm-example\Spring-DM-Target-Platform\target

    3. Close the osgi.udm project because it should be taken from the target platform: udm-1.0.0.jar and udm-1.1.0.jar

    4. After these three steps you will see that everything is okay. All the red marks should be gone now.

    5. Run the osgi.solution -> osgi.solution.launch. This should give you the exception as I wrote before in this forum, because of the dependencies to udm-1.x.x.jar. See the diagram in the beginning of this forum.

    IMHO it should be ok to include the interfaces of udm-1.x.x in both bundles:
    - The interface can change in every version.
    - This same example works fine in a pure OSGi technique. I have tested the same example in pure OSGi style with Activator, ServiceRegistry, ... and it works just fine.

    I can try to run my example in spring-dm 1.1.3 and I let you know the result...

    Just ask again if you have a problem to run the example... I will write an article about spring-dm very soon and would not like having to write that spring-dm does not work with bundles in different versions, as this should be one of the main advantages using OSGi

    Again, thanks a lot for your help...
    Lofi.

  2. #12
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    I've followed your steps and after some setting adjustments I've managed to reproduce the error. On first looks it seems to be caused by a missing uses clauses that indicates the dependency between classes.
    As you pointed out, the dependency between the classes is:
    Solution 1.0.0 -> Pricing 1.0.0 -> Udm 1.1.0
    Solution 1.0.0 -> Udm 1.0.0

    Since the Pricing -> Udm dependency is public (it's available on the interface signature) it becomes a transitive dependency to solution which needs to be wired/pinned to both Udm 1.0.0 (due to the direct dependency) and Udm 1.1.0 (through Pricing).
    The linkage error appears since proxies needs to copy the entire interface and thus are greedy in terms of class loading. If you look at the error, you'll notice that the problem becomes Udm which appears on both Pricing and Solution at the same time so a new version of the class breaks the bundle class space consistency.
    I'll take a look to see whether there is something we can do from Spring DM side though the class consistency is enforced by OSGi and w/o the proper directives (uses), OSGi cannot do that.
    An alternative for your application would be to remove the transitive dependency (Udm) from the Pricing interface - there is no need to have that on the interface.

    Regarding the standard OSGi usage, I'd be interested in seeing that example. My guess would be that the setter is not used (and thus the class loading is not triggered).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #13
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Looking at the past posts, as you pointed out by adding the uses directive the bundle doesn't get activated since the OSGi platform detects the versioning conflict and thus cannot guarantee the class space consistency.
    By removing the constraint, the class incompatibility is left in the open and through the uses of proxies (in this case JDKs which are quite lightweight in terms of class loading) Spring DM triggers it.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  4. #14
    Join Date
    May 2006
    Posts
    16

    Default

    Hi Costin

    Sorry for the late answer. It was carneval time here in Cologne, Germany ;-)

    You can download the pure OSGi example just here:
    http://lofidewanto.googlepages.com/v...gi-example.zip

    The steps to run the application are just the same as before: import whole projects, define the target platform, close the udm project and launch the solution project. You will see that the whole bundles will be activated and started correctly. The interfaces and also the implementation classes are identical with the SpringDM example. Only we need to have activators for each bundle.

    An alternative for your application would be to remove the transitive dependency (Udm) from the Pricing interface - there is no need to have that on the interface.
    Sorry I cannot follow you on this... I only exported the pricing package from the pricing bundle. I also need to have the udm injected into the pricing interface since I'm using the udm bundle in my implementation (see PricingServiceImpl.java). Could you please explain more about this alternative?

    Thanks a lot!
    Lofi.

  5. #15
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    It took so long to reply since I've had issues with the project that you sent (the platform didn't contain the proper jars but jetty and javax.servlet). Anyway, I started the bundles on just the Equinox platform outside Eclipse.
    The problem that I described can be exhibited by just adding a System out inside the Solution activator as follows:

    Code:
    // existing code
    PricingService pricingService = (PricingService) context
             .getService(pricingServiceReference);
    // inserted line
    System.out.println(pricingService.getUdmService().toString());
    // existing code
    solutionService.setPricingService(pricingService);
    The exception is similar to what you get with Spring DM:

    osgi> Start: UDM Version 1.0.0
    Start: UDM Version 1.1.0
    Start: PRICING Version 1.0.0
    Start: PRICING for: UDM Version 1.1.0
    Start: SOLUTION Version 1.0.0


    osgi> ss

    Framework is launched.

    id State Bundle
    0 ACTIVE org.eclipse.osgi_3.3.1.R33x_v20070828
    1 RESOLVED net.sf.cglib_2.1.3
    2 RESOLVED jcl104.over.slf4j_1.4.3
    3 RESOLVED slf4j.api_1.4.3
    4 RESOLVED slf4j.jdk14_1.4.3
    5 ACTIVE osgi.udm_1.0.0
    6 ACTIVE osgi.udm_1.1.0
    7 ACTIVE osgi.pricing_1.0.0
    8 RESOLVED osgi.solution_1.0.0

    osgi> start 8
    Start: SOLUTION Version 1.0.0
    org.osgi.framework.BundleException: Exception in osgi.solution.Activator.start()
    of bundle osgi.solution.
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl.startActiv
    ator(BundleContextImpl.java:1018)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl.start(Bund
    leContextImpl.java:974)
    at org.eclipse.osgi.framework.internal.core.BundleHos t.startWorker(Bundl
    eHost.java:346)
    at org.eclipse.osgi.framework.internal.core.AbstractB undle.start(Abstrac
    tBundle.java:260)
    at org.eclipse.osgi.framework.internal.core.AbstractB undle.start(Abstrac
    tBundle.java:252)
    at org.eclipse.osgi.framework.internal.core.Framework CommandProvider._st
    art(FrameworkCommandProvider.java:260)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknow n Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Un known Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.osgi.framework.internal.core.Framework CommandInterpreter.
    execute(FrameworkCommandInterpreter.java:150)
    at org.eclipse.osgi.framework.internal.core.Framework Console.docommand(F
    rameworkConsole.java:291)
    at org.eclipse.osgi.framework.internal.core.Framework Console.console(Fra
    meworkConsole.java:276)
    at org.eclipse.osgi.framework.internal.core.Framework Console.run(Framewo
    rkConsole.java:218)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.NoSuchMethodError: osgi.solution.SolutionService.setUdmServ
    ice(Losgi/udm/UdmServiceV
    at osgi.solution.Activator.start(Activator.java:29)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl$2.run(Bund
    leContextImpl.java:999)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.eclipse.osgi.framework.internal.core.BundleCon textImpl.startActiv
    ator(BundleContextImpl.java:993)
    ... 14 more
    Nested Exception:
    java.lang.NoSuchMethodError: osgi.solution.SolutionService.setUdmService(Losgi/u
    dm/UdmServiceV
    Could you please explain more about this alternative?
    The problem is that you are exposing a transitive dependecy (that causes the versioning issue) inside the solution bundle which means that Udm 1.0.0 and Udm 1.1.0 are going to clash.
    A workaround is to remove the setter/getter for Udm from the Pricing interface and just leave the pricing contract in there and leave each bundle to do its own configuration.
    That is,
    Code:
    public interface PricingService {
    
        public String getPrice();
    
        public void setUdmService(UdmService udmService);
    
        public UdmService getUdmService();
    }
    becomes

    Code:
    public interface PricingService {
    
        public String getPrice();
    
    }
    Again you can configure the implementation directly inside the Pricing activator and just publish the object through the Pricing interface.

    Lastly, note that this is not a Spring DM or OSGi problem per se - it's a generic versioning problem : you are forcing two versions of the same class inside the same space. As I've pointed out if you are using the uses clause, the bundle can't start due to this conflict. By removing the uses clause, you are not telling the platform about the bundle constrains so the bundle does start but the problem still remains as shown above.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  6. #16
    Join Date
    May 2006
    Posts
    16

    Default

    Hi Costin,

    thanks a lot for your reply. Sorry for the late answer...

    Quote Originally Posted by Costin Leau View Post
    It took so long to reply since I've had issues with the project that you sent (the platform didn't contain the proper jars but jetty and javax.servlet). Anyway, I started the bundles on just the Equinox platform outside Eclipse.
    This is weird since I checked it before and I can easily import the whole things and run the examples easily within Eclipse 3.4...

    Quote Originally Posted by Costin Leau View Post
    The problem that I described can be exhibited by just adding a System out inside the Solution activator as follows:
    Yes, this is true. Does this mean that Spring dm is a bit more "aggresive" by doing the injection? I mean that the "getter methods" will be executed directly within the startup phase?

    Quote Originally Posted by Costin Leau View Post
    ...
    becomes

    Code:
    public interface PricingService {
    
        public String getPrice();
    
    }
    Again you can configure the implementation directly inside the Pricing activator and just publish the object through the Pricing interface.

    Lastly, note that this is not a Spring DM or OSGi problem per se - it's a generic versioning problem : you are forcing two versions of the same class inside the same space. As I've pointed out if you are using the uses clause, the bundle can't start due to this conflict. By removing the uses clause, you are not telling the platform about the bundle constrains so the bundle does start but the problem still remains as shown above.
    Thanks a lot for your explanation. Yes, I don't need to export the two methods within the Pricing interface and I can still inject the dependency into the PricingImpl class with Spring... Now the examples work correctly!

    Cheers,
    Lofi

    BTW. Don't forget to close the bug given on the top of this discussion

  7. #17
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Yes, this is true. Does this mean that Spring dm is a bit more "aggresive" by doing the injection? I mean that the "getter methods" will be executed directly within the startup phase?
    As I've explained earlier, the 'greedy' class analysis is caused by using proxying since the weaving process literally has to introspect the target class.

    BTW. Don't forget to close the bug given on the top of this discussion
    Already did that a few days ago.

    Cheers,
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  8. #18

    Default

    Another way to get this linkage error is to have a lib on your bundle's classpath containing the same class (package + class name) than one of your runtime bundles.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •