简体   繁体   中英

No unique service maching interface error in Spring Boot Cloud Foundry error

I am trying to follow this tutorial https://github.com/cf-platform-eng/spring-boot-cities/tree/master/cities-service to run my spring boot application in Cloud Foundry. I have local bosh-lite installation

My Spring Boot application connects to postgresql as database. I am trying to connect to the Postgresql instance running on my local (host machine )

My application works fine locally if deployed to a local tomcat. But when i deploy the app to bosh-lite it fails with the following error "No unique service maching interface error ". My code is excatly the same as what is mentioned in the tutorial except i am using Maven to build my code.

    2017-06-07T22:29:54.44+0530 [App/0] OUT Caused by: org.springframework.cloud.CloudException: No unique service matching interface javax.sql.DataSource found. Expected 1, found 0
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.springframework.cloud.Cloud.getSingletonServiceConnector(Cloud.java:149) ~[spring-cloud-core-1.2.3.RELEASE.jar!/:na]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.saurav.cf.casestudy.employee.db.DataSourceConfiguration.dataSource(DataSourceConfiguration.java:20) ~[classes/:na]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.saurav.cf.casestudy.employee.db.DataSourceConfiguration$$EnhancerBySpringCGLIB$$847aab5e.CGLIB$dataSource$0(<generated>) ~[classes/:na]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.saurav.cf.casestudy.employee.db.DataSourceConfiguration$$EnhancerBySpringCGLIB$$847aab5e$$FastClassBySpringCGLIB$$2ad81e2b.invoke(<generated>) ~[classes/:na]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) ~[spring-context-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at org.saurav.cf.casestudy.employee.db.DataSourceConfiguration$$EnhancerBySpringCGLIB$$847aab5e.dataSource(<generated>) ~[classes/:na]
2017-06-07T22:29:54.44+0530 [App/0] OUT     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]

My connection to postgres works fine. And the same app works fine if i don't use spring cloud connector and read the value normally from application.properties.

My pom.xml`(Has dependencies for spring boot cloud connector and postgrsql driver )

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.saurav.cf.casestudy</groupId>
    <artifactId>employeerest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>employeerest</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <!--  <start-class>org.saurav.cf.casestudy.employee.EmployeerestApplication</start-class> -->
    </properties>



    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-hateoas</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-cloud-connectors</artifactId>

</dependency>



        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


<dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
      </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

`

[UPDATE] as per Scott's answers below i had a look at the requirements for a UPS to be picked up cloud connector.Since mine is an user provided provided service so i cannot have tags and label. But i added the jdbc urls. Now my app is failing with the below error

 Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set

For this i have set "spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect" in my application.properties but still it does not work

I have also checked that my DB is running and db settings in my service instance is correct.

Below is my service instance content`

"VCAP_SERVICES": {
  "user-provided": [
   {
    "credentials": {
     "jdbcUrl": "jdbc:postgresql://10.0.2.2:5432/employee",
     "username": "postgres",
     "password": "admin",
     "postgresUri": "postgresql://10.0.2.2:5432/employee",
     "uri": "postgresql://10.0.2.2:5432/employee"
    },
    "label": "user-provided",
    "name": "postgresql-cf-service",
    "syslog_drain_url": "",
    "tags": [],
    "volume_mounts": []
   }
  ]
 }

` Best Regards, Saurav

If you include spring-boot-starter-cloud-connectors as a dependency, then Spring Cloud Connectors will attempt to create the java.sql.DataSource bean necessary to connect to the database. Connectors does this by looking for a service binding that has certain characteristics . The No unique service matching interface javax.sql.DataSource found message means that Connectors couldn't find a service binding of the appropriate type.

If you want to use Connectors as in that sample app then you will need to create a user-provided service instance with the details of the Postgres connection and bind that service instance to the app.

Alternatively, you could remove the spring-boot-starter-cloud-connectors dependency and instead configure the database connection using spring.datasource properties in application.yml .

These options are explained in more detail in a blog post .

Just to summarize the overall solution for other readers.

If you have a scenario where you want to have a spring boot application talk to a database (hosted in other machine) and then run the application from cloud foundry. Then follow some of the tips below.

  1. Once you deploy your Spring Boot application and want to use Spring Boot cloud connector make sure you have all the proper dependencies in your classpath (spring-boot-cloud-connector and jar.
  2. If you want to bind a service instance with the application .Make sure the credentials adhere to this specification http://cloud.spring.io/spring-cloud-connectors/spring-cloud-cloud-foundry-connector.html#_postgresql
  3. In the service instance parameters make sure you use the uri parameter not depend on the username and password to construct the uri
  4. Make sure your database instance is actually running and you have created application service groups to allow outbound communication from your cloud foundry app. https://docs.cloudfoundry.org/concepts/asg.html#viewing

Steps 3 and 4 were the mistakes i made. Once corrected the application works fine.

Best Regards, Saurav

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM