Mohammed Nosirat
Mohammed Nosirat

Reputation: 372

ActiveMq throws MessageConversionException: Failed to resolve type id when sending an object

I am trying to use ActiveMQ in my two spring boot applications, where I want to enqueue an Object in the first app and dequeue it from the second app.

but I have this error

org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.javasampleapproach.activemq.jms.consumer.JmsReplyConsumer.receive(com.javasampleapproach.activemq.model.PlaceForm)' threw exception; nested exception is org.springframework.jms.support.converter.MessageConversionException: Failed to resolve type id [org.sc.oauth2.resource.server.model.PlaceForm]; nested exception is java.lang.ClassNotFoundException: org.sc.oauth2.resource.server.model.PlaceForm

my model PlaceForm (Object which I want to enqueue) is same in the two apps :

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="@id", scope = PlaceForm.class)
public class PlaceForm  implements Serializable{
    private Long id;
    private String Name;
    private double X;
    private double Y;
    private String Description;
    private Long place_type_id;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return Name;
    }
    public void setName(String name) {
        Name = name;
    }
    public double getX() {
        return X;
    }
    public void setX(double x) {
        X = x;
    }
    public double getY() {
        return Y;
    }
    public void setY(double y) {
        Y = y;
    }
    public String getDescription() {
        return Description;
    }
    public void setDescription(String description) {
        Description = description;
    }
    public Long getPlace_type_id() {
        return place_type_id;
    }
    public void setPlace_type_id(Long place_type_id) {
        this.place_type_id = place_type_id;
    }
}

and the configuration is the same in tow apps too:

@Configuration
public class ActiveMqConnectionFactoryConfig {

    @Value("${jsa.activemq.broker.url}")
    String brokerUrl;

    @Value("${jsa.activemq.borker.username}")
    String userName;

    @Value("${jsa.activemq.borker.password}")
    String password;

    /*
     * Initial ConnectionFactory
     */
    @Bean
    public ConnectionFactory connectionFactory(){
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(brokerUrl);
        connectionFactory.setUserName(userName);
        connectionFactory.setPassword(password);
        return connectionFactory;
    }

    @Bean // Serialize message content to json using TextMessage
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }

    /*
     * Used for Receiving Message
     */
    @Bean
    public JmsListenerContainerFactory<?> jsaFactory(ConnectionFactory connectionFactory,
                                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setMessageConverter(jacksonJmsMessageConverter());
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    /*
     * Used for Sending Messages.
     */
    @Bean
    public JmsTemplate jmsTemplate(){
        JmsTemplate template = new JmsTemplate();
        template.setMessageConverter(jacksonJmsMessageConverter());
        template.setConnectionFactory(connectionFactory());
        return template;
    }
}

In the sender app I used:

@Component
public class JmsProducer {

    @Autowired
    JmsTemplate jmsTemplate;

    @Value("${jsa.activemq.queue.producer}")
    String queue;

    public void send(PlaceForm product) {
        jmsTemplate.convertAndSend(queue, product);
    }
}

where Application.properties is

jsa.activemq.broker.url=tcp://localhost:61616
jsa.activemq.borker.username=admin
jsa.activemq.borker.password=admin

jsa.activemq.queue.producer=jsa-queue-1
jsa.activemq.queue.consumer=jsa-queue-2

and the dependencies are

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>


        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>

        </dependency>


    </dependencies>

and in the reciver app I used:

@Component
public class JmsReplyConsumer {

    @Autowired
    PlaceService placeservice;
    @Autowired
    JmsProducer jms;
    @JmsListener(destination = "${jsa.activemq.queue.listen}", containerFactory = "jsaFactory")
    @SendTo("${jsa.activemq.queue.sendto}")    
    public void receive(PlaceForm s)  {
                   System.out.println("Done");
    }
}

where Application.properties is

jsa.activemq.broker.url=tcp://localhost:61616
jsa.activemq.borker.username=admin
jsa.activemq.borker.password=admin
jsa.activemq.queue.listen=jsa-queue-1
jsa.activemq.queue.sendto=jsa-queue-2
jsa.activemq.queue.send2=jsa-queue-3

and the dependencies are

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>


    <dependency>
        <groupId>com.microsoft.sqlserver</groupId>
        <artifactId>mssql-jdbc</artifactId>

    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.5</version>
    </dependency>


</dependencies>

the "Done" is not printed and the full error is :

org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.javasampleapproach.activemq.jms.consumer.JmsReplyConsumer.receive(com.javasampleapproach.activemq.model.PlaceForm)' threw exception; nested exception is org.springframework.jms.support.converter.MessageConversionException: Failed to resolve type id [org.sc.oauth2.resource.server.model.PlaceForm]; nested exception is java.lang.ClassNotFoundException: org.sc.oauth2.resource.server.model.PlaceForm
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:112) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:69) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:719) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:679) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:649) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:317) [spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:255) [spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1166) [spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1158) [spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1055) [spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73]
Caused by: org.springframework.jms.support.converter.MessageConversionException: Failed to resolve type id [org.sc.oauth2.resource.server.model.PlaceForm]; nested exception is java.lang.ClassNotFoundException: org.sc.oauth2.resource.server.model.PlaceForm
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.getJavaTypeForMessage(MappingJackson2MessageConverter.java:507) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.fromMessage(MappingJackson2MessageConverter.java:228) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:222) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter.extractPayload(AbstractAdaptableMessageListener.java:442) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.unwrapPayload(AbstractAdaptableMessageListener.java:506) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage.getPayload(AbstractAdaptableMessageListener.java:489) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.java:113) ~[spring-messaging-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:112) ~[spring-messaging-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:135) ~[spring-messaging-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:107) ~[spring-messaging-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:104) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    ... 10 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.sc.oauth2.resource.server.model.PlaceForm
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_73]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_73]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) ~[na:1.8.0_73]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_73]
    at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:151) ~[spring-boot-devtools-1.5.8.RELEASE.jar:1.5.8.RELEASE]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_73]
    at org.springframework.util.ClassUtils.forName(ClassUtils.java:250) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.getJavaTypeForMessage(MappingJackson2MessageConverter.java:503) ~[spring-jms-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    ... 20 common frames omitted

can any body help me please???

Upvotes: 4

Views: 4661

Answers (3)

Daniel Castillo
Daniel Castillo

Reputation: 723

I also had that same problem, two different applications communicating with ActiveMQ. I solved it by setting the typeIdMappings property of the converter in both applications.

@Bean
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();

        Map<String, Class<?>> typeIdMappings = new HashMap<String, Class<?>>();
        typeIdMappings.put("JMS_TYPE", MyObject.class);

        converter.setTypeIdMappings(typeIdMappings);
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("JMS_TYPE");

        return converter;
    }

Upvotes: 4

Mohammed Nosirat
Mohammed Nosirat

Reputation: 372

thanks for @justin for his answer, but I want to explain the problem.

the problem is that the two projects use the same model "PlaceForm"

but each of the applications has been declaration the model in its project(first_app has a model "PlaceForm", and the second_app has a model "PlaceForm")

I fixed the problem by deleting "PlaceForm" from the second_app, and making the second_app use first_app as dependency(and use first-app's "PlaceForm").

Upvotes: 0

Justin Bertram
Justin Bertram

Reputation: 35038

The root caused-by is this:

Caused by: java.lang.ClassNotFoundException: org.sc.oauth2.resource.server.model.PlaceForm

The class org.sc.oauth2.resource.server.model.PlaceForm should be available on the classpath on both the sending and receiving application.

Upvotes: 3

Related Questions