MessageConversionException: Failed to resolve class name in Spring AMQP - spring

I am trying out simple sender and receiving of messages using Spring AMQP with jackson2JsonMessageConverter.
Also, what is the significance of _TypeId_ here
why it is showing sender package with class name?
I am facing issues in receiving the message.
Below is my configuration
org.springframework.amqp.support.converter.MessageConversionException:
failed to resolve class name. Class not found
[org.springframework.amqp.helloworld.User]
at org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper.getClassIdType(DefaultJackson2JavaTypeMapper.java:121)
at org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper.toJavaType(DefaultJackson2JavaTypeMapper.java:90)
at org.springframework.amqp.support.converter.Jackson2JsonMessageConverter.fromMessage(Jackson2JsonMessageConverter.java:145)
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:236)
at org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter.onMessage(MessageListenerAdapter.java:288)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:777)
... 10 common frames omitted Caused by: java.lang.ClassNotFoundException:
org.springframework.amqp.helloworld.User
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1139)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
at org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper.getClassIdType(DefaultJackson2JavaTypeMapper.java:118)
... 15 common frames omitted
XML Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<rabbit:connection-factory id="connectionFactory"
channel-cache-size="25" host="10.165.18.29" username="BipUser"
password="bip" />
<rabbit:queue name="Job Queue"></rabbit:queue>
<rabbit:queue name="Input Queue"></rabbit:queue>
<rabbit:queue name="More Info Queue"></rabbit:queue>
<rabbit:queue name="Adaptor O/P Queue"></rabbit:queue>
<rabbit:queue name="Command Queue"></rabbit:queue>
<rabbit:queue name="Error Queue"></rabbit:queue>
<bean id="simpleMessageConverter"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter">
</bean>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
message-converter="jsonConverterWithDefaultType" />
<rabbit:listener-container
connection-factory="connectionFactory" auto-declare="true"
message-converter="simpleMessageConverter" auto-startup="true"
acknowledge="auto">
<rabbit:listener ref="rabbitMQJobListener"
queue-names="Job Queue" priority="10" />
</rabbit:listener-container>
<rabbit:admin connection-factory="connectionFactory" id="amqpAdmin" />
<bean id="rabbitMQJobListener" class="com.bosch.bip.rabbitmq.consumer.RabbitMQJobListener">
</bean>
<rabbit:annotation-driven container-factory="rabbitListenerContainerFactory" />
<bean id="rabbitListenerContainerFactory"
class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="messageConverter" ref="jsonConverterWithDefaultType"></property>
</bean>
<bean id="jsonConverterWithDefaultType"
class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter">
<property name="classMapper">
<bean class="org.springframework.amqp.support.converter.DefaultClassMapper">
</bean>
</property>
</bean>
</beans>
Sender
package org.springframework.amqp.helloworld;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
#Component
public class Sender {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
User user=new User();
user.setPassword("welcome");
user.setUserName("welcome");
user.setXml("myxml");
RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
Jackson2JsonMessageConverter converter = context.getBean(Jackson2JsonMessageConverter.class);
MessageProperties properties = new MessageProperties();
properties.setHeader("user", "user");
properties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
Message message = converter.toMessage(user, properties);
System.out.println(message);
rabbitTemplate.send(message);
}
/* #RabbitListener(queues = HelloWorldConfiguration.helloWorldQueueName)
public void handleMessage(User user) {
System.out.println("User Values::::::::"+user.getPassword());
}*/
}
Consumer
package com.bip.rabbitmq.consumer;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.bip.entity.User;
#EnableRabbit
#Component
public class RabbitMQJobListener {
#RabbitListener(queues="Job Queue")
public void onMessage(User message) {
System.out.println(new String(message.getPassword()));
}
}
RabbitMQ
Exchange (AMQP default)
Routing Key Job Queue
Redelivered ○
Properties
priority: 0
delivery_mode: 2
headers:
user: user
__TypeId__: org.springframework.amqp.helloworld.User
content_encoding: UTF-8
content_type: application/json
Payload
57 bytes
Encoding: string
{"userName":"welcome","password":"welcome","xml":"myxml"}

The _TypeID_ header is set on outbound to tell the inbound what class to convert the JSON to. If you want to convert to a different class that is type-compatible with the JSON, you have to configure the converter.
If it'a always the same class, use a custom ClassMapper (not the default one).
Or, see this test, its listener and its configuration to see how to configure a different typeid mapping.

