Using spring-boot 2.2.4, java 8, Windows 10

I have the following code :

@EnableWs
@Configuration
@SpringBootApplication
public class DemoApplication {

    public static void main(final String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public CryptoFactoryBean cryptoFactoryBean() throws IOException {
        final CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
        cryptoFactoryBean.setKeyStoreLocation(new FileSystemResource("C:\\test\\keystore.p12"));
        cryptoFactoryBean.setKeyStorePassword("private");
        cryptoFactoryBean.setKeyStoreType("PKCS12");

        return cryptoFactoryBean;
    }

}

Works fine when run with mvn spring-boot:run:

2020-02-07 11:14:51.334 DEBUG 3708 --- [           main] org.apache.wss4j.common.util.Loader      : Trying to find [C:\test\keystore.p12] using sun.misc.Launcher$AppClassLoader@73d16e93 class loader.
2020-02-07 11:14:51.335 DEBUG 3708 --- [           main] org.apache.wss4j.common.util.Loader      : Trying to find [C:\test\keystore.p12] using sun.misc.Launcher$AppClassLoader@73d16e93 class loader.
2020-02-07 11:14:51.337 DEBUG 3708 --- [           main] org.apache.wss4j.common.util.Loader      : Trying to find [C:\test\keystore.p12] using ClassLoader.getSystemResource().
2020-02-07 11:14:51.655 DEBUG 3708 --- [           main] org.apache.wss4j.common.crypto.Merlin    : The KeyStore C:\test\keystore.p12 of type PKCS12 has been loaded
2020-02-07 11:14:51.779  INFO 3708 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-02-07 11:14:51.943  INFO 3708 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-02-07 11:14:51.947  INFO 3708 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 2.627 seconds (JVM running for 3.298)

However when I package the jar and try to run it (java -jar \<myjar>.jar), the file (C:\test\keystore.p12) is not found :

2020-02-07 11:21:06.738 DEBUG 12128 --- [           main] org.apache.wss4j.common.util.Loader      : Trying to find [C:\test\keystore.p12] using org.springframework.boot.loader.LaunchedURLClassLoader@31221be2 class loader.
2020-02-07 11:21:06.745  WARN 12128 --- [           main] org.apache.wss4j.common.util.Loader      : Caught Exception while in Loader.getResource. This may be innocuous.

java.lang.IllegalArgumentException: name
        at sun.misc.URLClassPath$Loader.findResource(URLClassPath.java:693) ~[na:1.8.0_131]
        at sun.misc.URLClassPath.findResource(URLClassPath.java:215) ~[na:1.8.0_131]
        at java.net.URLClassLoader$2.run(URLClassLoader.java:569) ~[na:1.8.0_131]
        at java.net.URLClassLoader$2.run(URLClassLoader.java:567) ~[na:1.8.0_131]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_131]
        at java.net.URLClassLoader.findResource(URLClassLoader.java:566) ~[na:1.8.0_131]
        at org.springframework.boot.loader.LaunchedURLClassLoader.findResource(LaunchedURLClassLoader.java:58) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at java.lang.ClassLoader.getResource(ClassLoader.java:1096) ~[na:1.8.0_131]
        at org.apache.wss4j.common.util.Loader.getResource(Loader.java:165) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.util.Loader.loadInputStream(Loader.java:59) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.crypto.Merlin.loadInputStream(Merlin.java:348) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.crypto.Merlin.loadProperties(Merlin.java:218) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.crypto.Merlin.<init>(Merlin.java:156) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.crypto.CryptoFactory.getInstance(CryptoFactory.java:119) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
        at org.apache.wss4j.common.crypto.CryptoFactory.getInstance(CryptoFactory.java:78) [wss4j-ws-security-common-2.2.3.jar!/:2.2.3]
...

I'm guessing (?) it has something to do with LaunchedURLClassLoader.

This is my pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-security</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

demo.zip

Comment From: snicoll

This is similar to #19098. I don't see how it could be related to LaunchedURLClassLoader given that it delegates to the standard URLClassLoader.

