-1

I’m developing a application where I need to load a schema file (xsd) as resource from the jar file, but the file path of getClass().getResource(“..”) is getting prefixed with the working directory.

This is the code:

//ClassLoader classLoader = getClass().getClassLoader();
URL xsdUrl = getClass().getResource(
         "/schema_" + XSD_VERSION.replace(".", "_") + ".xsd"
);

The xsdUrl should be: file:\D:\NetBeansProjects\Java\reports_cli\target\reports_cli-1.0-Beta-jar-with-dependencies.jar!\schema_1_1.xsd

But is returning: C:\Users\joao\file:\D:\NetBeansProjects\Java\reports_cli\target\reports_cli-1.0-Beta-jar-with-dependencies.jar!\schema_1_1.xsd

Is prefixing C:\Users\joao\ to the file path

This is the project: https://github.com/joaomfrebelo/reports_core

and this is the file: https://github.com/joaomfrebelo/reports_core/blob/master/src/main/java/rebelo/reports/core/parse/AParse.java

All method code:

public Unmarshaller unmarshallInstance() throws SAXException, JAXBException {
        LOG.trace(() -> "Create unmarshallInstance");
        LOG.trace(() -> "Read xsd file");

        //ClassLoader classLoader = getClass().getClassLoader();
        URL xsdUrl = getClass().getResource(
                "/schema_" + XSD_VERSION.replace(".", "_") + ".xsd"
        );

        LOG.trace(() -> "Creating JAXBContext.newInstance ");
        JAXBContext jaxbContext = JAXBContext.newInstance(Rreport.class);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

        if (xsdUrl == null) {
            LOG.warn(() -> "Schema not seted please put the schema file ('schema_"
                    + XSD_VERSION.replace(".", "_")
                    + ".xsd' in the same folder as your java file");
        } else {
            File xsd = new File(xsdUrl.getFile());
            if (xsd.isFile() && xsd.canRead()) {
                LOG.debug(() -> "Seting xsd shema file '" + xsd.getAbsolutePath() + "'");
                SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                Schema schema = sf.newSchema(xsd);
                unmarshaller.setSchema(schema);
                LOG.trace(() -> "Schema seted");
            } else {
                LOG.debug(() -> "XSD shema path file '"
                        + xsd.getAbsolutePath()
                        + "' is not a file or is not readable");
            }
        }

        return unmarshaller;
    }
Mashrur
  • 535
  • 10
  • 22
  • Hi @Joao Rebelo, you could check this stack overflow question: https://stackoverflow.com/questions/2343187/loading-resources-using-getclass-getresource, and this answer: https://stackoverflow.com/a/2343224/322950 – Mashrur Jan 19 '20 at 00:09
  • You don't need all this. Just check that `xsdUrl` isn't null as your existence proof, and then use [`SchemaFactory.newSchema(xsdUrl)`](https://docs.oracle.com/javase/8/docs/api/javax/xml/validation/SchemaFactory.html#newSchema-java.net.URL-). You don't have to care where the hell the resource is, or try to make a `File` out of it at all. Also your expectation as to what the `File` should be is baseless. – user207421 Jan 19 '20 at 06:08
  • Is resolved, passing the URL as argument to the sf.newSchema. This is the first time that i use this lib and my mistake was when the error occurred i was searching for a suitable constructor to create the Schema instance from the new Schema, and there aren’t, then i fail on that. Thanks, i did not tested but the answer of grey is suitable too. – Joao Rebelo Jan 19 '20 at 14:38

2 Answers2

3

The problem is not Class.getResource(). The problem is your code treating a resoure inside a jar file as if it was a file on the file system.

It's not.

You can't use File IO to read a resource inside a jar file, and you don't need to. Call the newSchema method that takes a URL as argument. It takes a URL, and that's what Class.getResource() returns.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
3

The mistake you make is trying to convert it to a File handle:

File xsd = new File(xsdUrl.getFile());

getClass().getResource() returns an URL that is not always convertible to a File URL. In this case, it's a URL that points to a part of a jar.

What will always work is loading the resource as an inputstream.

InputStream xsdStream = xsdUrl.openStream();
StreamSource xsdSource = new StreamSource(xsdStream);
Schema schema = sf.newSchema(xsdSource);

Or use the Class.getResourceAsStream() method to skip the URL step:

InputStream xsdStream = getClass().getResourceAsStream("/schema_" + ...)
GeertPt
  • 16,398
  • 2
  • 37
  • 61