ActiveMq抛出MessageConversionException:发送对象时无法解析类型ID

时间:2018-04-22 22:58:42

标签: spring-boot jms activemq

我正在尝试在我的两个Spring启动应用程序中使用ActiveMQ,我希望在第一个应用程序中将一个Object排入队列并从第二个应用程序中将其出列。

但我有这个错误

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

我的模型PlaceForm(我要入队的对象)在两个应用程序中是相同的:

@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;
    }
}

并且两个应用程序的配置也相同:

@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;
    }
}

在我使用的发件人应用中:

@Component
public class JmsProducer {

    @Autowired
    JmsTemplate jmsTemplate;

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

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

其中Application.properties是

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

,依赖项是

<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>

在我使用的reciver应用程序中:

@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");
    }
}

其中Application.properties是

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

,依赖项是

<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>

未完成“完成”,完整错误为:

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

任何人都可以帮我吗???

3 个答案:

答案 0 :(得分:1)

引起的根源是:

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

org.sc.oauth2.resource.server.model.PlaceForm应该在发送和接收应用程序的类路径上可用。

答案 1 :(得分:1)

感谢@justin的回答,但我想解释一下这个问题。

问题是两个项目使用相同的模型&#34; PlaceForm&#34;

但是每个应用程序都在其项目中声明了模型(first_app有一个模型&#34; PlaceForm&#34;,而second_app有一个模型&#34; PlaceForm&#34;)

我通过删除&#34; PlaceForm&#34;来解决问题。来自second_app,并使second_app使用first_app作为依赖项(并使用first-app&#39;&#34; PlaceForm&#34;)。

答案 2 :(得分:0)

我也有同样的问题,两个不同的应用程序与ActiveMQ通信。我通过在两个应用程序中都设置转换器的typeIdMappings属性来解决它。

@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;
    }