How do I implement an event listener when the key expires in Spring-Data-Reactive-Redis? - spring-boot

Spring data redis may be implemented as follows.
#Component
class ExpirationListener : MessageListener {
override fun onMessage(message: Message, pattern: ByteArray) {
println("########## onMessage pattern " + String(pattern) + " | " + message.toString())
}
}
#Configuration
class RedisConfig(private val env: Environment) {
#Bean
fun redisConnectionFactory(): RedisConnectionFactory {
val redisHost = env.getProperty("CONF_TRANSACTION_GATEWAY_REDIS_DB_HOST", "localhost")
val redisPort = env.getProperty("CONF_TRANSACTION_GATEWAY_REDIS_DB_PORT", "6379")
return LettuceConnectionFactory(redisHost, redisPort.toInt())
}
#Bean
fun redisTemplate(redisConnectionFactory: RedisConnectionFactory): RedisTemplate<String, String> {
val stringSerializer = StringRedisSerializer()
return RedisTemplate<String, String>()
.apply {
connectionFactory = redisConnectionFactory
keySerializer = stringSerializer
hashKeySerializer = stringSerializer
valueSerializer = stringSerializer
hashValueSerializer = stringSerializer
}
}
#Bean
fun redisMessageListenerContainer(
redisConnectionFactory: RedisConnectionFactory,
expirationListener: ExpirationListener
): RedisMessageListenerContainer {
val redisMessageListenerContainer = RedisMessageListenerContainer()
redisMessageListenerContainer.connectionFactory = redisConnectionFactory
redisMessageListenerContainer.addMessageListener(expirationListener, PatternTopic("__keyevent#*__:expired"))
return redisMessageListenerContainer
}
}
However, I don't know how to implement it with Spring data reactive redis.
In particular, since there is no addMessageListener() function in the RedisMessageListenerContainer, the predefined ExpirationListener could not be used.

Related

Can MockProducer and MockConsumer be used with kafkaTemplate producer

I have a service which using kafkaTemplate to send the kafka message.
#Service
class KafkaProducer(#Autowired val kafkaTemplate: KafkaTemplate<String, String>) {
final fun sendMessage(msg: String) {
val abc = kafkaTemplate.send(AppConstants.TOPIC_NAME, "abc", msg)
abc.whenComplete {
result, ex ->
if (ex != null) {
print("ex occured")
print(ex.message)
} else {
print("sent successfully")
print(result.producerRecord.value())
}
}
}
}
For unit test, I am trying to mock this KafkaProducer.
Can i use MockProducer (import org.apache.kafka.clients.producer.MockProducer) for this?
#Test
fun verify_test() {
val mockProducer = MockProducer(true,StringSerializer(), StringSerializer())
val kafkaProducer = KafkaProducer(mockProducer)
}
On trying the above code, i am getting error bcoz KafkaProducer takes argument as KafkaTemplate object, and I am providing MockProducer.
Here is an example using a mock ProducerFactory...
#SpringJUnitConfig
class So74993413ApplicationTests {
#Test
void test(#Autowired KafkaTemplate<String, String> template,
#Autowired MockProducer<String, String> producer) throws Exception {
CompletableFuture<SendResult<String, String>> future = template.send("foo", "bar");
SendResult<String, String> sendResult = future.get();
// System.out.println(sendResult);
List<ProducerRecord<String, String>> history = producer.history();
assertThat(history).hasSize(1);
ProducerRecord<String, String> record = history.get(0);
assertThat(record.topic()).isEqualTo("foo");
assertThat(record.value()).isEqualTo("bar");
}
#Configuration
public static class Config {
#Bean
MockProducer<String, String> producer() {
return new MockProducer<>(true, new StringSerializer(), new StringSerializer());
}
#Bean
ProducerFactory<String, String> pf (MockProducer producer) {
return new ProducerFactory<>() {
#Override
public Producer<String, String> createProducer() {
return producer;
}
};
}
#Bean
KafkaTemplate<String, String> template(ProducerFactory<String, String> pf) {
return new KafkaTemplate<>(pf);
}
}
}
KafkaTemplate is not a type of Producer. Native Kafka classes cannot be used in place of Spring's - that'd be a reverse dependency.
You would have to mock the template instead since that's what you're actually using. By doing so, it'll bypass any KafkaProducer instance the template used, mock or not.

