Spring mappingjackson2messageconverter выдает исключение нулевого указателя
Я пытаюсь преобразовать объект Java в формат JSON с помощью mappingjackson2messageconvertor
но похоже, что он не конвертируется в объект json, а выдает ошибку исключения нулевой точки. Интересно, что я делаю не так.
Я проверил один из примеров здесь. Но я не использую rabbitmq вместо activemq.
источник
@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);
}
}
ошибка
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)
4 ответа
С JMS-конвертером вы должны указать конвертеру, какой тип (id) вы хотите создать из JSON.
Вы делаете это, сообщая ему, какое свойство JMS (заголовок) содержит идентификатор типа).
Тогда есть Map
от идентификаторов типов к именам классов.
Или вы можете подкласс и переопределить getJavaTypeForMessage()
,
См. Javadoc для метода getJavaTypeForMessage()
на конвертере.
Я сделал, как указал Гари Рассел, из моего класса призвания
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);
Затем я переопределил методы MappingJackson2MessageConverter:
@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);
}
}
}
Вам просто нужно позвонить setTypeIdPropertyName
в конвертере сообщений и передайте желаемое имя для заголовка сообщения, где конвертер сообщений будет содержать имя класса вашего pojo.
Я создал свой собственный десериализатор и установил то же самое в своем объекте MappingJackson2MessageConverter, как показано ниже
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(WebResponse.class,new WebResponseDeserializer());
mapper.registerModule(module);
new MappingJackson2MessageConverter().setObjectMapper(mapper);
Где WebResponseDeserializer расширяет com.fasterxml.jackson.databind.JsonDeserializer для предоставления пользовательского способа демаршалинга моего объекта json