Announcement Announcement Module
Collapse

Spring Dynamic Modules forum decommissioned in favor of Eclipse Gemini Blueprint

With the official first release of Eclipse Gemini Blueprint shipped, the migration of the Spring Dynamic Modules code base to the Eclipse Foundation, as part of the Gemini project, has been completed.

As such, this forum has been decommissioned in favour of the Eclipse Gemini forums.
See more
See less
Is there a trick to getting castor to play well in osgi? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Is there a trick to getting castor to play well in osgi?

    I'm using dm server 2 (CI-476 but I don't think that matters atm), spring oxm 3.0.0.RC1, and castor 1.2.0 from EBR.

    The problem I'm having is that castor reads a mapping file that references a file in my project's bundle (which is exported) but cannot get to the class file because, presumably, it's using its own classloader.

    So, I'm wondering if anyone has gotten castor to work in osgi without just embedding the castor JAR in the bundle itself? Doing this is not an option for us because we'll have multiple bundles that would be using castor, and they all can't export castor so OXM can use it.

    Surely (hopefully) there's something I'm missing? I've scoured google and the forums here and maybe I'm just searching for it incorrectly.

    Hoping,
    Scott

  • #2
    Suspicious Trick Discovered

    Ok, so I found a way to get what I want here, but am suspicious. It seems too easy, and feels like I'm just pushing one problem off to be discovered later as a more insidious one.

    I'm hoping someone who knows this stuff (spring oxm, spring dm and osgi itself) can validate or show me that this should not be the way to go.

    What I did was to subclass the org.springframework.oxm.castor.CastorMarshaller class and override the createXMLContext() method:
    Code:
    	@Override
    	protected XMLContext createXMLContext(Resource[] mappingLocations, Class[] targetClasses, String[] targetPackages)
    			throws MappingException, ResolverException, IOException {
    
    		XMLContext context = new XMLContext();
    		if (!ObjectUtils.isEmpty(mappingLocations)) {
    			ClassLoader cl = Thread.currentThread().getContextClassLoader();
    			Mapping mapping = new Mapping(cl);
    			for (Resource mappingLocation : mappingLocations) {
    				mapping.loadMapping(SaxResourceUtils.createInputSource(mappingLocation));
    			}
    			context.addMapping(mapping);
    		}
    		if (!ObjectUtils.isEmpty(targetClasses)) {
    			context.addClasses(targetClasses);
    		}
    		if (!ObjectUtils.isEmpty(targetPackages)) {
    			context.addPackages(targetPackages);
    		}
    		return context;
    	}
    The only change I made here was the creation of the Mapping class - I now pass it in the TCCL rather than not giving it anything (which defaults to this.getClass().getClassLoader()).

    This happens to work for me because the spring context is being created from the same bundle that also imports the classes castor needs to create for me.

    So, as long as this precondition is true - that my oxm CastorMarshaller bean is created in a context whose classloader has access to the class it needs to create, won't this just always work?

    And if so, should this maybe be submitted back into spring oxm as a possible patch?

    Comment


    • #3
      Scott, I think your solution is pretty good for your case - whether the solution works for everyone that's debateable but feel free to raise up this problem on the Spring OXM tracker.

      The TCCL contract is very loose (actually there isn't any) and thus it works great in some cases while it fails miserably in others. The TCCL support in Spring DM and dm Server has been introduced exactly for this reason, to prevent libraries or code that otherwise works just fine, fail unexpectedly (since the TCCL is null or improperly set).

      Another potential solution to your problem, would be extending Castor classloader to include the modules/mapping that Castor needs to work with - I'm not familiar with the library so I can't tell whether this approach is better or not.

      Comment


      • #4
        dont forget the unmarshaller...

        also might want to override the unmarshaller...

        Code:
        	@Override
        	protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
        		unmarshaller.setValidation(validating);
        		unmarshaller.setWhitespacePreserve(this.whitespacePreserve);
        		unmarshaller.setIgnoreExtraAttributes(this.ignoreExtraAttributes);
        		unmarshaller.setIgnoreExtraElements(this.ignoreExtraElements);
        		unmarshaller.setClassLoader(cl);
        	}

        Comment

        Working...
        X