Spring Batch XML - Kotlin - Message: Content is not allowed in prolog. kotlin

I`m trying to run a simple spring batch job that read xml in kotlin but i got the error :
...
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,1]
Message: Content is not allowed in prolog.
XML Prolog is OK
const val test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root><test>test</test></root>"
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "test")
class Test(
#XmlValue
var test: String = ""
)
#Configuration
#EnableBatchProcessing
class BatchStgCarbPdv(
#Autowired
val jobBuilderFactory: JobBuilderFactory,
#Autowired
val stepBuilderFactory: StepBuilderFactory
) {
I can't find the error in the reader
fun read(): StaxEventItemReader<Test> {
val reader: StaxEventItemReader<Test> = StaxEventItemReader()
println(StandardCharsets.UTF_8.name())
reader.setEncoding(StandardCharsets.UTF_8.name())
reader.setResource(ByteArrayResource(test.encodeToByteArray()))
val unmarshaller = Jaxb2Marshaller()
unmarshaller.setClassesToBeBound(Test::class.java)
reader.setUnmarshaller(unmarshaller)
reader.setFragmentRootElementName("root")
reader.afterPropertiesSet()
return reader
}
Spring batch...
fun processor(): com.gs.ItemProcessor {
return ItemProcessor()
}
fun writer(): ConsoleItemWriter {
return ConsoleItemWriter()
}
#Bean
fun step1(): Step {
return stepBuilderFactory["step1"]
.chunk<Test, Test>(1)
.reader(read())
.processor(processor())
.writer(writer())
.taskExecutor(SimpleAsyncTaskExecutor("spring_batch"))
.build()
}
#Bean
fun importUserJob(step1: Step): Job {
return jobBuilderFactory["importJob"]
.incrementer(RunIdIncrementer())
.flow(step1)
.end()
.build()
}
}
Do nothing
class ItemProcessor : ItemProcessor<Test, Test> {
override fun process(t: Test): Test {
return t
}
}
class ConsoleItemWriter : ItemWriter<Test?> {
override fun write(items: List<Test?>) {
for (test in items) {
println(test)
}
}
}

JwtAuthenticationToken is not in the allowlist, Jackson issue

I have created my authorization server using org.springframework.security:spring-security-oauth2-authorization-server:0.2.2 and my client using org.springframework.boot:spring-boot-starter-oauth2-client. The users are able to sign in and out successfully, however, while testing I noticed that if I log in successfully then restart the client (but not the server) without signing out and try to login in again the server throws the following error in an endless loop of redirects
java.lang.IllegalArgumentException: The class with org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken and name of org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details
I tried to follow this link https://github.com/spring-projects/spring-security/issues/4370 but the solution on it did not work for me. I also tried a different solution described in this link https://github.com/spring-projects/spring-authorization-server/issues/397#issuecomment-900148920 and modified my authorization server code as follows:-
Here is my Jackson Configs
#Configuration
public class JacksonConfiguration {
/**
* Support for Java date and time API.
*
* #return the corresponding Jackson module.
*/
#Bean
public JavaTimeModule javaTimeModule() {
return new JavaTimeModule();
}
#Bean
public Jdk8Module jdk8TimeModule() {
return new Jdk8Module();
}
/*
* Support for Hibernate types in Jackson.
*/
#Bean
public Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
}
/*
* Module for serialization/deserialization of RFC7807 Problem.
*/
#Bean
public ProblemModule problemModule() {
return new ProblemModule();
}
/*
* Module for serialization/deserialization of ConstraintViolationProblem.
*/
#Bean
public ConstraintViolationProblemModule constraintViolationProblemModule() {
return new ConstraintViolationProblemModule();
}
/**
* To (de)serialize a BadCredentialsException, use CoreJackson2Module:
*/
#Bean
public CoreJackson2Module coreJackson2Module() {
return new CoreJackson2Module();
}
#Bean
#Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(coreJackson2Module());
mapper.registerModule(javaTimeModule());
mapper.registerModule(jdk8TimeModule());
mapper.registerModule(hibernate5Module());
mapper.registerModule(problemModule());
mapper.registerModule(constraintViolationProblemModule());
return mapper;
}
}
and here is my Authorization server config
#Configuration(proxyBeanMethods = false)
public class AuthServerConfig {
private final DataSource dataSource;
private final AuthProperties authProps;
private final PasswordEncoder encoder;
public AuthServerConfig(DataSource dataSource, AuthProperties authProps, PasswordEncoder encoder) {
this.dataSource = dataSource;
this.authProps = authProps;
this.encoder = encoder;
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource);
}
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer<>();
authorizationServerConfigurer.tokenRevocationEndpoint(tokenRevocationEndpoint -> tokenRevocationEndpoint
.revocationResponseHandler((request, response, authentication) -> {
Assert.notNull(request, "HttpServletRequest required");
HttpSession session = request.getSession(false);
if (!Objects.isNull(session)) {
session.removeAttribute("SPRING_SECURITY_CONTEXT");
session.invalidate();
}
SecurityContextHolder.getContext().setAuthentication(null);
SecurityContextHolder.clearContext();
response.setStatus(HttpStatus.OK.value());
})
);
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
http
.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest().authenticated())
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
.apply(authorizationServerConfigurer);
return http.formLogin(Customizer.withDefaults()).build();
}
#Bean
public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate, TokenSettings tokenSettings) {
JdbcRegisteredClientRepository clientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
RegisteredClient webClient = RegisteredClient.withId("98a9104c-a9c7-4d7c-ad03-ec61bcfeab36")
.clientId(authProps.getClientId())
.clientName(authProps.getClientName())
.clientSecret(encoder.encode(authProps.getClientSecret()))
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.redirectUri("http://127.0.0.1:8000/login/oauth2/code/web-client")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.tokenSettings(tokenSettings)
.build();
clientRepository.save(webClient);
return clientRepository;
}
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository,
ObjectMapper objectMapper) {
JdbcOAuth2AuthorizationService authorizationService =
new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper = new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
objectMapper.registerModules(SecurityJackson2Modules.getModules(classLoader));
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
// You will need to write the Mixin for your class so Jackson can marshall it.
// objectMapper.addMixIn(UserPrincipal .class, UserPrincipalMixin.class);
rowMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
return authorizationService;
}
#Bean
public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);
}
#Bean
public JWKSource<SecurityContext> jwkSource() {
RSAKey rsaKey = generateRsa();
JWKSet jwkSet = new JWKSet(rsaKey);
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
}
private static RSAKey generateRsa() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
return new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
}
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
#Bean
public ProviderSettings providerSettings() {
return ProviderSettings.builder()
.issuer(authProps.getIssuerUri())
.build();
}
#Bean
public TokenSettings tokenSettings() {
return TokenSettings.builder()
.accessTokenTimeToLive(Duration.ofDays(1))
.refreshTokenTimeToLive(Duration.ofDays(1))
.build();
}
}
But am still facing the same issue.
How do I solve this? Any assistance is highly appreciated.
After trying out different solutions this was how I was able to solve it.
I changed my OAuth2AuthorizationService bean to look like this.
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
JdbcOAuth2AuthorizationService authorizationService =
new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper oAuth2AuthorizationParametersMapper =
new JdbcOAuth2AuthorizationService.OAuth2AuthorizationParametersMapper();
ObjectMapper objectMapper = new ObjectMapper();
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
List<Module> securityModules = SecurityJackson2Modules.getModules(classLoader);
objectMapper.registerModules(securityModules);
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
objectMapper.addMixIn(JwtAuthenticationToken.class, JwtAuthenticationTokenMixin.class);
rowMapper.setObjectMapper(objectMapper);
oAuth2AuthorizationParametersMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
authorizationService.setAuthorizationParametersMapper(oAuth2AuthorizationParametersMapper);
return authorizationService;
}
and here is my JwtAuthenticationTokenMixin configurations
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
#JsonDeserialize(using = JwtAuthenticationTokenDeserializer.class)
#JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
#JsonIgnoreProperties(ignoreUnknown = true)
public abstract class JwtAuthenticationTokenMixin {}
class JwtAuthenticationTokenDeserializer extends JsonDeserializer<JwtAuthenticationToken> {
#Override
public JwtAuthenticationToken deserialize(JsonParser parser, DeserializationContext context) throws IOException {
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
JsonNode root = mapper.readTree(parser);
return deserialize(parser, mapper, root);
}
private JwtAuthenticationToken deserialize(JsonParser parser, ObjectMapper mapper, JsonNode root)
throws JsonParseException {
JsonNode principal = JsonNodeUtils.findObjectNode(root, "principal");
if (!Objects.isNull(principal)) {
String tokenValue = principal.get("tokenValue").textValue();
long issuedAt = principal.get("issuedAt").longValue();
long expiresAt = principal.get("expiresAt").longValue();
Map<String, Object> headers = JsonNodeUtils.findValue(
principal, "headers", JsonNodeUtils.STRING_OBJECT_MAP, mapper);
Map<String, Object> claims = new HashMap<>();
claims.put("claims", principal.get("claims"));
Jwt jwt = new Jwt(tokenValue, Instant.ofEpochMilli(issuedAt), Instant.ofEpochMilli(expiresAt), headers, claims);
return new JwtAuthenticationToken(jwt);
}
return null;
}
}
abstract class JsonNodeUtils {
static final TypeReference<Set<String>> STRING_SET = new TypeReference<Set<String>>() {
};
static final TypeReference<Map<String, Object>> STRING_OBJECT_MAP = new TypeReference<Map<String, Object>>() {
};
static String findStringValue(JsonNode jsonNode, String fieldName) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isTextual()) ? value.asText() : null;
}
static <T> T findValue(JsonNode jsonNode, String fieldName, TypeReference<T> valueTypeReference,
ObjectMapper mapper) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null;
}
static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) {
if (jsonNode == null) {
return null;
}
JsonNode value = jsonNode.findValue(fieldName);
return (value != null && value.isObject()) ? value : null;
}
}
you don't need to create a Mixin, because it's all ready created by authorization springboot module. juste
#Bean
public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
JdbcOAuth2AuthorizationService authorizationService = new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper = new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModules(new CoreJackson2Module());
objectMapper.registerModules(SecurityJackson2Modules.getModules(classLoader));
objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
rowMapper.setObjectMapper(objectMapper);
authorizationService.setAuthorizationRowMapper(rowMapper);
return authorizationService;
}
i think you miss this line and is where the token mixin is registered
objectMapper.registerModules(new CoreJackson2Module());

Spring's #Cacheable unable to cache data - Redis implementation

I am trying to use spring cache abstraction with Redis cache. I am unable to see the values in cache. Please help me if I am missing something in config :
As I am making the call multiple times actual fetch is happening. I tried connecting to same redis host port, I cant find there any keys as well.
PFB the implementation details.
CacheUtils.java :
#Slf4j
public class CacheUtils {
private final CustomerManagementClient customerManagementClient;
#Autowired
public CacheUtils(CustomerManagementClient customerManagementClient) {
this.customerManagementClient = customerManagementClient;
}
#Cacheable(value = "merchant-details", key = "#merchantEntityId")
public MerchantDetails getOrFetchMerchantDetails(OrderItemStatusChangeEvent event, MerchantType merchantType, String merchantEntityId) {
if (BUYER == merchantType) {
log.info("test - get buyer details");
CustomerDetails customerDetails =
customerManagementClient.getData(merchantEntityId);
String businessId = customerDetails.getBusinessId();
String phoneNumber = customerDetails.getPhoneNumber();
return MerchantDetails
.builder()
.merchantEntityId(merchantEntityId)
.businessId(businessId)
.businessName(customerDetails.getBusinessName())
.merchantType(merchantType)
.contactNumber(phoneNumber)
.build();
}
throw new InvalidInputException();
}
}
MainClass.java
#Slf4j
#Component
public class MainClass implements LogisticsPlanningService {
private final CacheUtils cacheUtils;
#Autowired
public LogisticsPlanningServiceImpl(CacheUtils cacheUtils) {
this.cacheUtils = cacheUtils;
}
private Set<LogisticsPlanningRequest> testMethod(Event event) {
MerchantDetails senderDetails = cacheUtils.getOrFetchMerchantDetails(event, SELLER, orderItem.getSellerId());
MerchantDetails receiverDetails = cacheUtils.getOrFetchMerchantDetails(event, BUYER, orderItem.getBuyerId());
}
}
RedisConfiguration.java
#Configuration
#EnableCaching
public class RedisConfiguration {
private String hostName;
private int port;
#Autowired
MarketPlaceServiceProperties properties;
#PostConstruct
public void init() {
hostName = properties.getRedisHostName();
port = Integer.parseInt(properties.getRedisPort());
}
#Bean
protected JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(hostName, port);
JedisConnectionFactory factory = new JedisConnectionFactory(configuration);
factory.afterPropertiesSet();
return factory;
}
public RedisCacheConfiguration getTestCacheConfig() {
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
cacheConfiguration.prefixCacheNameWith("marketplace");
cacheConfiguration.disableCachingNullValues();
return cacheConfiguration;
}
// #Bean
// public RedisTemplate<String, Object> redisTemplate() {
// final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// redisTemplate.setKeySerializer(new StringRedisSerializer());
// redisTemplate.setHashKeySerializer(new GenericToStringSerializer<>(Object.class));
// redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
// redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
// redisTemplate.setConnectionFactory(jedisConnectionFactory());
// return redisTemplate;
// }
}
service.properties :
redisHostName: redis.domain.prod.xyz.com
redisPort: 5400

Spring-boot 2 rabbitmq MessageConverter not working as excepted

I am using the springboot and rabitmq. I have kind of similar scenario here.
I would like to map my message to custom java object
I also want pass delivery tag which is message proprieties
I wann to pass Channel as well beacuse I need to manual ack messages
My code is like this
#RunWith(SpringRunner.class)
public class EPPQ2SubscriberTest {
#Autowired
private RabbitListenerEndpointRegistry registry;
public final String sampleMessage = "{" + "\"header\": {" + "\"RETRY_COUNT\":0," + "\"PUBLISH_EVENT_TYPE\":\"AUTH\""
+ "}," + "\"payLoad\":{" + "\"MTI\": \"120\"," + "\"MTI_REQUEST\": \"120\","
+ "\"PAN\": \"6011000000000000\"" + "}" + "}";
#Test
public void message_converter_test() throws Exception {
SimpleMessageListenerContainer container = (SimpleMessageListenerContainer) this.registry
.getListenerContainer("messageListener");
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
Message message = MessageBuilder.withBody(sampleMessage.getBytes())
.andProperties(MessagePropertiesBuilder.newInstance().setContentType("application/json").build())
.build();
listener.onMessage(message, mock(Channel.class));
}
#Configuration
#EnableRabbit
public static class config {
#Bean
public ConnectionFactory mockConnectionFactory() {
return mock(ConnectionFactory.class);
}
#Bean
public MessageConverter messageConverter() {
Jackson2JsonMessageConverter messageConverter = new Jackson2JsonMessageConverter();
/*
* DefaultClassMapper classMapper = new DefaultClassMapper();
* classMapper.setDefaultType(com.discover.dftp.scrubber.domain.Message.class);
* messageConverter.setClassMapper(classMapper);
*/
return messageConverter;
}
#Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(mockConnectionFactory());
factory.setMessageConverter(messageConverter());
factory.setAutoStartup(false);
return factory;
}
#Bean
public EPPQ2Subscriber messageListener() {
return new EPPQ2Subscriber();
}
}
}
#Component
public class EPPQ2Subscriber {
private static final Logger LOGGER = LoggerFactory.getLogger(EPPQ2Subscriber.class);
// #RabbitListener(queues = "#{queue.getName()}") #TODO I wann to use this in
// later point in time.. !
#RabbitListener(id = "messageListener", queues = "TestQueue")
public void receiveMessage(Message message, Channel channel/* ,#Header(AmqpHeaders.DELIVERY_TAG) long tag */) {
LOGGER.info("Method receiveMessage invoked");
message.getMessageProperties().getDeliveryTag();
LOGGER.info("Result:" + message.getClass() + ":" + message.toString());
}
}
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private Map<String, Object> header;
private Map<String, Object> payLoad;
public Map<String, Object> getHeader() {
return header;
}
public void setHeader(Map<String, Object> header) {
this.header = header;
}
public Map<String, Object> getPayLoad() {
return payLoad;
}
public void setPayLoad(Map<String, Object> payLoad) {
this.payLoad = payLoad;
}
#Override
public String toString() {
return "Header [header=" + this.header + ", payLoad=" + this.payLoad + "]";
}
}
#RabbitListener(id = "messageListener", queues = "TestQueue")
public void receiveMessage(Message message, Channel channel/* ,#Header(AmqpHeaders.DELIVERY_TAG) long tag */) {
LOGGER.info("Method receiveMessage invoked");
message.getMessageProperties().getDeliveryTag();
LOGGER.info("Result:" + message.getClass() + ":" + message.toString());
}
I looks like that method receives the raw (unconverted) Spring AMQP Message (you are importing the wrong Message class in EPPQ2Subscriber).

Resources