This might happen when the package name of the serialized instance is different than the consumer's model, represented by the headers: TypeId.
I believe following example will make things lot clearer.
Schema: Exchange x.invoice of type fanout is bound to queue q.invoice.
Producer: We are sending JSON message with type Id com.example.produceronequeuemultipletypes.model.InvoiceCreatedMessage.
Class ParseConfig is to help us avoid manual serialization of the instance to String.
public void sendInvoiceMessages() {
invoiceCreatedMessage.setId(0);
invoiceCreatedMessage.setType("Invoice Created");
rabbitTemplate.convertAndSend("x.invoice", "", invoiceCreatedMessage);
}
class InvoiceCreatedMessage {
private String type;
private int id;
}
#Configuration
class ParseConfig {
#Bean
public ObjectMapper getObjectMapper() {
return new ObjectMapper();
}
#Bean
public Jackson2JsonMessageConverter getConverter(
#Autowired ObjectMapper objectMapper) {
return new Jackson2JsonMessageConverter(objectMapper);
}
}
Consumer: Create a class mapper bean with mapping from "com.example.produceronequeuemultipletypes.model.InvoiceCreated" to InvoiceCreated.class.
#Slf4j
#Service
public class InvoiceConsumer {
#RabbitListener(queues = "q.invoice")
public void handleInvoiceCreated(
InvoiceCreatedMessage invoiceCreatedMessage) {
log.info("[Created] Invoice " + invoiceCreatedMessage);
}
}
#Configuration
class ParseConfig {
#Bean
public ObjectMapper getObjectMapper() {
return new ObjectMapper();
}
#Bean
public Jackson2JsonMessageConverter getConverter(
#Autowired ObjectMapper objectMapper) {
Jackson2JsonMessageConverter messageConverter =
new Jackson2JsonMessageConverter(objectMapper);
messageConverter.setClassMapper(getClassMapper());
return messageConverter;
}
#Bean
public DefaultClassMapper getClassMapper() {
DefaultClassMapper classMapper = new DefaultClassMapper();
Map<String, Class<?>> map = new HashMap<>();
map.put(
"com.example.produceronequeuemultipletypes.model." +
"InvoiceCreatedMessage",
InvoiceCreatedMessage.class)
classMapper.setIdClassMapping(idClassMapping);
return classMapper;
}
}
class InvoiceCreatedMessage {
private String type;
private int id;
}
Reference:
https://docs.spring.io/spring-amqp/reference/html/#json-message-converter
https://www.udemy.com/course/rabbitmq-java-spring-boot-for-system-integration/

Related

How to create a websocket endpoint in an existing spring application

I'm trying to make available a new websocket endpoint in an existing spring application.
I'm following the documentation at https://docs.spring.io/spring/docs/4.3.2.RELEASE/spring-framework-reference/html/websocket.html#websocket-server-handler . But based on documentation I should configure the DispatcherServlet or use WebSocketHttpRequestHandler.
How can I make available the websocket endpoint without any change in the web.xml config file ?
This is what I tried, but not working (Client error 404 not found).
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ws="http://jax-ws.dev.java.net/spring/core" xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers allowed-origins="*">
<websocket:mapping path="/ws" handler="websocketService"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
</websocket:handshake-interceptors>
</websocket:handlers>
<bean id="websocketService" class="com.krios.SocketHandler"/>
</beans>
Class file:
public class SocketHandler extends TextWebSocketHandler {
List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message)
throws InterruptedException, IOException {
for(WebSocketSession webSocketSession : sessions) {
Map value = new Gson().fromJson(message.getPayload(), Map.class);
webSocketSession.sendMessage(new TextMessage("Hello " + value.get("name") + " !"));
}
}
#Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//the messages will be broadcasted to all users.
sessions.add(session);
}
}
I can provide you the java configuration (you can then change it to xml yourself or use it as java class and scan it from xml)
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
#Bean
public MessagingWebSocketHandler webSocketHandler() {
//handler of your websocket. should be a class implementing WebSocketHandler.
//You could also extend AbstractWebSocketHandler or TextWebSocketHandler and override methods
return new MessagingWebSocketHandler();
}
#Bean
public WebSocketContainerFactoryBean createWebSocketContainer() {
WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
container.setMaxTextMessageBufferSize(StaticConfig.MAXIMUM_WS_TEXT_BUFFER_SIZE);
container.setMaxBinaryMessageBufferSize(StaticConfig.MAXIMUM_WS_BINARY_BUFFER_SIZE);
container.setMaxSessionIdleTimeout(StaticConfig.MAXIMUM_WS_SESSION_IDLE_TIMEOUT);
container.setAsyncSendTimeout(StaticConfig.MAXIMUM_WS_ASYNC_SEND_TIMEOUT);
return container;
}
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(webSocketHandler(), "/message").setAllowedOrigins("*"); // you could also get handler from context
}
}
I hope it hepls.
update
I myself don't use xml based configuration. But the simplest way is to add this java code then scan it from xml. For example, by adding this line to your spring servlet configuration xml you can scan your configuration package or whole project package.
<context:component-scan base-package="com.my.company.config" />
Then your WebSocketConfig class must be under com.my.company.config
Documentation Of Websocket support and configuration is here. On section Create and Configure a WebSocketHandler you can read about xml configuration. I havent test it myself tho.

