No suitable ServiceConnectorCreator found trying to connect to RabbitMQ


Jason Brown
 

I'm trying to connect to RabbitMQ from our Pivotal CloudFoundry environment and I can't get it to work. The only artifact I don't have in my pom is org.cloudfoundry:auto-reconfiguration:1.7.0.RELEASE (or whatever version is current). The error I get in logs is:
2015-12-02T10:12:58.19-0700 [App/0] OUT Caused by: org.springframework.cloud.CloudException: No suitable ServiceConnectorCreator found: service id=JasonMCFTest-rabbit, service info type=org.springframework.cloud.service.common.AmqpServiceInfo, connector type=class com.rabbitmq.client.ConnectionFactory


The following classes are my config class and a simple component that tries to autowire my rabbit bean. I'm also pretty new to Spring, so feel free to bash that too.
<code>
package com.jasbro.mcftest;

import org.springframework.cloud.Cloud;
import org.springframework.cloud.CloudFactory;
import org.springframework.cloud.config.java.AbstractCloudConfig;
import org.springframework.cloud.service.common.AmqpServiceInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.rabbitmq.client.ConnectionFactory;

@Configuration
public class PivotalConfig extends AbstractCloudConfig{
@Bean
public ConnectionFactory rabbitConnectionFactory(){
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
AmqpServiceInfo serviceInfo = (AmqpServiceInfo) cloud.getServiceInfo("JasonMCFTest-rabbit");
String serviceId = serviceInfo.getId();
return cloud.getServiceConnector(serviceId, ConnectionFactory.class, null);
}
}



package com.jasbro.mcftest.scheduled;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.ConnectionFactory;

@Component
public class FilePoller {
@Autowired
private ConnectionFactory rabbitConnectionFactory;
...
}
</code>

And here is the service listing showing (I think) that rabbit is set up and bound to my app.
C:\src\main\JasonMCFTest>cf s
Getting services in org crt / space dev as jason.c.brown...
OK

name service plan bound apps last operation
JasonMCFTest-rabbit p-rabbitmq standard JasonMCFTest create succeeded


Lastly, the list of dependencies from my pom (some of these are probably not needed, but I don't know which):
junit
spring-webmvc
javax.servlet-api
amqp-client
spring-cloud-cloudfoundry-connector
spring-cloud-spring-service-connector
spring-cloud-services-cloudfoundry-connector
spring-boot-autoconfigure
spring-boot-starter-amqp


Scott Frederick <scottyfred@...>
 

It looks like the main problem is the type of connection bean you are
expecting Spring Cloud Connectors to create. In the PivotalConfig class,
you have this:

import com.rabbitmq.client.ConnectionFactory;

@Configuration
public class PivotalConfig extends AbstractCloudConfig{
@Bean
public ConnectionFactory rabbitConnectionFactory(){

return cloud.getServiceConnector(serviceId,
ConnectionFactory.class, null);
}
}


The spring-cloud-spring-service-connector module of Spring Cloud Connectors
expects to work with Spring types. In the the case of a RabbitMQ
connection, it will create a
org.springframework.amqp.rabbit.connection.ConnectionFactory, not a
com.rabbitmq.client.ConnectionFactory. If you change this import, and the
matching one in FilePoller, you should get past this error.

If you are extending AbstractCloudConfig in your @Configuration class, you
can write much less code to get the same result. The PivotalConfig class
can look like this:

@Configuration
public class PivotalConfig extends AbstractCloudConfig {
@Bean
public ConnectionFactory rabbitConnectionFactory(){
return connectionFactory.rabbitConnectionFactory();
}
}


The name of the service instance isn’t required if you only have one
service of that type bound to your application. If you had more than one
RabbitMQ service bound to the app then you can do return connectionFactory.
rabbitConnectionFactory(“JasonMCFTest-rabbit”) instead.

Scott

On Wed, Dec 2, 2015 at 11:57 AM, Jason Brown <jasbro(a)gmail.com> wrote:

I'm trying to connect to RabbitMQ from our Pivotal CloudFoundry
environment and I can't get it to work. The only artifact I don't have in
my pom is org.cloudfoundry:auto-reconfiguration:1.7.0.RELEASE (or whatever
version is current). The error I get in logs is:
2015-12-02T10:12:58.19-0700 [App/0] OUT Caused by:
org.springframework.cloud.CloudException: No suitable
ServiceConnectorCreator found: service id=JasonMCFTest-rabbit, service info
type=org.springframework.cloud.service.common.AmqpServiceInfo, connector
type=class com.rabbitmq.client.ConnectionFactory


The following classes are my config class and a simple component that
tries to autowire my rabbit bean. I'm also pretty new to Spring, so feel
free to bash that too.
<code>
package com.jasbro.mcftest;

import org.springframework.cloud.Cloud;
import org.springframework.cloud.CloudFactory;
import org.springframework.cloud.config.java.AbstractCloudConfig;
import org.springframework.cloud.service.common.AmqpServiceInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.rabbitmq.client.ConnectionFactory;

@Configuration
public class PivotalConfig extends AbstractCloudConfig{
@Bean
public ConnectionFactory rabbitConnectionFactory(){
CloudFactory cloudFactory = new CloudFactory();
Cloud cloud = cloudFactory.getCloud();
AmqpServiceInfo serviceInfo = (AmqpServiceInfo)
cloud.getServiceInfo("JasonMCFTest-rabbit");
String serviceId = serviceInfo.getId();
return cloud.getServiceConnector(serviceId,
ConnectionFactory.class, null);
}
}



package com.jasbro.mcftest.scheduled;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.rabbitmq.client.ConnectionFactory;

@Component
public class FilePoller {
@Autowired
private ConnectionFactory rabbitConnectionFactory;
...
}
</code>

And here is the service listing showing (I think) that rabbit is set up
and bound to my app.
C:\src\main\JasonMCFTest>cf s
Getting services in org crt / space dev as jason.c.brown...
OK

name service plan bound apps last
operation
JasonMCFTest-rabbit p-rabbitmq standard JasonMCFTest create
succeeded


Lastly, the list of dependencies from my pom (some of these are probably
not needed, but I don't know which):
junit
spring-webmvc
javax.servlet-api
amqp-client
spring-cloud-cloudfoundry-connector
spring-cloud-spring-service-connector
spring-cloud-services-cloudfoundry-connector
spring-boot-autoconfigure
spring-boot-starter-amqp


Jason Brown
 

I was hoping it would be that simple, but it wasn't. I must have been in a hurry when I accepted the import suggestions. I updated to use the correct imports, but I still have the same issue (with a slightly different stack-trace of course). Am I missing a dependency in my project?


Scott Frederick <scottyfred@...>
 

The original problem didn’t look like a missing dependency issue. What’s
the exact error and stack trace you are getting after fixing the import to
use the spring-rabbitmq ConnectionFactory? Or better yet can you share some
sample code (e.g. in a GitHub project)?

On Wed, Dec 2, 2015 at 4:31 PM, Jason Brown <jasbro(a)gmail.com> wrote:

I was hoping it would be that simple, but it wasn't. I must have been in
a hurry when I accepted the import suggestions. I updated to use the
correct imports, but I still have the same issue (with a slightly different
stack-trace of course). Am I missing a dependency in my project?


Jason Brown
 

It turned out to be dependencies. I removed the *ampq* stuff and added spring-rabbit and now it is working like a charm (still using your simplified bean declaration). Between Maven, Spring, and CF, I feel like it is pretty hard to nail down all the dependencies that are needed.