Spring Boot + Spring Data on GAE with CloudSql - Database Connection - spring

I'm unable to deploy a Spring Boot + Spring Data application to Google App Engine and have the app connect to a Google CloudSql (MySQL) database.
The GAE application and CloudSql instance are in the same project.
I'm able to run the entire app and connect to CloudSql from localhost with no issue.
Spring Boot without a database connection works correctly without error on GAE. Adding Spring Data throws a "com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure" error.
In the pom.xml I have included:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>com.google.cloud.sql</groupId>
<artifactId>mysql-socket-factory</artifactId>
<version>1.0.2</version>
</dependency>
Also, I've tried to use only the mysql dependency:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
In my research, I have not found any good examples or related issues to Spring Boot + Spring Data + GAE + CloudSql.
What are the correct settings for connecting to a CloudSql DB in the application.properties file? I've tried the following, but all threw various errors:
spring.jpa.hibernate.ddl-auto:none
# tried with GoogleDriver and without:
# spring.datasource.driver-class-name=com.mysql.jdbc.GoogleDriver
# urls configs attempted:
# spring.datasource.url=jdbc:mysql://google/**db-name**?cloudSqlInstance=***instance-name***b&socketFactory=com.google.cloud.sql.mysql.SocketFactory
# spring.datasource.url=jdbc:mysql://***instance-name***/**db-name**?user=root
# spring.datasource.url=jdbc:mysql://localhost:3306/**db-name**
spring.datasource.url=jdbc:mysql://127.0.0.1:3306:3306/**db-name**
# spring.datasource.url=jdbc:mysql://***mysql ip address***:3306/**db-name**
spring.datasource.username=***user***
spring.datasource.password=***password***

I had the same issue, below properties in Spring boot application.properties worked for me.
database=mysql
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://google/{db-schema}?socketFactory=com.google.cloud.sql.mysql.SocketFactory&cloudSqlInstance={Cloud-sql-Instance-Name}
spring.datasource.username=root
spring.datasource.password=password

You have to follow following steps :
1) Enable Cloud SQL API by going to following link:
https://console.cloud.google.com/flows/enableapi?apiid=sqladmin&redirect=https:%2F%2Fconsole.cloud.google.com
2) Download service account JSON key file from https://console.cloud.google.com/apis/credentials/serviceaccountkey
3) Set this filepath as environment variable with key GOOGLE_APPLICATION_CREDENTIALS.
on Windows OS open command prompt and run command: set GOOGLE_APPLICATION_CREDENTIALS=[File path]
on Linux OS on console run command : export GOOGLE_APPLICATION_CREDENTIALS=[File path]
4) Add following dependencies in pom.xml :
`<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<dependency>
<groupId>com.google.cloud.sql</groupId>
<artifactId>mysql-socket-factory</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.23.0</version>
</dependency>
`
5) Use following properties in application.properties file :
spring.datasource.url=jdbc:mysql://google/[Database-Name]?cloudSqlInstance=[instance-Connection-Name]&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false
spring.datasource.username=[Database-Username]
spring.datasource.password=[Database-Password]
Hope this helps.

Related

How to externalize spring.cloud.vault.* properties to a spring cloud config server

I am using spring boot 2.7.8
I am following this https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#client-side-usage and https://docs.spring.io/spring-cloud-config/docs/current/reference/html/#_client_side_usage
I have a spring cloud config server too which hosts the externalized properties for my application. So my pom.xml has below
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-vault-config</artifactId>
</dependency>
I can point to the external spring cloud config server using the below in my properties file
spring.config.import=optional:configserver:http://myconfigserver.com
But as per https://docs.spring.io/spring-cloud-vault/docs/current/reference/html/#client-side-usage, I still have to define spring.cloud.vault.* in my application properties? How can I move spring.cloud.vault.* properties into my spring cloud config server so that all my properties are externalized. I want to avoid having some properties within the application and some externalized.
Please help to clarify if I am misunderstanding this

Azure AppConfiguration with Spring Boot 2.5.x