My autowired DataSource is returning null in Spring, how come?

I'm trying to set my dataSource to get a connection but it is returning null on conn=dataSource.getConnection();. Here is the relevant code from my DAO:
#Autowired
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public Acronym findByAcronymId(int acronymId) {
String sql = "SELECT * FROM acronym_table WHERE acronymId = ?";
Connection conn = null;
try {
conn = dataSource.getConnection();
Here is the database bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "dataSource"
class = "org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db_name?useSSL=false" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
</beans>
Here's the acronym bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "acronymDAO" class ="com.user.dao.JdbcAcronymDAO">
<property name = "dataSource" ref ="dataSource"/>
</bean>
</beans>
Try to move your #Autowired annotation on the field itself, something like this:
#Autowired
private DataSource dataSource;
Or to put it on constructor level, instead of putting it on setter level.
I believe that the data source bean is not being auto-wired because you're using it on setter level which never gets called.
Add this line to your spring context xml
<context:annotation-config/>
So that it can scan your classes for the #Autowired annotation
The problem was that I had an extra bean. Once I deleted the acronym bean and setup #Autowired it worked correctly
I'm going to add this here as this question comes so far up the google search results!
This link was invaluable for helping me solve this:
https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/
To summarise, something somewhere is probably instantiating with a new(). If a service is using an autowired property, the service must be autowired as well.
#Controller
public class Controller {
// !!!!!! This won't work!
// !!!!!! Autowire the service!
#GetMapping("/brokenexample")
public String brokenExample() {
MyService my = new MyService();
my.doStuff();
}
#Autowired
MyService service;
#GetMapping("/example")
public String example() {
service.doStuff();
}
}
#Service
public class MyService() {
#Autowired
MyRepository repo;
public void doStuff() {
repo.findByName( "foo" );
}
}
#Repository
public interface MyRepository extends SomeRepository<My, Long> {
List<My> findByName( String name );
}

Why it failed when combining #component and bean?

I am trying to use #component and regular beans. And below is my code:
MainApp.java
package com.company;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
}
}
SpellChecker.java
package com.company;
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling(){
System.out.println("Inside checkSpelling." );
}
}
TextEditor.java
package com.company;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class TextEditor {
#Autowired
private SpellChecker spellChecker;
#Autowired
#Qualifier("region")
private String region;
public TextEditor() {
System.out.println("I am in " + region );
}
public SpellChecker getSpellChecker( ){
return spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.company" />
<bean id="spellChecker" class="SpellChecker" />
<bean id="region" class="java.lang.String">
<constructor-arg value="Vancouver" />
</bean>
</beans>
However, when I run this code, it gave error messages:
Cannot find class [SpellChecker] for bean with name 'spellChecker' defined in class path resource
When I remove the bean in the Beans.xml for SpellChecker and mark #component to it as well. Then it works (yet, the region String is still empty).
So my question is: why cannot we autowired a bean in a #Component class?
That isn't related to Spring Integration, please, choose tags properly for the questions.
You problem is that SpellChecker is in the com.company package, but <bean class=""> really requires the fully qualified class name to define the proper class to instantiate.
The base-package="com.company" is exactly for the #Component to scan, but that fully doesn't relate to regular <bean> definition.
By using fully qualified class name it should work...
<bean id="spellChecker" class="com.company.SpellChecker" />

aop with spring 2.5 without Aspect J

I am working in a old project with spring 2.5.Application context starts with
.
I need to implment logging using aop I need to log each and every class's method.
tried this link :
http://forum.spring.io/forum/spring-projects/aop/4769-apply-jdkregexpmethodpointcut-to-multiple-beans-how.But didnt work.
and some more options.(but i felt this is taking me some where)
Also, I cant use xsd so i cant use aop namespace.i cant use aspect j as well
Please guide me on how can i achieve this what should be point cut as I have tried . and * as pattern and bean names with the point cut.
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="debugInterceptor" class="test.DebugInterceptor" />
<bean id="testBean" class="test.TestBean" />
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="*" />
<property name="interceptorNames">
<list>
<value>debugInterceptor</value>
</list>
</property>
</bean>
</beans>
TestBean
package test;
public class TestBean {
public void foo() {
System.out.println("foo");
}
void bar() {
System.out.println("bar");
}
}
DebugInterceptor
package test;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class DebugInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("Before: invocation=[" + invocation + "]");
Object rval = invocation.proceed();
System.out.println("Invocation returned");
return rval;
}
}
AopTest
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTest {
public static void main(String[] args) {
ApplicationContext ap = new ClassPathXmlApplicationContext("classpath:spring.xml");
TestBean bean = (TestBean)ap.getBean("testBean");
bean.foo();
bean.bar();
}
}

