6

I'm trying to convert a java object to json format using mappingjackson2messageconvertor but looks like it is not converting to json object instead throwing nullpoint exception error. Wondering what i'm doing wrong.

I have checked one of the example here . But i'm not using rabbitmq instead of i'm using activemq.

source

@SpringBootApplication
@EnableJms
public class Application {
    @Bean
    JmsListenerContainerFactory<?> myJmsContainerFactory(ConnectionFactory connectionFactory) {
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new MappingJackson2MessageConverter());
        return factory;
    }


    public static void main(String[] args) {
        // Clean out any ActiveMQ data from a previous run
        FileSystemUtils.deleteRecursively(new File("activemq-data"));

        // Launch the application
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        AssetApi asset = new AssetApi();
        asset.setBroadcasterId("test");
        asset.setNotes("test");

        // Send a message
        MessageCreator messageCreator = new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MessageConverter message = new MappingJackson2MessageConverter();
                return message.toMessage(asset, session);
            }
        };
        JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
        System.out.println("Sending a new message.");
        jmsTemplate.send("mailbox-destination", messageCreator);
    }
}

Error

java.lang.NullPointerException: null
    at org.apache.activemq.command.ActiveMQMessage.getStringProperty(ActiveMQMessage.java:676)
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.getJavaTypeForMessage(MappingJackson2MessageConverter.java:377)
    at org.springframework.jms.support.converter.MappingJackson2MessageConverter.fromMessage(MappingJackson2MessageConverter.java:195)
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:215)
    at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter.extractPayload(AbstractAdaptableMessageListener.java:397)
    at org.springframework.jms.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:108)
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:77)
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:62)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:678)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:638)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:608)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:579)
    at org.springframework.jms.listener.SimpleMessageListenerContainer.processMessage(SimpleMessageListenerContainer.java:329)
    at org.springframework.jms.listener.SimpleMessageListenerContainer$2.onMessage(SimpleMessageListenerContainer.java:305)
    at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1390)
    at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131)
    at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202)
    at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:133)
    at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:48)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
user1595858
  • 3,700
  • 15
  • 66
  • 109

4 Answers4

3

With the JMS converter, you need to tell the converter what type (id) you want to create from the JSON.

You do that by telling it which JMS property (header) contains the type id).

There is then a Map from type ids to class names.

Or you can subclass and override getJavaTypeForMessage().

See the javadoc for method getJavaTypeForMessage() on the converter.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
1

I did as Gary Russell pointed out, from my calling class

Map<String, Class<?>> typeIdMappings = new HashMap<String, Class<?>>();
typeIdMappings.put("JMSType",Audit.class);
mappingJackson2MessageConverter.setTypeIdMappings(typeIdMappings);
mappingJackson2MessageConverter.setTypeIdPropertyName("JMSType"); 
Audit audit = (Audit) mappingJackson2MessageConverter.fromMessage(message);

Then I overrode the MappingJackson2MessageConverter's methods:

@Component
public class MecMappingJackson2MessageConverter extends MappingJackson2MessageConverter {

    private Map<String, Class<?>> idClassMappings = new HashMap<String, Class<?>>();

    private Map<Class<?>, String> classIdMappings = new HashMap<Class<?>, String>();

    private ObjectMapper objectMapper = new ObjectMapper();

    private ClassLoader beanClassLoader;

    @Override
    public JavaType getJavaTypeForMessage(Message message){

        Class<?> mappedClass = this.idClassMappings.get("JMSType");
    if (mappedClass != null) {
        return this.objectMapper.getTypeFactory().constructType(mappedClass);
    }
    try {
        Class<?> typeClass = ClassUtils.forName("JMSType", this.beanClassLoader);
            return this.objectMapper.getTypeFactory().constructType(typeClass);
        }
        catch (Throwable ex) {
            throw new MessageConversionException("Failed to resolve type id [" + "JMSType" + "]", ex);
        }

    }

    @Override
    public void setTypeIdMappings(Map<String, Class<?>> typeIdMappings) {
        this.idClassMappings = new HashMap<String, Class<?>>();
        for (Map.Entry<String, Class<?>> entry : typeIdMappings.entrySet()) {
            String id = entry.getKey();
            Class<?> clazz = entry.getValue();
        this.idClassMappings.put(id, clazz);
        this.classIdMappings.put(clazz, id);
    }
}

}

Tim Schumacher
  • 321
  • 3
  • 19
0

I had created my own de-serialzer and set the same in my MappingJackson2MessageConverter object like below

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(WebResponse.class,new WebResponseDeserializer());
mapper.registerModule(module);
new MappingJackson2MessageConverter().setObjectMapper(mapper);

Where WebResponseDeserializer extends com.fasterxml.jackson.databind.JsonDeserializer to provide custom way of unmarshalling of my json object

0

You just need to call setTypeIdPropertyName on your message converter and pass the desired name for message header where message converter will hold the class name of your pojo.

briarheart
  • 1,906
  • 2
  • 19
  • 33