views:

38

answers:

3

I have a web-service (with Spring-WS).

I have a jar with several schemas (schema1.xsd, schema2.xsd and schema3.xsd) which I include in my web service.

Is there a way to expose the schemas from the jar through a servlet somehow in my web-service wep app?

My Spring MessageDispatcherServlet is mapped to /ws/

I would like my schemas to be exposed to /schemas/schema1.xsd /schemas/schema2.xsd and so on.

I have an idea how to do it with a servlet, but it's too verbose and there has to be a nicer way.

The way I am thinking is have a servlet filter and everything that hits /schemas/ check if it is in my list of allowed resources and display it.

This has to be a server agnostic solution. (For instance http://tuckey.org/urlrewrite/ will not work).

Thanks.

+1  A: 

They only way I've found to do this in the past is the have a Spring controller (or servlet, whatever's your poison), which opens a stream to the resource in the JAR (using Class.getResourceAsStream, for example), and then "piping" it to the HTTP response (using Apache Commons IO's IOUtils.copy()).

It's not very nice, but it's a fully generic solution (just parameterise it with the classpath of the resource).

Here's my source for this:

@Controller
public class ResourceController {

    private Resource resource;

    @Required
    public void setResource(Resource resource) {
        this.resource = resource;
    }

    @RequestMapping
    public void handleRequest(HttpServletResponse httpResponse) throws IOException {
        InputStream resourceStream = resource.getInputStream();
        try {
            IOUtils.copy(resourceStream, httpResponse.getOutputStream());
        } finally {
            resourceStream.close();
        }
    }

}
skaffman
I did the same thing with a servlet.For security purposes I need to define the list of xsd's I will allow. I do that via init parameters.Still this solution seems to me to be a hack. I thought there has to be a easier way, a Spring way, but I guess because of security issues it might cause, nobody actually implement any solutions.
Alexandru Luchian
It feels like a hack, yes, but then the contents of JAR files (and things under `/WEB-INF`) are not *supposed* to be accessible via the client, so you have to go the extra mile.
skaffman
A: 

Just package your XSD's in a war called schemas.war, put in a default web.xml, and deploy the war in whatever web container you use. Its the easiest, code-less way to solve the problem.

sri
+1  A: 

Me again! Having seen the comments to your original question, I thought I'd offer an alternative solution.

If I understand your problem, it seems you have a WSDL (generated by Spring-WS) which contains references to the various schema. When a client tries to follow those schema references, it fails, because there is no such resource.

Spring-WS offers a nice way out of this, which is described in the section on WSDL exposure:

If you want to use multiple schemas, either by includes or imports, you might want to use the CommonsXsdSchemaCollection, and refer to that from the DefaultWsdl11Definition, like so:

<bean id="schemaCollection" class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
    <property name="xsds">
        <list>
            <value>classpath:/path/to/schema1.xsd</value>
            <value>classpath:/path/to/schema2.xsd</value>
        </list>
    </property>
    <property name="inline" value="true"/>
</bean>

When the inline property is enabled, it follows all XSD imports and includes, and inlines them in the WSDL. This greatly simplifies the deloyment of the schemas, which still making it possible to edit them separately.

So what you get is a generated WSDL with all of the referenced schemas inlined, so there are no references for the client to follow. It's very slick, and means you don't have to expose your schema files individually.

skaffman
Waw! That's what I need.Thanks a million, I should read more :)
Alexandru Luchian