Why would Spring Boot/EhCache NOT use the specified configuration file? - spring

I'm trying to enable EhCache 3 caching inside a Spring Boot 2 application and as near as I can tell I've set this up correctly but caching is just...NOT working and I'm being given no information as to why.
I've added to my maven POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
I've added an #EnableCaching annotation.
I've specified the config, I'm using bootstrap.yml so:
spring:
cache:
jcache:
config: classpath:ehcache.xml
But just in case I also put the spring.cache.jcache.config version in a properties file.
I've written a basic src/main/resources/ehcache.xml file...
Finally, I've set a method as #Cacheable but it errors out when I call it with "Cannot find cache named..."
It literally doesn't matter one iota what I write in ehcache.xml. I can paste in Lorem Ipsum text instead of XML and have no errors or indication it even opened the file.
Spring Boot itself seems to have found the appropriate pre-requisites for JSR 107 autoconfiguration:
JCacheCacheConfiguration matched:
- #ConditionalOnClass found required classes 'javax.cache.Caching', 'org.springframework.cache.jcache.JCacheCacheManager' (OnClassCondition)
- Cache org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration automatic cache type (CacheCondition)
I've tried going back to EhCache 2, so I replaced org.ehcache with net.sf.ehcache, switched my YML to ehcache instead of jcache and removed javax.cache. This puts this into my auto-configuration report:
EhCacheCacheConfiguration matched:
- #ConditionalOnClass found required classes 'net.sf.ehcache.Cache', 'org.springframework.cache.ehcache.EhCacheCacheManager' (OnClassCondition)
- Cache org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration automatic cache type (CacheCondition)
- ResourceCondition (EhCache) found resource 'classpath:/ehcache.xml' (EhCacheCacheConfiguration.ConfigAvailableCondition)
But I still don't have any caches available to me. Why would Spring's autoconfiguration mechanism go so far as to mention that it found the EhCache 2 config file but not actually configure anything? Is there some other auto-configuration class I need to also look up in the report like a GenericCache, CacheConfiguration, something else?
What I can't see is any indication that it tried to do anything to start up a caching subsystem, read my configs, did anything.
As convenient as autoconfiguration is, when it doesn't feel like doing the thing it frustratingly tells me absolutely nothing about why it's deciding to blow me off so I could really use some help figuring out how to tease those details out of the thing.
Did I miss something? What can I debug and where can I look to figure out why it's ignoring the XML configuration I'm trying to tell it about? I tried adding some breakpoints to Spring CacheProperties around the jcache settings but it didn't hit them when I attached the debugger.

Related

Cannot find template location :( please add some templates, check your Thymeleaf configuration, or set spring.thymeleaf.check-template-location=false)

I created a spring boot application and while running it I am getting this warning.
2022-10-27 00:35:12.520 WARN 11512 --- [ restartedMain] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates, check your Thymeleaf configuration, or set spring.thymeleaf.check-template-location=false)
Here, you can see my application.properties file
spring.datasource.url=jdbc:mysql://localhost:3306/springbootblogapp?
createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true
spring.jpa.open-in-view=false
Even though there were some related questions here, the provided answers for them are not working for me, because the warnings mentioned there were a little bit deviated from the warning which I got.
Please help me.
My initial comment, transferred to an answer:
Here is the text of the warning message shown in your question:
2022-10-27 00:35:12.520 WARN 11512 --- [ restartedMain] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates, check your Thymeleaf configuration, or set spring.thymeleaf.check-template-location=false)
Did you try what the warning message suggests - for example, by adding:
spring.thymeleaf.check-template-location=false
to your application's config? Or by creating the directory templates mentioned in the warning message (and adding a template there)? By default this directory is expected to be created in the resources location, so that it is on the classpath of the application at runtime.
Update based on your follow-up comment:
Why do you get this warning?
When you create a Spring Boot application, you can choose various additional dependencies (for example by using Spring Initializr).
One such additional dependency is Thymeleaf.
For Maven (assuming you are using Maven), that is the following artifact in your POM:
<artifactId>spring-boot-starter-thymeleaf</artifactId>
There is no point in choosing this option if you don't set up the basic location where you are going to store your Thymeleaf templates.
If you choose to configure the option:
spring.thymeleaf.check-template-location=false
then you are telling Spring not to bother checking if there is a valid configured location for your Thymeleaf templates.
So, even if there is not a valid configured location, you won't see that warning.
If you decide you do want to use Thymeleaf after all, you will need to fix this, by providing that default folder templates on the runtime classpath - or by specifying a custom location via your properties file.
You may see similar warnings (or even errors) with other Spring Boot dependencies you have chosen. For example, if you choose to include the JDBC API, but do not configure a valid data source, then I believe that causes an error (if I recall).

Unable to access /actuator endpoints

I've got a small project running Spring Boot and Spring Cloud Streams with version Greenwich.SR4.
So far I've tried to include the following dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
</dependency>
Wanting to have a /check/health endpoint which basically returns a code 200.
I've modified the config accordingly so that I don't have useless health configs within.
management.endpoints.web.base-path=/check
management.endpoint.health.enabled=true
management.health.solr.enabled=false
management.health.elasticsearch.enabled=false
However, whenever I try to run localhost:8080/check/health a 404 is prompted. What could be happening?
Also mentioning that I've tried including my own #RestController but same behavior happens.
The URL for the health check should be http://localhost:8080/check/health, not /check/status.
It is depends on the Spring-Boot version. After version 2.0 the path name is manage, so your right url is: http://localhost:8080/check/health
You can also change that with (.yml version):
management:
context-path: /manage
security:
enabled: false

