I have a web application that uses Apache Shiro. I'm upgrading from Java 8 to 11. That is the only change, but when I try to launch my server, it looks like shiro can't find the default ehcache.xml config. I get the following error:
[main] INFO org.apache.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization.
[main] ERROR org.apache.shiro.web.env.EnvironmentLoader - Shiro environment initialization failed
java.lang.NullPointerException: The url can not be null
at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:151)
at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:131)
at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:115)
at org.ehcache.integrations.shiro.EhcacheShiroManager.getConfiguration(EhcacheShiroManager.java:176)
at org.ehcache.integrations.shiro.EhcacheShiroManager.ensureCacheManager(EhcacheShiroManager.java:149)
at org.ehcache.integrations.shiro.EhcacheShiroManager.init(EhcacheShiroManager.java:205)
at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:45)
at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:40)
at org.apache.shiro.config.ReflectionBuilder$BeanConfigurationProcessor.execute(ReflectionBuilder.java:831)
at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:290)
at org.apache.shiro.config.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:181)
at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:139)
at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:107)
at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:98)
at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:47)
at org.apache.shiro.config.IniFactorySupport.createInstance(IniFactorySupport.java:150)
at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:47)
at org.apache.shiro.web.env.IniWebEnvironment.createWebSecurityManager(IniWebEnvironment.java:296)
at org.apache.shiro.web.env.IniWebEnvironment.configure(IniWebEnvironment.java:121)
at org.apache.shiro.web.env.IniWebEnvironment.init(IniWebEnvironment.java:73)
at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:45)
at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:40)
at org.apache.shiro.web.env.EnvironmentLoader.createEnvironment(EnvironmentLoader.java:313)
at org.apache.shiro.web.env.EnvironmentLoader.initEnvironment(EnvironmentLoader.java:139)
at org.apache.shiro.web.env.EnvironmentLoaderListener.contextInitialized(EnvironmentLoaderListener.java:58)
In my web.xml I have:
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
...which automatically picks up my shiro.ini config in my WEB-INF directory, which contains (among other things):
[main]
...
...
cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager
securityManager.cacheManager = $cacheManager
When I compile and run using java 8, there's no problems finding the ehcache config and the server starts up normally:
[main] INFO org.apache.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization.
[main] INFO org.ehcache.xml.XmlConfiguration - Loading Ehcache XML configuration from file:/path/to/my/app/lib/shiro-ehcache3-1.0.0.jar!/org/ehcache/integrations/shiro/ehcache.xml.
As I mentioned, the only change is that I'm compiling and running with java 11. All of the same jars are available to both builds, and those shiro specific jars are:
- shiro-all-1.12.0.jar
- shiro-ehcache3-1.0.0.jar
I've also tried adding cacheManager.cacheManagerConfigFile = /path/to/custom/configuration.xml to my shiro.ini as suggested by the docs here by extracting the default ehcache.xml config file from the ehcache jar, but no matter what path I use in the ini file, the server startup always fails with org.apache.shiro.ShiroException: java.net.MalformedURLException: no protocol: /path/to/my/app/ehcache.xml.
I've also tried setting the cacheManagerConfigFile path to the ehcache xml config programmatically in my application entry point, but I get a MalformedURLException for any string that I provide e.g. "/path/to/my/app/ehcache.xml", "file:///path/to..." or "classpath:ehcache.xml".
The default ehcache.xml config extraction was really just a workaround though (that I can't get working), so ideally I would like to understand and fix why shiro isn't finding the default config itself with java 11.
I've reproduced this problem with a minimal example by initialising the ini file programatically like below and putting the ini file into the root of the classpath:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.util.Factory;
public class Test {
public static void main(String[] args) {
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
}
}
The shiro.ini in this case only contains:
[main]
cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager
securityManager.cacheManager = $cacheManager
Java 8 is fine, Java 11 fails with the "URL can not be null" error. For the example to work, you'll also need:
- commons-beanutils
- commons-logging
- log4j
- slf4j
- ehcache
...as well as the 2 shiro jars I mentioned previously. The specific java 11 builds I've tried using that fail are Amazon Coretto (11.0.16-amzn) and Temeric (11.0.20-tem), and the java 8 builds that are working for me are 8.0.332-tem and 8.0.382-amzn.
I've also tried compiling and running with Java 17 (17.0.8-amzn), which fails with the same error.