使用ClassPathResource访问Jar文件中的文件

huangapple go评论52阅读模式
英文:

Accessing files in a Jar using ClassPathResource

问题

以下是代码部分的翻译:

我有一个Spring应用程序我必须将其转换为JAR文件在这个应用程序中我有一个单元测试

@BeforeEach
void setUp() throws IOException {
    //facturxHelper = new FacturxHelper();
    facturxService = new FacturxService();
    // String pdf = "facture.pdf"; // 无效的pdfa1
    String pdf = "resources/VALID PDFA1.pdf";
    // InputStream sourceStream  = new FileInputStream(pdf); //
    InputStream sourceStream = getClass().getClassLoader().getResourceAsStream(pdf);
    byte[] sourceBytes = IOUtils.toByteArray(sourceStream);
    this.b64Pdf = Base64.getEncoder().encodeToString(sourceBytes);
}

@Test
void createFacturxMin() throws Exception {
    // 创建一个包含请求对象的FacturX
    FacturxRequestMin request = FacturxRequestMin.builder()
            .pdf(this.b64Pdf)
            .chorusPro(Boolean.FALSE)
            .invoiceNumber("FA-2017-0010")
            .issueDate("13/11/2017")
            .buyerReference("SERVEXEC")        
            .seller(TradeParty.builder()
                    .name("Au bon moulin")
                    .specifiedLegalOrganization(LegalOrganization.builder()
                            .id("99999999800010")
                            .scheme(SpecifiedLegalOrganizationScheme.FR_SIRENE.getSpecifiedLegalOrganizationScheme())
                            .build())
                    .postalAddress(PostalAddress.builder()
                            .countryId(CountryIso.FR.name())
                            .build())
                    .vatId("FR11999999998")
                    .build())
            .buyer(TradeParty.builder()
                    .name("Ma jolie boutique")
                    .specifiedLegalOrganization(LegalOrganization.builder()
                            .id("78787878400035")
                            .scheme(SpecifiedLegalOrganizationScheme.FR_SIRENE.getSpecifiedLegalOrganizationScheme())
                            .build())
                    .build())
            .headerMonetarySummation(HeaderMonetarySummation.builder()
                    .taxBasisTotalAmount("624.90")
                    .taxTotalAmount("46.25")
                    .prepaidAmount("201.00")
                    .grandTotalAmount("671.15")
                    .duePayableAmount("470.15")
                    .build())
            .build();


    FacturXAppManager facturXAppManager = new FacturXAppManager(facturxService);
    FacturxResponse facturxResponse = facturXAppManager.createFacturxMin(request);

    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String json = gson.toJson(facturxResponse);
    System.out.println(json);
}

这段代码是一个Spring应用程序,用于创建XML并将其嵌入到PDF文件中。它包括了设置测试数据和创建FacturX的过程。如果您需要更多的信息或其他部分的翻译,请告诉我。

英文:

I have a spring application that i must convert to jar. In this application I have a unit test:

