Accessing H2 Console While Running SpringBootTest - spring-boot

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.

Related

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

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.

SpringBootTest: how to use application-test.yaml and inherit missing values from application.yaml

I am trying to run an integration test using the annotations :
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles({ "test" }).
The problem I have is that the application loads by using the spring profile "test"
I have two config files:
application.yaml
application-test.yaml
application.yaml contains:
xyz:
list:
- class-name: com.any.prod.ClassName1
jndi-name: com/ws/ClassName1
- class-name: com.any.prod.ClassName2
jndi-name: com/ws/ClassName2
and the other file doesn't contain these values.
these valuer are used by a library that i use, and not directly by my application.
when I load the test with the "test" profile enabled the values from application.yaml are not picked up. If I add the same values to application-test.yaml they are picked up during the binding process.
These are the properties that are picked up:
xyz.list[0].class-name: com.any.prod.ClassName1 (loaded from application-test.yaml)
xyz.list[0].jndi-name: com/ws/ClassName1 (loaded from application-test.yaml)
xyz.list[1].class-name: com.any.prod.ClassName2 (loaded from application-test.yaml)
xyz.list[1].jndi-name: com/ws/ClassName2 (loaded from application-test.yaml)
xyz.list (loaded from application.yaml)
Unfortunately the last entry makes the validation of the properties fail.
Does anyone has in mind what can I do to solve this mystery?
At this point my understanding of how configuration yaml files are wrong (at least for the testing case - inheritance appears to be working just fine when we deploy our app)
You can achieve this by using the annotation #TestPropertySource .

Grails 3.3.1 and reloading beans with properties defined in resources.groovy

I have a class in src/main/groovy (ApiService.groovy). I am defining this as a spring bean in resources.groovy as I have multiple implementations.
There is a single property for this bean:
apiService(ApiService) {
server = '${server.address}'
}
Properties are defined in an external properties file.
All is fine when the application is first started.
However, if I change the file ApiService.groovy, the server property is null after ApiService gets reloaded.
I am using the following when starting the app with run-app:
-reloading -Ddisable.auto.recompile=false
I have also tried running Application.groovy, running the Gradle task bootRun and numerous other options for reloading but to no avail.
I have also tried using constructor based args instead, using resources.xml instead of resources.groovy but the same outcome.
Also, just for testing, I used the #Value annotation for the server property in the class itself and all was fine after a reload.
I'm running within Intellij but get the same behaviour running from the command line.
Maybe this shouldn't actually work but any suggestions/advice would be greatly appreciated to save me spending any more time on it.

Where does the default datasource url for h2 come from on Spring Boot?

I started a new spring-boot 1.5.3 project. Added some starters:
data-jpa
starter-web
data-rest
And then added
devtools
h2
I can see the datasource is automatically set to jdbc:h2:mem:testdb. Everything is working fine but just out of curiosity I tried to determine from where the jdbc:h2:mem:testdb value comes from. I searched spring-boot, spring-data, spring jdbc and devtools projects' source code but I was unable to find out. As far as I can tell, the value does not come as default suggestion from h2 either.
So where does this value exactly come from?
That would be coming from this class, which also contains the defaults for other flavours of in-mem DBs.
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/EmbeddedDatabaseConnection.java
H2(EmbeddedDatabaseType.H2, "org.h2.Driver", "jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"),
Which get's loaded via, the DataSourceAutoConfiguration if it meets the criteria,
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java
The default for the database name, testdb, comes from a default set in the Datasourceproperties,
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java
private String name = "testdb";

Can't find #SpringBootApplication from JUnit test file

I was following the guide here, https://spring.io/guides/gs/spring-boot/ - cloned the project, built with Gradle and tried to run...application ran fine. Then I changed some file structure as per my requirement and tried to run the unit test case given there, but getting this error -
Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
I only restructure the codes in there, and this is my current project structure -
/projectroot
- /src/main/java
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
Now trying to run test case from
/src/test/java/controller/MyControllerTest.java
I have gone through this Stack Overflow link and understood that if I put my test folder under /src/main/java/ it may work. But if I do that test file doesn't compile and it also doesn't seem the right way to put application code along with test code. I know I'm missing something very fundamental.
The way you setup your test (using the whole spring boot context), I believe MyControllerTest.java needs to be at most at the same level as Application.java. Also, I notice Application.java is using default package, you should move it into a package, so that all your beans are below your Spring Boot main class:
/projectroot
- /src/main/java/com/example/project/
-Application.java
-/controller
-MyController.java
-/util
-MyUtil.java
-/model
-MyModel.java
- /src/test/java/com/example/project/
-MyControllerTest.java
Spring's documentation
How Spring Boot's context is resolved from a test:
The search algorithm works up from the package that contains the test
until it finds a #SpringBootApplication or #SpringBootConfiguration
annotated class. As long as you’ve structure your code in a sensible
way your main configuration is usually found.
About using the default package with Spring Boot:
When a class doesn’t include a package declaration it is considered to
be in the “default package”. The use of the “default package” is
generally discouraged, and should be avoided. It can cause particular
problems for Spring Boot applications that use #ComponentScan,
#EntityScan or #SpringBootApplication annotations, since every class
from every jar, will be read.
We recommend that you follow Java’s recommended package naming conventions and use a reversed domain name (for example, com.example.project).

Resources