Skip to content

Commit 5666529

Browse files
fix: update async properties handling and improve error messaging (#149)
Co-authored-by: lugomez <[email protected]>
1 parent 86e0663 commit 5666529

File tree

11 files changed

+71
-44
lines changed

11 files changed

+71
-44
lines changed

async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/communications/UnroutableMessageNotifierTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class UnroutableMessageNotifierTest {
4444

4545
@BeforeEach
4646
void setUp() {
47-
// Usar el constructor por defecto y espiar el sink interno
47+
// Use the default constructor and spy on the internal sink
4848
unroutableMessageNotifier = new UnroutableMessageNotifier();
49-
// Inyectar el mock del sink usando un spy para poder verificarlo
49+
// Inject the sink mock using a spy to verify it
5050
try {
5151
java.lang.reflect.Field sinkField = UnroutableMessageNotifier.class.getDeclaredField("sink");
5252
sinkField.setAccessible(true);

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ plugins {
1515
id 'org.sonarqube' version '6.3.1.5724'
1616
id 'org.springframework.boot' version '3.5.5' apply false
1717
id 'io.github.gradle-nexus.publish-plugin' version '2.0.0'
18-
id 'co.com.bancolombia.cleanArchitecture' version '3.25.0'
18+
id 'co.com.bancolombia.cleanArchitecture' version '3.26.1'
1919
}
2020

2121
repositories {

main.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ allprojects {
2222
property 'sonar.organization', 'reactive-commons'
2323
property 'sonar.host.url', 'https://sonarcloud.io'
2424
property "sonar.sources", "src/main"
25-
property "sonar.test", "src/test"
25+
property "sonar.tests", "src/test"
2626
property "sonar.java.binaries", "build/classes"
2727
property "sonar.junit.reportPaths", "build/test-results/test"
2828
property "sonar.java-coveragePlugin", "jacoco"
@@ -86,7 +86,7 @@ subprojects {
8686

8787
dependencyManagement {
8888
imports {
89-
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.4'
89+
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.5'
9090
}
9191
}
9292

starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomain.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ public GenericAsyncPropsDomain(String defaultAppName,
3232
this.asyncPropsClass = asyncPropsClass;
3333
ObjectMapper mapper = new ObjectMapper();
3434
mapper.registerModule(new JavaTimeModule());
35-
this.computeIfAbsent(DEFAULT_DOMAIN, k -> {
36-
T defaultApp = AsyncPropsDomainBuilder.instantiate(asyncPropsClass);
37-
defaultApp.setConnectionProperties(mapper.convertValue(defaultProperties, propsClass));
38-
return defaultApp;
39-
});
35+
36+
if (!this.containsKey(DEFAULT_DOMAIN)) {
37+
throw new InvalidConfigurationException("Required domain '" + DEFAULT_DOMAIN + "' is not configured.");
38+
}
39+
4040
super.forEach((key, value) -> { // To ensure that each domain has an appName
4141
if (value.getAppName() == null) {
4242
if (defaultAppName == null || defaultAppName.isEmpty()) {

starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomainTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ void shouldCreateProps() {
2525
String defaultAppName = "sample";
2626
MyBrokerConnProps defaultMyBrokerProps = new MyBrokerConnProps();
2727
AsyncMyBrokerPropsDomainProperties configured = new AsyncMyBrokerPropsDomainProperties();
28+
configured.put(DEFAULT_DOMAIN, new MyBrokerAsyncProps());
29+
2830
MyBrokerAsyncProps other = new MyBrokerAsyncProps();
2931
other.setAppName(OTHER);
3032
configured.put(OTHER, other);

starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/RabbitMQBrokerProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public void listenQueries(HandlerResolver resolver) {
141141

142142
@Override
143143
public void listenReplies() {
144-
if (props.isListenReplies()) {
144+
if (Boolean.TRUE.equals(props.getListenReplies())) {
145145
final ApplicationReplyListener replyListener = new ApplicationReplyListener(router,
146146
receiver,
147147
props.getBrokerConfigProps().getReplyQueue(),

starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/RabbitMQSetupUtils.java

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.rabbitmq.client.ConnectionFactory;
55
import lombok.AccessLevel;
66
import lombok.NoArgsConstructor;
7-
import lombok.SneakyThrows;
87
import lombok.extern.java.Log;
98
import org.reactivecommons.api.domain.DomainEventBus;
109
import org.reactivecommons.async.commons.DLQDiscardNotifier;
@@ -50,18 +49,21 @@
5049
import java.security.cert.CertificateException;
5150
import java.time.Duration;
5251
import java.util.Arrays;
52+
import java.util.concurrent.ConcurrentHashMap;
53+
import java.util.concurrent.ConcurrentMap;
5354
import java.util.logging.Level;
5455

5556
@Log
5657
@NoArgsConstructor(access = AccessLevel.PRIVATE)
5758
public final class RabbitMQSetupUtils {
58-
private static final String LISTENER_TYPE = "listener";
59-
private static final String TOPOLOGY_TYPE = "topology";
60-
private static final String SENDER_TYPE = "sender";
59+
private static final String SHARED_TYPE = "shared";
6160
private static final String DEFAULT_PROTOCOL;
6261
public static final int START_INTERVAL = 300;
6362
public static final int MAX_BACKOFF_INTERVAL = 3000;
6463

64+
private static final ConcurrentMap<RabbitProperties, ConnectionFactory> FACTORY_CACHE = new ConcurrentHashMap<>();
65+
private static final ConcurrentMap<ConnectionFactory, Mono<Connection>> CONNECTION_CACHE = new ConcurrentHashMap<>();
66+
6567
static {
6668
String protocol = "TLSv1.1";
6769
try {
@@ -78,17 +80,23 @@ public final class RabbitMQSetupUtils {
7880
DEFAULT_PROTOCOL = protocol;
7981
}
8082

81-
@SneakyThrows
8283
public static ConnectionFactoryProvider connectionFactoryProvider(RabbitProperties properties) {
83-
final ConnectionFactory factory = new ConnectionFactory();
84-
PropertyMapper map = PropertyMapper.get();
85-
map.from(properties::determineHost).whenNonNull().to(factory::setHost);
86-
map.from(properties::determinePort).to(factory::setPort);
87-
map.from(properties::determineUsername).whenNonNull().to(factory::setUsername);
88-
map.from(properties::determinePassword).whenNonNull().to(factory::setPassword);
89-
map.from(properties::determineVirtualHost).whenNonNull().to(factory::setVirtualHost);
90-
factory.useNio();
91-
setUpSSL(factory, properties);
84+
final ConnectionFactory factory = FACTORY_CACHE.computeIfAbsent(properties, props -> {
85+
try {
86+
ConnectionFactory newFactory = new ConnectionFactory();
87+
PropertyMapper map = PropertyMapper.get();
88+
map.from(props::determineHost).whenNonNull().to(newFactory::setHost);
89+
map.from(props::determinePort).to(newFactory::setPort);
90+
map.from(props::determineUsername).whenNonNull().to(newFactory::setUsername);
91+
map.from(props::determinePassword).whenNonNull().to(newFactory::setPassword);
92+
map.from(props::determineVirtualHost).whenNonNull().to(newFactory::setVirtualHost);
93+
newFactory.useNio();
94+
setUpSSL(newFactory, props);
95+
return newFactory;
96+
} catch (Exception e) {
97+
throw new RuntimeException("Error creating ConnectionFactory: ", e);
98+
}
99+
});
92100
return () -> factory;
93101
}
94102

@@ -107,7 +115,7 @@ public static ReactiveMessageSender createMessageSender(ConnectionFactoryProvide
107115

108116
public static ReactiveMessageListener createMessageListener(ConnectionFactoryProvider provider, AsyncProps props) {
109117
final Mono<Connection> connection =
110-
createConnectionMono(provider.getConnectionFactory(), props.getAppName(), LISTENER_TYPE);
118+
createConnectionMono(provider.getConnectionFactory(), props.getAppName());
111119
final Receiver receiver = RabbitFlux.createReceiver(new ReceiverOptions().connectionMono(connection));
112120
final Sender sender = RabbitFlux.createSender(new SenderOptions().connectionMono(connection));
113121

@@ -119,8 +127,7 @@ public static ReactiveMessageListener createMessageListener(ConnectionFactoryPro
119127

120128
public static TopologyCreator createTopologyCreator(AsyncProps props) {
121129
ConnectionFactoryProvider provider = connectionFactoryProvider(props.getConnectionProperties());
122-
final Mono<Connection> connection = createConnectionMono(provider.getConnectionFactory(),
123-
props.getAppName(), TOPOLOGY_TYPE);
130+
final Mono<Connection> connection = createConnectionMono(provider.getConnectionFactory(), props.getAppName());
124131
final Sender sender = RabbitFlux.createSender(new SenderOptions().connectionMono(connection));
125132
return new TopologyCreator(sender, props.getQueueType());
126133
}
@@ -134,8 +141,7 @@ public static DiscardNotifier createDiscardNotifier(ReactiveMessageSender sender
134141

135142
private static SenderOptions reactiveCommonsSenderOptions(String appName, ConnectionFactoryProvider provider,
136143
RabbitProperties rabbitProperties) {
137-
final Mono<Connection> senderConnection = createConnectionMono(provider.getConnectionFactory(), appName,
138-
SENDER_TYPE);
144+
final Mono<Connection> senderConnection = createConnectionMono(provider.getConnectionFactory(), appName);
139145
final ChannelPoolOptions channelPoolOptions = new ChannelPoolOptions();
140146
final PropertyMapper map = PropertyMapper.get();
141147

@@ -153,18 +159,20 @@ private static SenderOptions reactiveCommonsSenderOptions(String appName, Connec
153159
.transform(Utils::cache));
154160
}
155161

156-
private static Mono<Connection> createConnectionMono(ConnectionFactory factory, String connectionPrefix,
157-
String connectionType) {
158-
log.info("Creating connection mono to RabbitMQ Broker in host '" + factory.getHost() + "' with " +
159-
"type: " + connectionType);
160-
return Mono.fromCallable(() -> factory.newConnection(connectionPrefix + " " + connectionType))
161-
.doOnError(err ->
162-
log.log(Level.SEVERE, "Error creating connection to RabbitMQ Broker in host '" +
163-
factory.getHost() + "'. Starting retry process...", err)
164-
)
165-
.retryWhen(Retry.backoff(Long.MAX_VALUE, Duration.ofMillis(START_INTERVAL))
166-
.maxBackoff(Duration.ofMillis(MAX_BACKOFF_INTERVAL)))
167-
.cache();
162+
private static Mono<Connection> createConnectionMono(ConnectionFactory factory, String appName) {
163+
return CONNECTION_CACHE.computeIfAbsent(factory, f -> {
164+
log.info("Creating connection mono to RabbitMQ Broker in host '" + f.getHost() + "'");
165+
return Mono.fromCallable(() -> f.newConnection(
166+
appName + "-" + InstanceIdentifier.getInstanceId(SHARED_TYPE, "")
167+
))
168+
.doOnError(err ->
169+
log.log(Level.SEVERE, "Error creating connection to RabbitMQ Broker in host '"
170+
+ f.getHost() + "'. Starting retry process...", err)
171+
)
172+
.retryWhen(Retry.backoff(Long.MAX_VALUE, Duration.ofMillis(START_INTERVAL))
173+
.maxBackoff(Duration.ofMillis(MAX_BACKOFF_INTERVAL)))
174+
.cache();
175+
});
168176
}
169177

170178
// SSL based on RabbitConnectionFactoryBean

starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncProps.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,14 @@ public class AsyncProps extends GenericAsyncProps<RabbitProperties> {
5454
private Integer retryDelay = 1000;
5555

5656
@Builder.Default
57-
private boolean listenReplies = true;
57+
private Boolean listenReplies = null;
58+
59+
public Boolean getListenReplies() {
60+
if (listenReplies == null) {
61+
throw new IllegalArgumentException("The 'listenReplies' property is required, please specify a 'true' or 'false' value.");
62+
}
63+
return listenReplies;
64+
}
5865

5966
@Builder.Default
6067
private Boolean withDLQRetry = false;

starters/async-rabbit-starter/src/test/java/org/reactivecommons/async/rabbit/RabbitMQBrokerProviderTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ void init() {
8080
IBrokerConfigProps configProps = new BrokerConfigProps(props);
8181
props.setBrokerConfigProps(configProps);
8282
props.setAppName("test");
83+
props.setListenReplies(Boolean.TRUE);
8384
brokerProvider = new RabbitMQBrokerProvider(DEFAULT_DOMAIN,
8485
props,
8586
brokerConfig,

starters/async-rabbit-starter/src/test/resources/application.properties

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)