Can I use both configuring SI with annotation in java file and xml?

Last year, spring integration released 4.0 version for us to configure using annotation without configuring in XML files. But I want to use this feature using the existing XML configurations.
So I wrote the code using spring boot and integration annotation
#Configuration
#ComponentScan(basePackages ={"com.strongjoe.blue"},excludeFilters=#ComponentScan.Filter(type=FilterType.REGEX, pattern={"com.strongjoe.blue.agent.Bootstrap*"}))
#IntegrationComponentScan
#ImportResource( {"${context.agent.path}context-bean-*.xml", // Context Configuration
"${project.agent.path}context-properties.xml" } ) // Project Based Chain configuration
public class AgentStarter implements CommandLineRunner{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
#Lazy
#Bean
#ServiceActivator(inputChannel="blue-hub-start-channel", outputChannel="blue-hub-route-channel")
public <T> BlueMessage<T> startJob(BlueMessage<T> msg) {
logger.debug("BluE Hub Agent started :{} [phrase:{}]", System.currentTimeMillis() , "prototype-version");
return msg;
}
#Lazy
#Bean
#ServiceActivator(inputChannel="blue-hub-end-channel")
public <T> BlueMessage<T> endJob(BlueMessage<T> msg) {
logger.debug("BluE Hub Agent ended :{} [phrase:{}]", System.currentTimeMillis() , "prototype-version");
return msg;
}
#Bean
#Transformer(inputChannel="blue-normalized-channeel", outputChannel="blue-output-channel")
public org.springframework.integration.transformer.Transformer JsonToMap( ) {
return new JsonToObjectTransformer( List.class );
}
#MessageEndpoint
public static class Echo {
#ServiceActivator(inputChannel="blue-output-channel")
public void stringEcho(Message message) {
}
}
#Autowired
Gateway gateway;
public static void main(String[] args) {
SpringApplication app = new SpringApplication(AgentStarter.class);
app.setWebEnvironment(false);
app.run(args).close();
}
#Override
public void run(String... args) throws Exception {
System.err.println("blue-hub-agent started..");
System.out.println(gateway.sendReceive("gitlab"));
}
And I wrote the definition about every channel I use in the xml.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-4.0.xsd
http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd
http://www.springframework.org/schema/integration/xml http://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http-4.0.xsd">
<int:channel id="blue-normalized-channel" />
<int:channel id="blue-header-channeel" />
<int:channel id="blue-request-channel" />
<int:channel id="blue-output-channel" />
<int:channel id="blue-gitlab-request-prepare-channel" />
<int:channel id="blue-hub-start-command-channel" />
<int:channel id="blue-hub-start-channel"/>
<int:channel id="blue-hub-end-channel" />
But I got error.
Caused by: org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'application:8090.blue-hub-start-channel'.
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:81)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
The reason will be, I think,
that spring bean in XML file and spring bean with the annotation has different context. So I think that even if blue-hub-start-channel is subscribed by the service activator named "startJob", it got error.
How can I solve this problem?
Annotating #ServiceActivator on #Bean is not for POJO Messaging. See the documentation.
When you annotate #Beans this way, you have to provide an appropriate object (MessageHandler in this case).
For POJO style annotated methods, the annotation must be on a method in a #Bean method (like you have on this one...
#MessageEndpoint
public static class Echo {
#ServiceActivator(inputChannel="blue-output-channel")
public void stringEcho(Message message) {
}
}
... and then declare a #Bean for Echo.
You can put all your #ServiceActivator methods (and #Transformers) in the same #MessageEndpoint.

Resources