Accessing H2 Console While Running SpringBootTest

If I'm running a test with #SpringBootTest is there any way to access the H2 console? I have a test that accesses an H2 database (successfully), but if I want to inspect the database myself, how can I?
I started by running the test with a webEnvironment=DEFINED_PORT and http://localhost:8080/ responds to HTTP, but there's nothing http://localhost:8080/h2-console/ still responds with 404.
I tried turning on the console explicitly by adding values to application.properties:
spring.h2.console.enabled=true
spring.h2.console.path=/h2
That seemed to have no effect. Still 404s at /h2-console and /h2.
The H2 Console seems to come in through Auto-Configuration, so I turned on the auto configuration report using -Ddebug, and I can see that despite the enabled flag being on in application.properties, it's seen as being off:
H2ConsoleAutoConfiguration:
Did not match:
- #ConditionalOnProperty (spring.h2.console.enabled=true) did not find property 'enabled' (OnPropertyCondition)
Matched:
- #ConditionalOnClass found required class 'org.h2.server.web.WebServlet'; #ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found WebApplicationContext (OnWebApplicationCondition)
Seems like some mechanism is overriding the value or ignoring the value from application.properties while running the test.
Does Spring Boot Test not start up the console? Is there any way to convince it to do so?
Ok, I was able to get it to appear with the following annotation (in Kotlin):
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = arrayOf("spring.h2.console.enabled=true"))
Even with this, the console is still at /h2-console, so it's clearly ignoring the console path as well. I could presumably control that by adding another property.

Spring Infinispan - Setting expiry time for cached objects

We are currently using below. It's quite old, but cannot upgrade to higher version now
`
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-spring3</artifactId>
<version>6.4.0.Final-redhat-4</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-client-hotrod</artifactId>
<version>6.4.0.Final-redhat-4</version>
</dependency>
`
We have modified our code from something with a direct JDG implementation (as shown below) to SpringRemoteCacheManager in an XML based configuration file and are using Spring cache:advice to define cacheable, cahce-put, cache-evict methods.
See Current code where we have control to add expiry time. We want to do similar thing with Spring - Infinispan as well. With Spring - Infinispan we do not write any application code that puts/gets objects in/from cache as its handled by Spring annotations (#Cacheable / #CachePut)
Appreciate if anyone can provide any pointers
RemoteCache<Object, Object> cache = jdgRemoteCacheManager.getCache(cacheName);
cache.put(keyName, object, 15, TimeUnit.MINUTES);
Unfortunately Spring Cache support doesn't provide such methods (see the Javadocs). So it seems the only way is to use the RemoteCache API provided by Infinispan.
Perhaps you could implement your own #Cacheable annotation and implement all the functionality you need. But that's a Spring question really...

WildFly 10, JCache - method caching

i have simple application using Spring Boot. I wanted allow method caching with JSR107 - JCache. So with help of tutorial i put together this code :
#CacheResult(cacheName = "testpoc")
public Country getCountry(Integer id){
System.out.println("---> Loading country with code '" + id + "'");
return new Country(id, "X", "Title");
}
with this POM file
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
...
(dependency 'spring-boot-starter-web' is there for simple REST service which call getCountry method)
Everything works like documentations says - method is invoked only once.
Now i wanted to try it on WildFly 10 application server
I have modified pom file :
excluded tomcat
exluded spring-boot-starter-cache
added infinispan-jcache (because i want to use cache configured / managed by wildfly in standalone/domain.xml)
Check pom file here on pastebin.
Problem is, that i am receiving following error :
Cannot find cache named 'java:jboss/infinispan/app-cache'
(i have tried to use both JNDI assigned and name to infinispan cache configured in wildfly).
Following code created Cache object (so i can used it) :
CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
Cache<String, String> cache = cacheManager.createCache("testpoc", new MutableConfiguration<String, String>());
Question :
It is possible to use JCache method caching on WildFly 10 using Infinispan managed by WildFly ?
Or Infinispan should be used for method caching like JCache, hence JCache has "more functionality" than Infinispan.
Thank you very much
PS :It is not problem for me to put whole code on github and post link - it is few lines of code ...
There are a couple of problems with your approach so let me go through them in steps.
At first you need to use proper Infinispan setup. Infinispan bits shipped with WF should be considered as internal or private. In order to use Infinispan in your app properly - either add org.infinispan:infinispan-embedded to your deployment or install Infinispan Wildfly modules. You can find installation guide here (it's a bit outdated but still, the procedure is exactly the same - unpack modules into WF and use Dependencies MANIFEST.MF entry).
Once you have successfully installed Infinispan (or added it to your app), you need to consider whether you want to use Spring Cache or JCache. If you're only interested in using annotations - I would recommend the former since it's much easier to setup (all you need to do is to add #EnableCaching to one of your configurations). Finally with Spring Cache you will create an Infinispan CacheManager bean. An example can be found here.
Final note - if you still need to use JCache - use this manual to setup Caching Provider.

Resources