I have a wildfly 10 (Java + Spring) project. I have a requirement to dynamically inject the datasource (mysql) config details to wildfly. But since wildfly depends on the standalone xml file at startup, and needs it before even the java beans are created, the only way I've found so far is to inject is by setting env vars (by running some other program/script to fetch the configs before wildfly starts). Is there any other better option?
Is it possible to do this through the same java application itself, ignoring the xml and set the right config? If yes, how?
DataSource object via JNDI
Externalize your JDBC connection details by using JNDI to access a naming/directory server to obtain an object implementing the DataSource interface.
With a DataSource object in hand, call getConnection to obtain a Connection.
See tutorial by Oracle, Connecting with DataSource Objects.
Related
i already setup oracle xadatasource in websphere, and i want get datasource by using spring context lookup jndi , exception happen when i start my app : WasjdbcDataSource incompatible with javax.sql.XADataSource.
how can i solve this?
In a Java EE application server, such as WebSphere Application Server, even though you configure the XA-capable javax.sql.XADataSource, the application (and Spring) should always expect to use it as javax.sql.DataSource. Look in the Spring configuration if there is a way to indicate the expected type of javax.sql.DataSource rather than javax.sql.XADataSource. The XADataSource API is intended only for the application server's own internal use in order to accomplish two-phase commit. The user always interacts with it as javax.sql.DataSource, and gains the ability to enlist multiple resources in a single global transaction.
I have a small API running on PCF using Spring JPA. Of course, within the code, I could use a JDBC connection running prepared statements to access a bound MySQL instance. Doing this requires a username and password, as per normal standards when connecting to a database via Java.
However, with Spring JPA, I don't have to do any of this. I simply bind the MySQL instance and can perform my queries using the JPA API.
For lack of a better question, what is this magic?
Cloudfoundry with Spring Cloud follows 12-factor app patterns through out.
For configuration also it uses the config pattern suggested by 12-factor app patterns.
According to this pattern we should be storing properties outside the code in the environment as environment variables. So that application bundle can be deployed to any environment once it's built without any modifications. Since it picks up configuration from the environment variables, different environments have to define same environment variables with the different values.
Whenever you add a service to your application using cf bind-service Cloudfoundry sets predefined environment variables related to that service in the virtual machine (or container or whatever it has).
You can check these environment variables using cf env app-name.(Command Refeference)
Sample output of cf env app-name
{
"VCAP_APPLICATION": {
"application_id": "fa05c1a9-0fc1-4fbd-bae1-139850dec7a3",
"application_name": "my-app",
"application_uris": [
"my-app.10.244.0.34.xip.io"
],
"application_version": "fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca",
"limits": {
"disk": 1024,
"fds": 16384,
"mem": 256
},
"name": "my-app",
"space_id": "06450c72-4669-4dc6-8096-45f9777db68a",
"space_name": "my-space",
"uris": [
"my-app.10.244.0.34.xip.io"
],
"users": null,
"version": "fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca"
}
Using the spring actuator endpoints you can inspect all environment variables using /env endpoint. It lists more properties than cf env.
When spring detects that
cloud profile is active (set by spring.profiles.active environment property, or spring.profile property in spring cloud)
Auto Configuration is enabled (enabled by #SpringBootApplication)
No in memory Datasource dependency is present on the classpath (though I assume it would give cloud datasource configuration preference, even if in memory dependency were present)
No data source has been explicitly configured
Spring creates the Datasource bean itself using environment variables if a datasource service (like Postgres) has been bound to application.
Below is the link for the environment properties that it uses for creating Datasource.
https://docs.cloudfoundry.org/buildpacks/java/spring-service-bindings.html
Here is a list of Datasource only properties.
cloud.services.<database-service-name>.connection.hostname
cloud.services.<database-service-name>.connection.name
cloud.services.<database-service-name>.connection.password
cloud.services.<database-service-name>.connection.port
cloud.services.<database-service-name>.connection.username
cloud.services.<database-service-name>.plan
cloud.services.<database-service-name>.type
database-service-name is defined in the Manifest.yml file in the env: block
In my experience if there's only one database service added to the application, there was no need to define the database service name in the environment variables section.
Note: By default spring would try to use the servlet container's poolable connection support, however most of the time we our self have to configure some properties that are only supported by connection pool providers like Apache DBCP. In these cases we have to create Datasource bean manually using environment properties (using System.getProperty() or spring Environment.getProperty()).
Would it be possible to set up a DataSource using Spring Cloud in which open JDBC connections could be injected into all of my Spring Boot applications?
Something kind of like a JNDI server lookup? If so, can someone provide some examples or a description on how to use this type of configuration?
You could use a Spring Cloud bootstrap configuration to create a DataSource. I don't see much value in doing it that way over a normal Spring Boot autoconfiguration though. Link: http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-developing-auto-configuration.
One solution I found out was to set all datasources info into the properties files which will supplied by Spring Cloud Config Server to applications clients. So the aplications clients which creates DataSources gets from remote properties those values.
I have one query regarding datasource configuration.
I had configured one data source in server. Where my JNDI name is "MyDS".
To acquire the data-source in JBoss environment i had used like "java:/MyDS" in persistence, spring even in Birt reports.
But when i am running same thing in Tomcat environment, then it is showing error that unable to get the data-source.
I had googled about tomcat datasource communication, where i had seen like "jdbc/MyDS"
So, my query is what is the difference between above two types of configurations? (java:/MyDS and jdbc/MyDS) and how can i use the common configuration for both the servers (tomcat6 and jboss 5.1.0.GA).
Please help me.
Would it be possible to programmaticly create a data source in jboss and still have a valid jndi entry for the entity manager to use?
Creating the data source is where I am lost, I hope I can use a MBean that runs on stat-up to handle this.
This would not be my preferred method, but the application I am working on has a global configuration file hosted on another server I am suppose to use for configuration.
update: In this instance I need to create a data source programticly or change the jdbc url of an exsiting datasource. I don't know the DB server url until runtime.
Rather than poking around in the guts of JBoss in order to do this, I suggest using a 3rd-party connection pool utility, such as Apache Commons DBCP. There are instructions on how to programmatically register a DBCP datasource on JNDI here.
The first two lines of the sample code should be unnecessary, just create the default InitialContext and then rebind the datasource reference into it as described.
Here's a post that describes how to create a jboss service archive (SAR) that you can put in your EAR that will deploy a data source when the EAR is deployed, and remove it when the EAR in undeployed.