Question
How to integrate an Azure AppConfiguration with SpringBoot 2.5.x or higher?
Info
Im trying to use an Azure AppConfiguration resource with a Spring Boot 2.5.4 project. Unfortunately I cant get it to read a setting from the AppConfiguration or even connect to it as far as I can tell.
The project is newly created with the Spring Initializr where I only added
Spring Boot Starter Web
Spring Boot Starter Security
Spring Boot Starter WebSocket
Afterwards I tried following the Microsoft Quickstart documentation with no success. The documentation mentions that its using Spring 2.4.x so I assume some changes broke it.
I also tried to identify the issue by looking through some Azure Spring Boot Code Samples.
All the examples so far use the bootstrap.properties file which I learned during my search so far is deprecated. Moving the settings to the application.yml or enabling use-legacy-processing: true did not work either. Any ideas?
pom.xml
...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-cloud-appconfiguration-config</artifactId>
<version>2.0.0</version>
</dependency>
...
application.yml
spring:
config:
use-legacy-processing: true
profiles:
active: "develop"
application:
name: "MySampleService"
cloud:
azure:
appconfiguration:
stores:
- connection-string: "SomeAzureAppConfigurationResourceConnectionString"
label: ${spring.profiles.active}
#mysampleservice:
# message: "this is a message from file"
AppConfiguration Resource
Im not entirely sure about the format for the setting name. I tried to build the format based on this documentation.
The configuration classes should be fine since commenting in the mysampleservice causes the value of message beeing used.
Any hints are appreciated!
Some more info to elaborate on the accepted answer
The documentation linked in the answer refers to two different packages. The one linked right at the start in the maven repository is spring-cloud-azure-appconfiguration-config while the one used further down is azure-spring-cloud-appconfiguration-config. The second one works with the bootstrap.properties file.
Working pom.xml and bootstrap.properties:
...
<dependencies>
<!-- Dependency to load configuration from azure app configuration resource. Note that additional settings are required in bootstrap.properties
Documentation of settings: https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/appconfiguration/azure-spring-cloud-starter-appconfiguration-config
-->
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>azure-spring-cloud-appconfiguration-config-web</artifactId>
<version>2.1.0</version>
</dependency>
...
# Use this to enable or disable the cloud config, disabling it results in application.yaml beeing used.
spring.cloud.azure.appconfiguration.enabled=true
# Connection string to azure app configuration resource
spring.cloud.azure.appconfiguration.stores[0].connection-string= Endpoint=https://myofficeconfiguration.azconfig.io;Id=zUcT-l9-s0:PFYfW7WM0/Pz7WZOnH3v;Secret=JTB9myJqGekDAJ5m8Z1vjmkJZrPd88JbOEE3EqoqJYs=
# Configured filters for settings in the previous defined app configuration resource
spring.cloud.azure.appconfiguration.stores[0].selects[0].key-filter = /mysampleservice/
spring.cloud.azure.appconfiguration.stores[0].selects[0].label-filter = Sample
spring.cloud.azure.appconfiguration.stores[0].selects[1].key-filter = /notificationservice/
spring.cloud.azure.appconfiguration.stores[0].selects[1].label-filter = Sample2
bootstrap.yml/bootstrap.properties can still be used, they are no longer part of the base Spring packages.
Also, you want to use this doc for 2.0.0 and newer https://github.com/Azure/azure-sdk-for-java/tree/main/sdk/appconfiguration/azure-spring-cloud-starter-appconfiguration-config.

h2 localhost url different from testdb

