Search code examples
osgixstreamoptaplannerapache-servicemix

Xstream - OSGI - OptaPlanner


i'm trying to use optaplanner OSGI-core. In a Java standard environment i have custimze the Vehiclerouting example in order to run it without UI and all works fine. After that i made an OSGI bundle of this project, but when it start i get this error from Xstream.

com.thoughtworks.xstream.mapper.CannotResolveClassException: org.optaplanner.core.config.solver.SolverConfig
at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:79)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:30)

the exception is raised from this snippet of code:

     @Override
    protected Solver createSolver() {
       File solver = new File(SOLVER_CONFIG);
       SolverFactory solverFactory =SolverFactory.createFromXmlFile(solver);

       return solverFactory.buildSolver();
}`

Googling i undestrand that it is a problem related to Xtream and Class Loading on OSGI, someone suggest to wrap Xstream inside the bundle that use it. But in my case Xstream metodhs are called by a 3rd part bundle (Optaplanner-core).

How can i fix this problem?


Solution

  • I think I solved this issue.

    So, I have 3 bundles:

    • XStream (Bundle A)
    • OptaPlanner-Core, which is where org.optaplanner.core.config.solver.SolverConfig is (Bundle B)
    • My code that use the SolverFactory.createFromXmlResource() (Bundle C)

    Now, when Bundle B invokes xStream.fromXML (https://github.com/droolsjbpm/optaplanner/blob/2a0c40283c8b8a068d24c40297581ff2c597bf1e/optaplanner-core/src/main/java/org/optaplanner/core/impl/solver/XStreamXmlSolverFactory.java#L117) it needs to resolve SolverConfig.class (https://github.com/droolsjbpm/optaplanner/blob/master/optaplanner-core/src/main/java/org/optaplanner/core/impl/solver/XStreamXmlSolverFactory.java#L51).

    However, in an OSGI environment, XStream lives in an isolated Classloader, so Bundle A can't access Bundle B's components. That said, to make XStream work, I have to call the Xstream.setClassloader(getclass().getClassloader()) after the initialization.

    Finally, XStream must resolve the class that I declare into the solver.xml and this class is in Bundle C. But since OptaPlanner-Core, obviously, can't import that class, I need to add <DynamicImport-Package>*</DynamicImport-Package> in Bundle B's pom.xml. In this way OptaPlanner can load everything it needs at runtime.