Welcome back! In
part 1 we discussed the basic concepts of Spring Boot and how-to create a configuration setup that allows to leverage all the nifty features (one word:
livereloads) AND still support classic
WAR
deployments (as needed for SAP HANA Cloud Platform Tomcat 8 runtime.)
In this episode we'll look into the topic of connecting to a database. Simple as it sounds, it gets a bit tricky if one considers the various scenarios that need to be supported:
|
Stand-alone |
NEO (local) |
NEO (cloud) |
Cloud Foundry |
Package type: |
JAR |
WAR |
WAR |
JAR |
Datasource: |
manually defined |
provisioned via JNDI |
provisioned via JNDI |
auto-configuration |
Profiles: |
dev |
neo |
neo |
cf |
When running as stand-alone executable we need to manually define the properties to create a
JDBC
connection and instantiate a
Datasource
(see
Connection to a production database). The NEO runtimes
automagically provision a reference to the configured
Datasource
via
JNDI
(see
Retrieving Data Sources). Cloud Foundry makes it even simpler by using a concept known as auto-reconfiguration (see
Auto-Reconfiguration) that will wire your
DataSource
automatically in case there's only a single relational backing service bound to your app.
Stand-alone
Arguably the easiest way to achieve this is by using so-called
profiles and leverage profile-specific configurations. Let's have a look at the respective
application-dev.properties config file:
spring.profiles.active=dev
spring.datasource.url=jdbc:derby:memory:DemoDB;create=true
spring.datasource.username=demo
spring.datasource.password=demo
spring.datasource.driver-class-name=org.apache.derby.jdbc.EmbeddedDriver
Note: Admittedly, we could also have used the
DataSourceAutoConfiguration feature that would create this by default if only one embedded database is found in the classpath (see
Embedded Database Support), but for educational purposes we do take control of things, ok?
So, if we start the application using the 'dev' profile we'll end up with a temporary embedded/in-memory Derby database:
mvn spring-boot:run -Drun.profiles=dev
NEO
As stated above, the Tomcat 8 runtime of SAP HANA Cloud Platform provisions a reference to the underlying
Datasource
via
JNDI
. That works the same way regardless of running it locally or in the cloud. Hence, we just need to define a
Datasource
factory bean that creates a respective
Datasource
via the JNDI lookup (see
NeoConfig.java😞
@Configuration
@Profile({"neo"})
public class NeoConfig
{
@Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException
{
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource ds = dataSourceLookup.getDataSource("java:comp/env/jdbc/DefaultDB");
return ds;
}
}
NOTE: Please note that you need to specify the following JVM argument to make sure that Spring Boot runs in the 'neo' profile:
-Dspring.profiles.active=neo
.
Cloud Foundry
As stated above it's fairly simply to get the app to run on Cloud Foundry: all we need to ensure is that we bind a relational database backing service (e.g. Postgres) to the app. There are numerous ways to do this, but the most simple may be using a respective
manifest:
---
applications:
- name: springboot-${random-word}
memory: 512M
instances: 1
host: springboot
path: target/ROOT.jar
services:
- postgres
env:
SPRING_PROFILES_DEFAULT: cf
Conclusion, final words and Outlook
As demonstrated it's fairly easy to provide a
Datasource
for our app in such a way that it works in all scenarios using profiles. Still, we always need to indicate the profile to use, which does not really fly with the idea of (
cloud agnostic)
cloud-native apps, right?
So, in the next episode we'll incorporate
Spring Cloud Connectors... stay tuned!
Github repository:
https://github.com/SAP/cloud-spring-boot-sample