I am using below spring boot config:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
When my spring app comes up, I see the following:
H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:304a69fe-27f6-4271-a5c3-015f06910885'
However if i set the below in property file, i do see testdb being connected:
spring.datasource.url=jdbc:h2:mem:testdb
Can someone please let me know why do i need to explicitly set the url in property file? I had created another spring boot app recently with the exact same config but with spring boot version 2.2.4.RELEASE where h2 connected by default to testdb without setting it in property file.
Thanks!
Reconsider default for spring.datasource.generate-unique-name as the current one makes test cases brittle #16747
commit
This change ensures that each test in a test suite that shares an
application context gets a unique embedded database, to prevent
inconsistent embedded database state between tests.
You can revert to the previous behavior by following setting:
spring.datasource.generate-unique-name=false
Found out that with the latest versions of Spring Boot (2.3+), the H2 database name is randomly generated each time you restart the server. Similar post: springboot 2.3.0 while connecting to h2 database
Update:
As you are using h2 console, you probably have a property called
spring.h2.console.enabled=true
If so then Spring's H2ConsoleAutoConfiguration class gets enabled and it does the auto-configuration as given below. (Check here )
If you are using any of this annotations - #DataJdbcTest, #DataJpaTest and #JdbcTest in your test, then Spring through #AutoConfigureTestDatabase will call TestDatabaseAutoConfiguration, which in turn, by default, will configure an in-memory embedded database instance with an auto generated unique name.
If you want to solve the problem for single test case, please use:
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
If you want this to apply for all test cases, then please have this property in application.yaml
spring:
test:
database:
replace: none

Cannot include Prometheus metrics in spring boot 2 (version 2.0.0.M7)

Cannot include Prometheus metrics in spring boot 2 (version 2.0.0.M7) project.
According micrometer docs added spring-boot-starter-actuator dependency and in application.yaml added management.endpoints.web.expose: prometheus but when calling /actuator/prometheus get
{
"timestamp": 1518159066052,
"path": "/actuator/prometheus",
"message": "Response status 404 with reason \"No matching handler\"",
"status": 404,
"error": "Not Found"
}
Tell me please why I wasn't getting prometheus metrics?
I had trouble initiating micrometer with Springboot 2. x.
These changes in my project helped me to expose the metrics atactuator/prometheus endpoint
These are the changes in my application.properties file
management.endpoints.web.exposure.include=*
management.endpoint.metrics.enabled=true
My build.gradle file included
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('io.micrometer:micrometer-registry-prometheus')
Edit: Since I gave this answer a lot has changed. It was valid for 2.0.0.RC1. Please read the documentation https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-metrics.html
If above solution doesn't work for someone try this:
I had the same issue with Spring Boot 2.0.0.RC1, spring-boot-starter-web and of course spring-boot-starter-actuator.
My application.properties file read:
management.endpoints.web.expose=prometheus,metrics,info,health
In my pom file I had additionally:
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>0.12.0.RELEASE</version>
</dependency>
Prometheus metrics under /actuator/prometheus where only shown after I had switched to the newest version of micrometer-registry-prometheus:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.0.0-rc.9</version>
</dependency>
Did you add micrometer-registry-prometheus to your dependecies?
Micrometer has a pluggable architecture where you need to define (by plugging dependencies) what monitoring system you'd like to work with. (You can even add multiple, not just one.)
Btw, you should be switching to Spring Boot 2.0.0.RC1. That's the current one as of this writing.
Recap:
pom.xml
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>
... ... ...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
application.properties.yml (aka. application.yml)
management.endpoints.web.exposure.include=health,info,prometheus
management.endpoint.metrics.enabled=true
management.endpoint.prometheus.enabled=true
management.endpoint.health.show-details=always
management.endpoint.health.show-components=always
management.endpoint.health.probes.enabled=true
management.metrics.tags.application=TheApplicationName
After applying all the above, health & info endpoints were displayed in the http://localhost:8080/actuator -list, but not the prometheus endpoint.
Of course, rerun the Maven lifecycle - still failing prometheus to be displayed ...
Finally my issue disappeared after invalidate caches and restart of my IntelliJ IDE

Web Application using JavaCV and deployed on SAP HANA Cloud Platform error

I'm currently working on a face recognition web application using JavaCV. I send snapshots of a live webcam stream on a client's browser over websockets and the face recognition system does all the rest on the server side. However, I receive the following error when deploying my application on HCP.
no jniopencv_core in java.library.path
I have added all the jar files related to javacv/javacpp in my project lib folder and
this is my pom.xml
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.0.0-1.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.1</version>
</dependency>
Any ideas? Thanks in advance.
For some reason, Maven isn't picking up the platform dependencies properly. Add something like the following to fix that error:
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.0.0-1.1</version>
<classifier>linux-x86_64</version>
</dependency>

Resources