I am not able to conncet to RabbitMQ.RabbitMQ is not on local machine .
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
#Configuration
#EnableRabbit
public class AMQPConfig {
#Autowired
private RabbitMQProperties rabbitMQProperties;
#Bean
Queue queue() {
return new Queue(rabbitMQProperties.getQueueName(), false);
}
#Bean
TopicExchange exchange() {
return new TopicExchange(rabbitMQProperties.getExchangeName());
}
#Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(rabbitMQProperties.getRoutingKey());
}
#Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
System.out.println( " ques name is ------- " + rabbitMQProperties.getQueueName() );
container.setQueueNames(rabbitMQProperties.getQueueName());
container.setMessageListener(listenerAdapter);
return container;
}
#Bean
public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
return new MappingJackson2MessageConverter();
}
#Bean
public RabbitTemplate amqpTemplate(ConnectionFactory connectionFactory) {
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(messageConverter());
return rabbitTemplate;
}
#Bean
public Jackson2JsonMessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
#Bean
MessageListenerAdapter listenerAdapter(RabbitMqListener listener) {
return new MessageListenerAdapter(listener, "listen");
}
}
My application.properties looks like
spring.rabbitmq.password=pass
spring.rabbitmq.port=15671
spring.rabbitmq.username=user
spring.rabbitmq.host=https://urltologinscreen
I am able to access to Rabbitmq gui using
https://urltologinscreen:15671
I am getting the below error
ConfigServletWebServerApplicationContext
: Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
'container' defined in class path resource [pathhidden/rabbitmq/AMQPConfig.class]: Unsatisfied dependency
expressed through
method 'container' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.amqp.rabbit.connection.ConnectionFactory'
available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Parameter 0 of method amqpTemplate in pathhidden.rabbitmq.AMQPConfig required a bean of type
'org.springframework.amqp.rabbit.connection.ConnectionFactory' that
could not be found.
How do i resolve the issue?
Here is a simple solution that worked for me
Make sure RabbitMQ is defined on your properties file
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
On your pom.xml file, ensure to add the tag below under dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
My guess is that you properties should be like so:
spring.rabbitmq.password=pass
spring.rabbitmq.username=user
spring.rabbitmq.host=urltologinscreen
Don't need to specify the port or use http in the host
Related
I am new to Spring Boot. The code is Sring Batch which converts data from Outsystems database to xmls.
I am upgrading the code from spring boot 1.4.0 to the latest 2.7.2.
Currently using JDK8 & Gradle 6.9
The code gets deployed to wildfly (RHEL7/Jboss7)
I have migrated the code but the logs show some issues while starting the service. It cannot find Bean "omapmDataSource" but it is clearly defined.
It says: Failed to instantiate [org.mybatis.spring.SqlSessionFactoryBean]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'omapmDataSource' available
The build.gradle file:
buildscript {
repositories {
maven { url "https://jcenter.bintray.com" }
mavenCentral()
}
dependencies {
classpath ("org.springframework.boot:spring-boot-gradle-plugin:2.7.2")
}
}
apply plugin: 'java-library'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
apply plugin: 'project-report'
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.5'
war {
manifest {
attributes 'Implementation-Title': 'Gradle Quickstart',
'Implementation-Version': version
}
archiveName 'ApplicationDataExtractor.war'
metaInf { from 'src/main/resources/META-INF/*' }
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch:2.7.2'
implementation 'org.springframework.boot:spring-boot-maven-plugin:2.7.2'
implementation 'org.springframework.security:spring-security-crypto:5.7.2'
implementation 'org.bouncycastle:bcpg-jdk15on:1.70'
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.springframework.security:spring-security-web:5.7.2'
implementation 'org.springframework.security:spring-security-config:5.7.2'
implementation 'org.springframework.boot:spring-boot-starter-actuator:2.7.2'
//implementation 'org.hsqldb:hsqldb:2.7.2'
implementation 'org.hsqldb:hsqldb:2.5.2'
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.2'
implementation 'org.jasypt:jasypt:1.9.3'
implementation 'org.springframework.boot:spring-boot-starter-batch:2.7.2'
implementation 'org.springframework:spring-oxm:5.3.22'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
implementation 'org.mybatis:mybatis:3.5.10'
implementation files('jdbclibs/ojdbc7.jar')
implementation files('jdbclibs/ucp.jar')
implementation files('jdbclibs/bcprov-jdk15on-155.jar')
implementation files('jdbclibs/CouchbaseIntegration-1.04.jar')
implementation 'org.springframework.data:spring-data-couchbase:4.4.2'
implementation 'org.springframework.boot:spring-boot-starter-data-couchbase:2.7.2'
implementation 'com.couchbase.client:java-client:3.3.3'
implementation 'org.springframework.boot:spring-boot-starter-parent:2.7.2'
implementation group: 'commons-collections', name: 'commons-collections', version: '3.2.2'
implementation group: 'commons-configuration', name: 'commons-configuration', version: '1.10'
implementation 'org.slf4j:jcl-over-slf4j:1.7.36'
testImplementation group: 'junit', name: 'junit', version: '4.13.2'
}
test {
systemProperties 'property': 'value'
}
task copyRuntimeLibs(type: Copy) {
into "lib"
from configurations.runtime
}
task allDeps {
doLast {
println "All Dependencies:"
allprojects.each { p ->
println()
println " $p.name ".center( 60, '*' )
println()
p.configurations.all.findAll { !it.allDependencies.empty }.each { c ->
println " ${c.name} ".center( 60, '-' )
c.allDependencies.each { dep ->
println "$dep.group:$dep.name:$dep.version"
}
println "-" * 60
}
}
}
}
springBoot {
mainClass = "com.*SomePackageName*.om.apm.batch.ApplicationDataExtractorBoot"
}
repositories {
flatDir {
dirs 'repos'
}
}
The Data Source Configuration File consisting the Bean(Pls ignore SomePackageName, I replaced it from actual name):
package com.*SomePackageName*.om.apm.batch.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.stereotype.Component;
import oracle.jdbc.pool.OracleDataSource;
#Configuration
#Component
#MapperScan("com.*SomePackageName*.om.apm.mapping")
#ComponentScan({"com.*SomePackageName*"})
#EntityScan(basePackages = "com.*SomePackageName*")
public class DataSourceConfiguration {
private final static Logger logger = LoggerFactory.getLogger(DataSourceConfiguration.class);
#Autowired
private Environment environment;
#Bean(name = "omapmDataSource")
#Profile("server")
public DataSource omapmDataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
final String dataSourceName = this.environment.getProperty("omapm.datasource");
DataSource dataSource = dsLookup.getDataSource(dataSourceName);
return dataSource;
}
#Bean(name = "omapmDataSource")
#Profile("mock")
public DataSource omapmDataSourceMock() {
final String user = this.environment.getProperty("omapm.jdbc.user");
final String password = this.environment.getProperty("omapm.jdbc.password");
final String url = this.environment.getProperty("omapm.jdbc.url");
return this.oracleDataSource(url, user, password);
}
private DataSource oracleDataSource(String url, String user, String password) {
OracleDataSource dataSource = null;
try {
dataSource = new OracleDataSource();
dataSource.setURL(url);
dataSource.setUser(user);
dataSource.setPassword(password);
} catch (SQLException e) {
logger.error("ERROR : ", e);
e.printStackTrace();
}
return dataSource;
}
#Bean(name = "batchDataSource")
#Primary
//#Profile("mock")
public DataSource batchDataSourceMock() {
final SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new org.hsqldb.jdbcDriver());
//dataSource.setDriverClass());
dataSource.setUrl("jdbc:hsqldb:file:/apps/hsqldb/hsqldb");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
#Autowired
private ResourceLoader resourceLoader;
#Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(omapmDataSource());
sessionFactory.setTypeAliasesPackage("com.*SomePackageName*.om.apm.batch.domain");
sessionFactory.setMapperLocations(new Resource[] {
new ClassPathResource("entity-mapper.xml"),
new ClassPathResource("application-mapper.xml"),
new ClassPathResource("iamapplication-mapper.xml"),
new ClassPathResource("riskletter-mapper.xml"),
new ClassPathResource("accesshistory-mapper.xml"),
new ClassPathResource("hotpeople-mapper.xml"),
new ClassPathResource("referencecode-mapper.xml"),
new ClassPathResource("lettertable-mapper.xml"),
new ClassPathResource("userRoles-mapper.xml")});
return sessionFactory;
}
}
ApplicationDataExtractorBatchConfiguration file which imports stuff from DataSourceConfiguration, etc:
#Configuration
#EnableBatchProcessing
#EnableAsync
#Component
#Import({ DataSourceConfiguration.class, CouchbaseConfiguration.class, BusinessBureauDataCouchbaseConfiguration.class,
ActivityLogCouchbaseConfiguration.class, CRACouchbaseConfiguration.class,
GeneratedDocsCouchbaseConfiguration.class })
#PropertySource("file:/usr/share/jbossas/standalone/configuration/application.properties")
#PropertySource("file:/usr/share/jbossas/standalone/configuration/product.properties")
public class ApplicationDataExtractorBatchConfiguration extends DefaultBatchConfigurer {
private final static Logger logger = LoggerFactory.getLogger(ApplicationDataExtractorBatchConfiguration.class);
// private static int CHUNK_SIZE = 30;
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private PlatformTransactionManager transactionManager;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
#Autowired
private Environment environment;
#Override
#Autowired
public void setDataSource(#Qualifier("batchDataSource") DataSource batchDataSource) {
super.setDataSource(batchDataSource);
}
#Bean
public ResourcelessTransactionManager resourceTransactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactory(
ResourcelessTransactionManager resourceTransactionManager) throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(
resourceTransactionManager);
factory.afterPropertiesSet();
return factory;
}
#Bean
public JobRepository jobRepository(MapJobRepositoryFactoryBean factory)
throws Exception {
return factory.getObject();
}
#Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}
Error Logs:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-08-08 08:43:03,073 ERROR [org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter] (ServerService Thread Pool -- 46)
***************************
APPLICATION FAILED TO START
***************************
Description:
VFS resource ["/content/ApplicationDataExtractor.war/WEB-INF/classes/com/*SomePackageName*/om/apm/mapping/EntityMapper.class"] required a bean named 'omapmDataSource' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean named 'omapmDataSource' in your configuration.
2022-08-08 08:43:03,074 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 46) MSC000001: Failed to start service jboss.deployment.unit."ApplicationDataExtractor.war".undertow-deployment: org.jboss.msc.service.StartException in service jboss.deployment.unit."ApplicationDataExtractor.war".undertow-deployment: java.lang.RuntimeException: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'batchTriggerForCSVFile': Unsatisfied dependency expressed through field 'riskLettersSummaryDataExtractorStep'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'riskLettersSummaryDataExtractorStep' defined in class path resource [com/*SomePackageName*/om/apm/batch/config/ApplicationDataExtractorBatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.Step]: Factory method 'riskLettersSummaryDataExtractorStep' threw exception; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'riskLettersDataReader': Unsatisfied dependency expressed through field 'entityMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityMapper' defined in VFS resource ["/content/ApplicationDataExtractor.war/WEB-INF/classes/com/*SomePackageName*/om/apm/mapping/EntityMapper.class"]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/*SomePackageName*/om/apm/batch/config/DataSourceConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.mybatis.spring.SqlSessionFactoryBean]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'omapmDataSource' available
For full logs: https://drive.google.com/file/d/1g7hX2vFZR1THhTpKBeW10IEh_xqtZ97Q/view?usp=sharing
The omapmDataSource dataSource bean is defined under the server profile. Accoding to the error, this bean is not defined, probably because you are starting your application with the default profile (in which that bean won't be visible).
Make sure you start your application with the server profile, or make that bean available to the default profile.
My spring-boot applications fails to start with the following exceptions:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'BatchConfiguration': Unsatisfied dependency expressed through field 'sftpProcessor'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'SFTPProcessor': Unsatisfied dependency expressed through field 'gateway'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com....SFTPProcessor$UploadGateway' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'SFTPProcessor': Unsatisfied dependency expressed through field 'gateway'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com....SFTPProcessor$UploadGateway' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
And the class SFTPProcessor is a step of a spring boot batch application.
It complains that the gateway cannot be Autowired. However, I don't see any obvious problem with the code below.
I've searched on the internet some people talks about the messaginggateway and itemwriter are not in the same context.
How can I identify the root cause and fix this issue.
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.remote.session.CachingSessionFactory;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.sftp.outbound.SftpMessageHandler;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
#Component
public class SFTPProcessor {
#Value("${sftp.host}")
private String sftpHost;
#Value("${sftp.port:22}")
private int sftpPort;
#Value("${sftp.user}")
private String sftpUser;
#Value("${sftp.privateKey:#{null}}")
private Resource sftpPrivateKey;
#Value("${sftp.privateKeyPassphrase:}")
private String sftpPrivateKeyPassphrase;
#Value("${sftp.password:#{null}}")
private String sftpPasword;
#Value("${sftp.remote.directory:/}")
private String sftpRemoteDirectory;
#Autowired private UploadGateway gateway;
#Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(sftpHost);
factory.setPort(sftpPort);
factory.setUser(sftpUser);
if (sftpPrivateKey != null) {
factory.setPrivateKey(sftpPrivateKey);
factory.setPrivateKeyPassphrase(sftpPrivateKeyPassphrase);
} else if (sftpPasword != null) {
factory.setPassword(sftpPasword);
}
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
}
#Bean
#ServiceActivator(inputChannel = "toSftpChannel")
public MessageHandler handler() {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
handler.setRemoteDirectoryExpression(new LiteralExpression(sftpRemoteDirectory));
handler.setFileNameGenerator(
new FileNameGenerator() {
#Override
public String generateFileName(Message<?> message) {
if (message.getPayload() instanceof File) {
return ((File) message.getPayload()).getName();
} else {
throw new IllegalArgumentException("File expected as payload.");
}
}
});
return handler;
}
#MessagingGateway
public interface UploadGateway {
#Gateway(requestChannel = "toSftpChannel")
void upload(File file);
}
public void doSFTP(String fileName) throws IOException {
// Prepare phase
Path tempFile = Paths.get(fileName);
// Prerequisites
gateway.upload(tempFile.toFile());
}
}
I'm new to Kotlin and working on a Spring application, trying to set Redis configuration. I keep getting this problem:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'redisConfig': Requested bean is
currently in creation: Is there an unresolvable circular reference?
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| redisConfig defined in file [file]
└─────┘
I don't understand what exactly causes this problem and how to fix it. It seems to me that RedisConfig is being created inside RedisConfig, but I'm not sure and don't understand where this problem comes from.
Here's RedisConfig.kt
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.MessageListener
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.listener.ChannelTopic
import org.springframework.data.redis.listener.RedisMessageListenerContainer
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
#Configuration
class RedisConfig(val messageListener: MessageListener) {
#Value("\${spring.redis.host}")
lateinit var redisHost: String
#Value("\${spring.redis.port}")
lateinit var redisPort: String
#Value("\${spring.redis.topic}")
lateinit var redisTopic: String
#Bean
fun jedisConnectionFactory(): JedisConnectionFactory {
val config = RedisStandaloneConfiguration(redisHost, redisPort.toInt())
val jedisClientConfiguration = JedisClientConfiguration.builder().usePooling().build()
val factory = JedisConnectionFactory(config, jedisClientConfiguration)
factory.afterPropertiesSet()
return factory
}
#Bean
fun redisTemplate(): RedisTemplate<String, Any> {
val template: RedisTemplate<String, Any> = RedisTemplate()
template.connectionFactory = JedisConnectionFactory()
template.valueSerializer = GenericJackson2JsonRedisSerializer()
return template
}
#Bean
fun topic(): ChannelTopic = ChannelTopic(redisTopic)
#Bean
fun newMessageListener(): MessageListenerAdapter = MessageListenerAdapter(messageListener)
#Bean
fun redisContainer(): RedisMessageListenerContainer {
val container = RedisMessageListenerContainer()
container.connectionFactory = jedisConnectionFactory()
container.addMessageListener(newMessageListener(), topic())
return container
}
}
I believe you should use your method jedisConnectionFactory() instead of a new JedisConnectionFactory class, in redisTemplate method.
Basicly, you should do the same as you do in redisContainer()
I am trying to listen to topic using the below snippet. However its listening to queue by default. There is no xml config in this case. I am completely relying on annotations. Moreover I have relied completely on the AutoConfiguration provided by Spring boot. I am not sure how to set the destination type as topic, In JmsListener. Spring JMS gurus please help.
#Component
public class MyTopicListener {
#JmsListener(destination = "${trans.alert.topic}")
public void receiveMessage(TransactionAlert alert) {
logger.info("AlertSubscriberEmail :: Sending Email => <" + alert + ">");
}
}
The answer marked correct is ALMOST correct. It still wont work because:
factory.setPubSubDomain(true)
must come AFTER:
configurer.configure(factory, connectionFactory);
Otherwise the pubSubDomain flag being set to true is lost when configuring the defaults and that factory instance will still work with queues and not topics.
I just took the complete Spring boot example from : https://github.com/spring-guides/gs-messaging-jms/
In this it is created for sending and receipt of messages from a queue. To Change this to a topic , you have to set the Pub-Sub property in the Factory instance.
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import javax.jms.ConnectionFactory;
#SpringBootApplication
#EnableJms
public class JmsSampleApplication {
public void registerBeans(ConfigurableApplicationContext context ){
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(JmsTemplate.class);
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
builder.addPropertyValue("connectionFactory", cachingConnectionFactory); // set property value
DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory();
factory.registerBeanDefinition("jmsTemplateName", builder.getBeanDefinition());
}
#Bean
public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
// This provides all boot's default to this factory, including the message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
#Bean
public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
//factory.setPubSubDomain(true);
// This provides all boot's default to this factory, including the message converter
configurer.configure(factory, connectionFactory);
return factory;
}
#Bean // Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(JmsSampleApplication.class, args);
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
// Send a message with a POJO - the template reuse the message converter
System.out.println("Sending an email message.");
jmsTemplate.convertAndSend("mailbox.topic", new Email("info#example.com", "Hello"));
jmsTemplate.convertAndSend("mailbox.queue", new Email("info#example.com", "Hello"));
}
}
The listener
package org.springboot.jms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/**
* Created by RGOVIND on 10/20/2016.
*/
#Component
public class HelloTopicListener {
#JmsListener(destination = "mailbox.topic", containerFactory = "topicListenerFactory")
public void receiveTopicMessage(Email email) {
System.out.println("Received <" + email + ">");
}
#JmsListener(destination = "mailbox.queue", containerFactory = "queueListenerFactory")
public void receiveQueueMessage(Email email) {
System.out.println("Received <" + email + ">");
}
}
Once this is done , you are all set to subscribe to the topic of choice.
There are multiple approaches to this of course , you can have a map of beans for different jmsTemplates , each of which can be used when you need them based on queue or topic. The template & beans can be instantiated in a method you choose to like discussed in this SO Question. Hope it helps
In Spring Boot's Application.properties, try setting the following property:
spring.jms.pub-sub-domain=true
Then, use this property for the container factory that you are using to listen to the topic.
I recently started learning spring. I am trying a simple example with spring data jpa in a spring mvc project. I am getting the following error while deploying the war file in the tomcat.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creati
ng bean with name '(inner bean)#584d15f2': Cannot resolve reference to bean 'ent
ityManagerFactory' while setting constructor argument; nested exception is org.s
pringframework.beans.factory.BeanCurrentlyInCreationException: Error creating be
an with name 'entityManagerFactory': Requested bean is currently in creation: Is
there an unresolvable circular reference?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver
.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver
.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolve
ConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.instant
iateUsingFactoryMethod(ConstructorResolver.java:444)
at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:11
19)
at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBean
Factory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver
.resolveInnerBean(BeanDefinitionValueResolver.java:299)
... 92 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: E
rror creating bean with name 'entityManagerFactory': Requested bean is currently
in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
y.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr
y.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe
an(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver
.resolveReference(BeanDefinitionValueResolver.java:351)
... 100 more
27-Sep-2015 17:56:45.304 INFO [http-apr-8080-exec-35] org.apache.catalina.startu
p.HostConfig.deployWAR Deployment of web application archive D:\ApacheTomcat\apa
che-tomcat-8.0.26\webapps\springTest.war has finished in 6,124 ms
My controller code is as follows,
package com.demo.repo;
import com.demo.model.Customer;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
import javax.activation.DataSource;
import javax.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
/**
* Handles requests for the application home page.
*/
#Controller
#Configuration
#EnableJpaRepositories("com.demo.repo")
#EnableTransactionManagement
public class HomeController {
#Autowired
customerRepository repository;
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#Bean(destroyMethod = "close")
DataSource dataSource(Environment env) {
HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver"));
dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url"));
dataSourceConfig.setUsername(env.getRequiredProperty("db.username"));
dataSourceConfig.setPassword(env.getRequiredProperty("db.password"));
return (DataSource) new HikariDataSource(dataSourceConfig);
}
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
Environment env) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource((javax.sql.DataSource) dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("com.demo.repo");
Properties jpaProperties = new Properties();
//Configures the used database dialect. This allows Hibernate to create SQL
//that is optimized for the used database.
jpaProperties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
//Specifies the action that is invoked to the database when the Hibernate
//SessionFactory is created or closed.
jpaProperties.put("hibernate.hbm2ddl.auto",
env.getRequiredProperty("hibernate.hbm2ddl.auto")
);
//Configures the naming strategy that is used when Hibernate creates
//new database objects and schema elements
jpaProperties.put("hibernate.ejb.naming_strategy",
env.getRequiredProperty("hibernate.ejb.naming_strategy")
);
//If the value of this property is true, Hibernate writes all SQL
//statements to the console.
jpaProperties.put("hibernate.show_sql",
env.getRequiredProperty("hibernate.show_sql")
);
//If the value of this property is true, Hibernate will format the SQL
//that is written to the console.
jpaProperties.put("hibernate.format_sql",
env.getRequiredProperty("hibernate.format_sql")
);
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
for(Customer customer : repository.findAll())
{
System.out.println("Log Results :: "+customer.toString());
}
return "myhome";
}
}
Can anyone suggest me what is wrong with my code and any suggestions to resolve the same.
It seems that your entityManagerFactory requires the dataSource that is defined in the same configuration file.
Try moving the definition of dataSource to another configuration class, or, instead of passing the dataSource as parameter, just call the dataSource() method when you need it in the entityManagerFactory.
#Autowired
Environment env;
#Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean =
new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource((javax.sql.DataSource) dataSource());
....
}
TIP: Don't mix your #Controller and #Configuration. Create a different file for each of them.