Thanks for answer Andrei.
I know the cleanest way would be the URL protocol handler (e.g.
"dbresource://whatever). Also due to the fact that a lot of code
everywhere just creates URLs trying to get to a resource and if the
protocol is not valid - bad luck.
However, as there is the ResourceManager component in CXF, it would be
nice if it would be used consistently everywhere.
As it is a nice feature to allow the user to write a custom resource
resolver which can do so based on a string location which does not
necessarily have to be a URL.
I experimented with the following change and it seems to do what I need
(although I did not fully evaluate whether there are potential side
implications). Of course, there is my custom resource resolver
registered with the ResourceManager as I mentioned in previous mail.
In org.apache.cxf.wsdl11.SchemaUtil:
$ svn diff rt/core/src/main/java/org/apache/cxf/wsdl11/SchemaUtil.java
Index: rt/core/src/main/java/org/apache/cxf/wsdl11/SchemaUtil.java
===================================================================
--- rt/core/src/main/java/org/apache/cxf/wsdl11/SchemaUtil.java
(revision 1449715)
+++ rt/core/src/main/java/org/apache/cxf/wsdl11/SchemaUtil.java (working
copy)
@@ -126,8 +126,8 @@
String systemId = def.getDocumentBaseURI() +
"#types" + schemaCount;
schemaCol.setBaseUri(def.getDocumentBaseURI());
- CatalogXmlSchemaURIResolver schemaResolver =
- new CatalogXmlSchemaURIResolver(bus);
+ ResourceManagerXmlSchemaURIResolver
schemaResolver =
+ new
ResourceManagerXmlSchemaURIResolver(bus);
schemaCol.setSchemaResolver(schemaResolver);
XmlSchema xmlSchema =
schemaCol.read(schemaElem, systemId);
And then the quite simple implementation of
ResourceManagerXmlSchemaURIResolver:
package org.apache.cxf.wsdl11;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import org.apache.cxf.Bus;
import org.apache.cxf.catalog.CatalogXmlSchemaURIResolver;
import org.apache.cxf.resource.ResourceManager;
import org.apache.ws.commons.schema.resolver.URIResolver;
import org.xml.sax.InputSource;
public class ResourceManagerXmlSchemaURIResolver implements URIResolver {
private CatalogXmlSchemaURIResolver parent;
private Bus bus;
public ResourceManagerXmlSchemaURIResolver(
CatalogXmlSchemaURIResolver parent, Bus bus) {
this.parent = parent;
this.bus = bus;
}
public ResourceManagerXmlSchemaURIResolver(Bus bus) {
this(new CatalogXmlSchemaURIResolver(bus), bus);
}
@Override
public InputSource resolveEntity(String targetNamespace,
String schemaLocation, String baseUri) {
InputSource src = getInputSource(schemaLocation);
if (src == null) {
src = parent
.resolveEntity(targetNamespace, schemaLocation,
baseUri);
}
return src;
}
private InputSource getInputSource(String schemaLocation) {
InputStream ins = bus.getExtension(ResourceManager.class)
.getResourceAsStream(schemaLocation);
if (ins == null) {
return null;
} else {
InputSource is = new InputSource(ins);
is.setSystemId(schemaLocation);
is.setPublicId(schemaLocation);
URL url =
bus.getExtension(ResourceManager.class).resolveResource(
schemaLocation, URL.class);
if (url != null) {
is.setSystemId(url.toString());
is.setPublicId(url.toString());
}
return is;
}
}
public Map<? extends String, ? extends String> getResolvedMap() {
Map<String, String> resolvedMap = parent.getResolvedMap();
return resolvedMap;
}
}
On 22. 3. 2013 10:09, Andrei Shakirin wrote:
> Hi Rastislav,
>
> To be honest, I have resolved the similar case only through self-contained
> WSDL (all schemas are embedded into WSDL).
> Anyway I find the topic quite interesting. Perhaps Dan can give you some more
> entry points to digging.
>
> Regards,
> Andrei.
>
>
>> -----Original Message-----
>> From: Rastislav Cesnek [mailto:[email protected]]
>> Sent: Dienstag, 19. März 2013 16:16
>> To: [email protected]
>> Subject: Dynamic service from WSDL+imports loaded from database
>>
>> HI all.
>>
>> I am trying to tweak CXF into a very dynamic scenario, where services would
>> be published dynamically from a priori unknown WSLDs uploaded at run time
>> (together with an interpreted service implementation).
>>
>> Basically, I already have some idea about the dynamic publish (using custom
>> Invoker and custom DataBinding, etc.).
>>
>> What I concept-proofed right now is loading the WSDLs + its imports from
>> database.
>>
>> Here I stumble upon some show stoppers, when I try to create ServiceInfos
>> from a definition like:
>> WSDLServiceBuilder builder = new WSDLServiceBuilder(bus);
>> List<ServiceInfo> serviceInfos = builder.buildServices(definition);
>>
>> The problem is that I am able to read the Definition while serving the
>> content
>> as I wish (from DB, 2 approaches desribed below), however, the
>> WSDLServiceBuilder fails when it tries to get the schemas (I cannot find a
>> possibility to tweak the resource resolving here, as there is a
>> CatalogXmlSchemaURIResolver hard-registered as schema collection
>> resolver):
>>
>> org.apache.ws.commons.schema.XmlSchemaException: Unable to locate
>> imported document at 'db#RootXSD.xsd', relative to
>> 'db#SubWSDL.wsdl#types1'.
>> at
>> org.apache.cxf.catalog.CatalogXmlSchemaURIResolver.resolveEntity(Catalog
>> XmlSchemaURIResolver.java:76)
>> at
>> org.apache.ws.commons.schema.SchemaBuilder.resolveXmlSchema(Schem
>> aBuilder.java:684)
>> at
>> org.apache.ws.commons.schema.SchemaBuilder.handleImport(SchemaBuild
>> er.java:538)
>> at
>> org.apache.ws.commons.schema.SchemaBuilder.handleSchemaElementChil
>> d(SchemaBuilder.java:1513)
>> at
>> org.apache.ws.commons.schema.SchemaBuilder.handleXmlSchemaElement
>> (SchemaBuilder.java:659)
>> at
>> org.apache.ws.commons.schema.XmlSchemaCollection.read(XmlSchemaColl
>> ection.java:540)
>> at
>> org.apache.cxf.common.xmlschema.SchemaCollection.read(SchemaCollectio
>> n.java:129)
>> at org.apache.cxf.wsdl11.SchemaUtil.extractSchema(SchemaUtil.java:133)
>> at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:81)
>> at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:65)
>> at org.apache.cxf.wsdl11.SchemaUtil.getSchemas(SchemaUtil.java:60)
>> at
>> org.apache.cxf.wsdl11.WSDLServiceBuilder.getSchemas(WSDLServiceBuilder
>> .java:372)
>>
>> Any ideas? Can anything like this be done?
>>
>>
>> Basically, for the Definition reading, I tried two approaches which both
>> work:
>>
>> 1) Implementing and registering a CustomResourceResolver with the
>> ResourceManager in the Bus and using standard
>> WSDLManager.getDefinition(String url) method.
>> In the CustomResourceResolver:
>> - in "public InputStream getAsStream(String name)" I recognize the resource
>> name (like "db#name") name and provide na InputSream.
>> - in "public <T> T resolve(String resourceName, Class<T> resourceType)"
>> I always return null (for the URL), so the systemId/publicId of the
>> constructed InputSource stays in the "db#name" form.
>>
>> 2) Copying some code from CXF and implementing custom WSDLLocator and
>> doing completely custom definition reading like:
>> WSDLManager wsdlManager = bus.getExtension(WSDLManager.class);
>> WSDLFactory wsdlFactory = wsdlManager.getWSDLFactory();
>> ExtensionRegistry extensionRegistry = wsdlManager.getExtensionRegistry();
>>
>> WSDLReader reader = wsdlFactory.newWSDLReader();
>> reader.setFeature("javax.wsdl.verbose", false);
>> reader.setFeature("javax.wsdl.importDocuments", true);
>> reader.setExtensionRegistry(extensionRegistry);
>>
>> CatalogWSDLLocator catLocator = new CatalogWSDLLocator(url, bus);
>> CustomDelegatingWSDLLocator = new CustomDelegatingWSDLLocator(url,
>> catLocator, bus); Definition def = reader.readWSDL(wsdlLocator);
>> wsdlManager.addDefinition(url, def); In the CustomDelegatingWSDLLocator I
>> do similar stuff like in the CustomResourceResolver, i.e. provide InputSource
>> or delegate and return an URI (which again stays in the form "db#name" and
>> gets set to
>> systemId/publicId) or delegate.
>>
>> This works charming and the definition is read.
>>
>>
>> I considered using custom URL protocol handler but this is a show-stopper
>> too, as the application runs on JEE server, where I cannot register a custom
>> protocol handler easily (usually, a URLStreamHandlerFactory is already set
>> and it cannot be set a second time). The option to use the system
>> environment property -Djava.protocol.handler.pkgs is also cumbersome as it
>> requires installing classes/modules deep into the server/java core.
>>
>> Please, notice that Whitestein Slovakia has moved to a new location.
>> Prosím, všimnite si že Whitestein Slovensko sa presťahovalo na novú adresu.
>>
>> --
>> Rastislav Cesnek | [email protected]
>> Senior Software Engineer | Advanced Technologies Whitestein Technologies
>> s.r.o. | www.whitestein.com Moskovska 13 | 811 08 Bratislava-Staré Mesto |
>> Slovak Republic Main +421 2 5443-5502 | Fax +421 2 5443-5512
Please, notice that Whitestein Slovakia has moved to a new location.
Prosím, všimnite si že Whitestein Slovensko sa presťahovalo na novú adresu.
--
Rastislav Cesnek | [email protected]
Senior Software Engineer | Advanced Technologies
Whitestein Technologies s.r.o. | www.whitestein.com
Moskovska 13 | 811 08 Bratislava-Staré Mesto | Slovak Republic
Main +421 2 5443-5502 | Fax +421 2 5443-5512