@BeforeEach
void setUp() throws IOException {
//facturxHelper = new FacturxHelper();
facturxService = new FacturxService();
// String pdf = "facture.pdf"; // invalid pdfa1
String pdf = "resources/VALID PDFA1.pdf";
// InputStream sourceStream  = new FileInputStream(pdf); //
InputStream sourceStream = getClass().getClassLoader().getResourceAsStream(pdf);
byte[] sourceBytes = IOUtils.toByteArray(sourceStream);
this.b64Pdf = Base64.getEncoder().encodeToString(sourceBytes);
}
@Test
void createFacturxMin() throws Exception {
// on va créer une facturX avec l'objet request
FacturxRequestMin request = FacturxRequestMin.builder()
.pdf(this.b64Pdf)
.chorusPro(Boolean.FALSE)
.invoiceNumber("FA-2017-0010")
.issueDate("13/11/2017")
.buyerReference("SERVEXEC")        
.seller(TradeParty.builder()
.name("Au bon moulin")
.specifiedLegalOrganization(LegalOrganization.builder()
.id("99999999800010")                                .scheme(SpecifiedLegalOrganizationScheme.FR_SIRENE.getSpecifiedLegalOrganizationScheme())
.build())
.postalAddress(PostalAddress.builder()
.countryId(CountryIso.FR.name())
.build())
.vatId("FR11999999998")
.build())
.buyer(TradeParty.builder()
.name("Ma jolie boutique")
.specifiedLegalOrganization(LegalOrganization.builder()
.id("78787878400035")
.scheme(SpecifiedLegalOrganizationScheme.FR_SIRENE.getSpecifiedLegalOrganizationScheme())
.build())
.build())
.headerMonetarySummation(HeaderMonetarySummation.builder()
.taxBasisTotalAmount("624.90")
.taxTotalAmount("46.25")
.prepaidAmount("201.00")
.grandTotalAmount("671.15")
.duePayableAmount("470.15")
.build())
.build();
FacturXAppManager facturXAppManager = new FacturXAppManager(facturxService);
FacturxResponse facturxResponse = facturXAppManager.createFacturxMin(request);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(facturxResponse);
System.out.println(json);
}

The aim of the application is to create an xml and to embed it into the pdf file.

My issue is concerning an xml validation through xsd.

Here is an abstract of the code :

public static boolean xmlValidator(String fxGuideLine, String xmlString) throws Exception {
System.out.println("xmlValidator() called");
File xsdFile = null;
Source source = new StreamSource(new StringReader(xmlString));
// i removed a lot of if else statement concerning files which allow to validate xml
try {
xsdFile = new ClassPathResource(FacturxConstants.FACTUR_X_MINIMUM_XSD).getFile();
} catch (IOException e) {
throw new FacturxException(e.getMessage());
}
// validation du contenu XML
try {
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdFile);
Validator validator = schema.newValidator();
validator.validate(source);
return true;
} catch (SAXException | IOException e) {
throw new FacturxException(e.getLocalizedMessage());
}
...
}

In constants class, I added path to the xsd file:

public static final String FACTUR_X_MINIMUM_XSD = "resources/xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

In my POM file I do want to put the resources files in the built jar.

<build>
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<outputDirectory> ${project.build.outputDirectory}\resources</outputDirectory>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.4.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>

When I do a simple maven clean package, everything is running perfectly.
So far so good.

Next step is where my problem comes. Let's consider i want to use this dependency in an another application (a spring boot application). The previous jar compiled is a high level API that i want to integrate.

I launched the following command line :

mvn install:install-file -Dfile=myapi.jar -DgroupId=fr.myapi -DartifactId=graph-api-sharepoint -Dversion=1.0.0-SNAPSHOT -Dpackaging=jar

