Хорошо, и вот очень хакерский, не рекомендуемый подход, который сработал. Он довольно запутанный и хрупкий, я не собираюсь его использовать, но просто для иллюстрации вот что нужно, чтобы зарегистрировать пользовательский конвертер для преобразования @Header jms.
Здесь я передаю user_email в заголовок сообщения jms и хотел, чтобы Spring автоматически преобразовал id / email в фактический объект домена User. У меня уже был работающий конвертер, который хорошо работает в режиме mvc / http.
public class StringToUserConverter implements Converter<String,User>{
@Autowired
UserDAO userDAO;
public User convert(String email) {
return userDAO.getByEmail(email);
}
}
Вышеуказанная часть довольно стандартная и прямолинейная. Вот идиотская запутанная часть. Я прошелся по коду инициализации слушателя пружинного jms и нашел самое низкое место, где я мог бы подключить свой собственный конвертер для jms @ Header.
Я создал сервис, который будет @Autowire один из бинов Jms пружин, а затем установит для него пользовательский сервис конвертации, используя @PostConstruct. Даже здесь некоторые свойства были частными, поэтому мне пришлось использовать отражение, чтобы прочитать их
@Service
public class JmsCustomeConverterSetter {
@Autowired
StringToUserConverter stringToUserConverter;
@Autowired
JmsListenerAnnotationBeanPostProcessor jmsPostProcessor;
@PostConstruct
public void attachCustomConverters() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
//create custom converter service that includes my custom converter
GenericConversionService converterService = new GenericConversionService();
converterService.addConverter(stringToUserConverter); //add custom converter, could add multiple here
DefaultConversionService.addDefaultConverters(converterService); //attach some default converters
//reflection to read the private field so i can use it later
Field field = jmsPostProcessor.getClass().getDeclaredField("beanFactory"); //NoSuchFieldException
field.setAccessible(true);
BeanFactory beanFactory = (BeanFactory) field.get(jmsPostProcessor); //IllegalAccessException
DefaultMessageHandlerMethodFactory f = new DefaultMessageHandlerMethodFactory();
f.setConversionService(converterService);
f.setBeanFactory(beanFactory); //set bean factory read using reflection
f.afterPropertiesSet();
jmsPostProcessor.setMessageHandlerMethodFactory(f);
}
}
Создание DefaultMessageHandlerMethodFactory было основано на коде, который я видел в org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory.
Я бы определенно не рекомендовал использовать это в производстве. Он довольно хрупкий и излишне сложный.
Весна ... иногда это глоток свежего воздуха ... а иногда это извилистая хлопка-ловушка