Going forward, please share a link to a zip or a github repo as code in text is not very useful. To reproduce, we'll have to copy/paste all that in a project anyway.

Comment From: snicoll

I've copy/pasted the above on MacOS and can't reproduce the issue. I can give that a try on Windows later.

Comment From: Rommz

my bad, forgot to attach the test project. I've added it to my first post

Comment From: snicoll

Thanks. I can reproduce the issue on Windows.

Comment From: makaxel

Hello. I can confirm the issue. jar-file on windows - spring-boot 2.3.0 (2.2.7), java 8 and 11, Windows 10 - exception the same jar-file on linux - spring-boot 2.3.0 (2.2.7), java 11, oracle linux 7.7 - working OK slightly modified jar-file (pom parent and dependencies) - spring boot 1.3.3, java 8, Windows 10 - working OK

Maybe it will help. Sources are at https://github.com/makaxel/test-cryptoFileResourse and https://github.com/makaxel/test-cryptoFileResourseOld

Comment From: elvus

Hi i have the same error, the project is https://github.com/elvus/apiprinter I try this https://stackoverflow.com/questions/51203893/java-lang-illegalargumentexception-name but doesn't works. Sometimes it works and sometimes it doesn't. The error occurs only after compiling Error

Comment From: mightybeaker

I have had the same problem on: :: Spring Boot :: (v2.2.1.RELEASE) Windows 10 openjdk version "11.0.2" 2019-01-15

I have an @Configuration bean defining my Wss4jSecurityInterceptor. The WSS securement keystore location Resource is injected via properties:

    @Value("${wss.securement.ks.url}")
    private Resource securementKeyStoreLocation;

If I set the property to a classpath resource it works fine: wss.securement.ks.url=classpath:ws-client.jks If I override this in an exernal properties file pointing to an external keystore location I hit the problem: wss.securement.ks.url=file:///TEST/certs/ws-client.jks

I tried the following override to workaround the issue and it seems to work quite well until the underlying bug is fixed:

    @Bean
    public CryptoFactoryBean securementSignatureCrypto() throws IOException
    {
        CryptoFactoryBean securementSigCrypto = new CryptoFactoryBean()
            {
            @Override
            public void setKeyStoreLocation(Resource location) throws IOException
            {
                String path = null;
                try 
                {
                    path = location.getFile().getPath().replace("\\", "/");
                }
                catch (IOException ex) 
                {
                    if (location instanceof ClassPathResource) {
                        ClassPathResource classPathResource = (ClassPathResource) location;
                        path = classPathResource.getPath();
                    }
                    else {
                        throw ex;
                    }
                }
                Properties keyStoreLocations = new Properties();
                keyStoreLocations.setProperty("org.apache.ws.security.crypto.merlin.file", path);
                setConfiguration(keyStoreLocations);
            }};
        securementSigCrypto.setKeyStoreType(KEYSTORE_TYPE);
        securementSigCrypto.setKeyStoreLocation(securementKeyStoreLocation);
        securementSigCrypto.setKeyStorePassword(securementKeyStorePassword);
        return securementSigCrypto;
    }

So I had to replace the windows style back slashes with linux style forward slashes and it started working! As per the line above: path = location.getFile().getPath().replace("\\", "/");

Comment From: wilkinsona

Thanks for the sample and for your patience, @Rommz. Unfortunately, this is a bug in WSS4J's Loader so fixing it is out of our control. It is standard behaviour for the JVM's URLClassLoader to throw an IllegalArgumentException when getResource(String) is called with a name that cannot be turned into a URL and that's what is happening when you run your application is a jar file.

The early parts of Loader's getResource method handle exceptions from getResource(String) but the latter parts do not. I believe it needs to be updated to consistently handle exceptions from getResource(String) and then move on to the next candidate.

Comment From: wilkinsona

@makaxel This worked with Spring Boot 1.3.x as there was a workaround in our class loader. It was removed as we want its behaviour to align as closely as possible with a standard URLClassLoader. Please see https://github.com/spring-projects/spring-boot/issues/5650#issuecomment-208253864 and subsequent comments for further details.