I do add my dependency correctly in my new project. that's perfect.
To check if my import worked correctly, i created a simple unit test with the same code (I do have a VALID PDFA1 in my resources folder. So far so good.

When running the test I do have the following error:

class path resource [resources/xsd/BASIC-WL_XSD/FACTUR-X_BASIC-WL.xsd] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/.m2/repository/fr/myapi/1.1.0/myapi-1.1.0.jar!/resources/xsd/BASIC-WL_XSD/FACTUR-X_BASIC-WL.xsd

How can i fix this issue ? I read many post but not fixes solved my issue. I do also think that i will have an issue also while compiling the springboot app as a jar

As mentionned, using a File won't work.
In the current code I updated it using InputStream:

InputStream is = new ClassPathResource(FacturxConstants.FACTUR_X_MINIMUM_XSD).getInputStream();
xsdSource = new StreamSource(is);

if my xsd path doesn't have resources:

public static final String FACTUR_X_MINIMUM_XSD = "xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

I have the following exception:

class path resource [xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd] cannot be opened because it does not exist

If i do put

public static final String FACTUR_X_MINIMUM_XSD = "resources/xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

the response is the following:

 src-resolve: Cannot resolve the name 'ram:ExchangedDocumentContextType' to a(n) 'type definition' component.

I updated also the SchemaFactory and schema implementation:

SchemaFactory schemaFactory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(source);
return true;

答案1

得分: 1

public static final String FACTUR_X_MINIMUM_XSD = "/xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

public static boolean xmlValidator(String fxGuideLine, String xmlString) throws Exception {
    System.out.println("xmlValidator() called");
    Source source = new StreamSource(new StringReader(xmlString));
    // I removed a lot of if-else statements concerning files that allow validation of XML.
    try {
        InputStream xsd = new ClassPathResource(FacturxConstants.FACTUR_X_MINIMUM_XSD).getInputStream();
        StreamSource xsdSource = new StreamSource(xsd);
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = schemaFactory.newSchema(xsdSource);
        Validator validator = schema.newValidator();
        validator.validate(source);
        return true;
    } catch (SAXException | IOException e) {
        throw new FacturxException(e.getLocalizedMessage());
    }
    ...
}
英文:
public static final String FACTUR_X_MINIMUM_XSD = "resources/xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

Is wrong it should be (assuming src/main/resources/xsd is the actual location you are using).

public static final String FACTUR_X_MINIMUM_XSD = "/xsd/MINIMUM_XSD/FACTUR-X_MINIMUM.xsd";

Then your code is using a java.io.File which won't work, as a java.io.File needs to be a physical file on the file system. Which this isn't as it is inside a jar file. You need to use an InputStream.

public static boolean xmlValidator(String fxGuideLine, String xmlString) throws Exception {
    System.out.println("xmlValidator() called");
    Source source = new StreamSource(new StringReader(xmlString));
    // i removed a lot of if else statement concerning files which allow to validate xml
    try {
        InputStream xsd = new ClassPathResource(FacturxConstants.FACTUR_X_MINIMUM_XSD).getInputStream();
        StreamSource xsdSource = new StreamSource(xsd);
          SchemaFactory schemaFactory = SchemaFactory
                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = schemaFactory.newSchema(xsdSource);
        Validator validator = schema.newValidator();
        validator.validate(source);
        return true;
    } catch (SAXException | IOException e) {
        throw new FacturxException(e.getLocalizedMessage());
    }
    ...
}

Which loads the schema using an inputstream.

答案2

得分: 0

感谢M. Deinum,我能够找到一个解决方案。我必须确实使用StreamSource。这并没有解决以下问题:

src-resolve: 无法解析名称'ram:ExchangedDocumentContextType'为'type definition'组件。

由于我使用了多个xsd文件,我实现了一种使用PathMatchingResourcePatternResolver(来自spring)来检索源列表的方法。

private static Source[] buildSources(String fxGuideLine, String pattern) throws SAXException, IOException {
    List<Source> sources = new ArrayList<>();
    PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = patternResolver.getResources(pattern);

    for (Resource resource : resources) {
        StreamSource dtd = new StreamSource(resource.getInputStream());
        dtd.setSystemId(resource.getURI().toString());
        sources add(dtd);
    }
    return sources.toArray(new Source[sources.size()]);
}
英文:

Thanks to M. Deinum, I was able to find out a solution. I had to use indeed StreamSource. This didn't solve the following issue:

src-resolve: Cannot resolve the name 'ram:ExchangedDocumentContextType' to a(n) 'type definition' component.

As I used several xsd files, I implemented a way to retrieve a list of sources using PathMatchingResourcePatternResolver (from spring)

private static Source[] buildSources(String fxGuideLine, String pattern) throws SAXException, IOException {
List&lt;Source&gt; sources = new ArrayList&lt;&gt;();
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources = patternResolver.getResources(pattern);
for (Resource resource : resources) {
StreamSource dtd = new StreamSource(resource.getInputStream());
dtd.setSystemId(resource.getURI().toString());
sources.add(dtd);
}
return sources.toArray(new Source[sources.size()]);
}

huangapple
  • 本文由 发表于 2023年2月8日 18:36:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75384520.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定