Skip to content

Commit 311fa62

Browse files
committed
Polish "Add service connection for Testcontainers ActiveMQ"
This also adds support for Docker Compose. See gh-35080
1 parent 63121dd commit 311fa62

File tree

11 files changed

+277
-16
lines changed

11 files changed

+277
-16
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/activemq/ActiveMQConnectionDetails.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,27 @@
2222
* Details required to establish a connection to an ActiveMQ service.
2323
*
2424
* @author Eddú Meléndez
25-
* @since 3.1.0
25+
* @author Stephane Nicoll
26+
* @since 3.2.0
2627
*/
2728
public interface ActiveMQConnectionDetails extends ConnectionDetails {
2829

30+
/**
31+
* Broker URL to use.
32+
* @return the url of the broker
33+
*/
2934
String getBrokerUrl();
3035

36+
/**
37+
* Login user to authenticate to the broker.
38+
* @return the login user to authenticate to the broker or {@code null}
39+
*/
3140
String getUser();
3241

42+
/**
43+
* Login to authenticate against the broker.
44+
* @return the login to authenticate against the broker or {@code null}
45+
*/
3346
String getPassword();
3447

3548
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.activemq;
18+
19+
import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;
20+
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
21+
import org.springframework.boot.docker.compose.core.RunningService;
22+
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
23+
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
24+
25+
/**
26+
* {@link DockerComposeConnectionDetailsFactory} to create
27+
* {@link ActiveMQConnectionDetails} for an {@code activemq} service.
28+
*
29+
* @author Stephane Nicoll
30+
*/
31+
class ActiveMQDockerComposeConnectionDetailsFactory
32+
extends DockerComposeConnectionDetailsFactory<ActiveMQConnectionDetails> {
33+
34+
private static final int ACTIVEMQ_PORT = 61616;
35+
36+
protected ActiveMQDockerComposeConnectionDetailsFactory() {
37+
super("symptoma/activemq");
38+
}
39+
40+
@Override
41+
protected ActiveMQConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) {
42+
return new ActiveMQDockerComposeConnectionDetails(source.getRunningService());
43+
}
44+
45+
/**
46+
* {@link RabbitConnectionDetails} backed by a {@code rabbitmq}
47+
* {@link RunningService}.
48+
*/
49+
static class ActiveMQDockerComposeConnectionDetails extends DockerComposeConnectionDetails
50+
implements ActiveMQConnectionDetails {
51+
52+
private final ActiveMQEnvironment environment;
53+
54+
private final String brokerUrl;
55+
56+
protected ActiveMQDockerComposeConnectionDetails(RunningService service) {
57+
super(service);
58+
this.environment = new ActiveMQEnvironment(service.env());
59+
this.brokerUrl = "tcp://" + service.host() + ":" + service.ports().get(ACTIVEMQ_PORT);
60+
}
61+
62+
@Override
63+
public String getBrokerUrl() {
64+
return this.brokerUrl;
65+
}
66+
67+
@Override
68+
public String getUser() {
69+
return this.environment.getUser();
70+
}
71+
72+
@Override
73+
public String getPassword() {
74+
return this.environment.getPassword();
75+
}
76+
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.activemq;
18+
19+
import java.util.Map;
20+
21+
/**
22+
* ActiveMQ environment details.
23+
*
24+
* @author Stephane Nicoll
25+
*/
26+
class ActiveMQEnvironment {
27+
28+
private final String user;
29+
30+
private final String password;
31+
32+
ActiveMQEnvironment(Map<String, String> env) {
33+
this.user = env.get("ACTIVEMQ_USERNAME");
34+
this.password = env.get("ACTIVEMQ_PASSWORD");
35+
}
36+
37+
String getUser() {
38+
return this.user;
39+
}
40+
41+
String getPassword() {
42+
return this.password;
43+
}
44+
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Auto-configuration for docker compose ActiveMQ service connections.
19+
*/
20+
package org.springframework.boot.docker.compose.service.connection.activemq;

spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ org.springframework.boot.docker.compose.service.connection.DockerComposeServiceC
55

66
# Connection Details Factories
77
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
8+
org.springframework.boot.docker.compose.service.connection.activemq.ActiveMQDockerComposeConnectionDetailsFactory,\
89
org.springframework.boot.docker.compose.service.connection.cassandra.CassandraDockerComposeConnectionDetailsFactory,\
910
org.springframework.boot.docker.compose.service.connection.elasticsearch.ElasticsearchDockerComposeConnectionDetailsFactory,\
1011
org.springframework.boot.docker.compose.service.connection.flyway.JdbcAdaptingFlywayConnectionDetailsFactory,\
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.activemq;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
22+
import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests;
23+
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
26+
/**
27+
* Integration tests for {@link ActiveMQDockerComposeConnectionDetailsFactory}.
28+
*
29+
* @author Stephane Nicoll
30+
*/
31+
class ActiveMQDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests {
32+
33+
ActiveMQDockerComposeConnectionDetailsFactoryIntegrationTests() {
34+
super("activemq-compose.yaml");
35+
}
36+
37+
@Test
38+
void runCreatesConnectionDetails() {
39+
ActiveMQConnectionDetails connectionDetails = run(ActiveMQConnectionDetails.class);
40+
assertThat(connectionDetails.getBrokerUrl()).isNotNull().startsWith("tcp://");
41+
assertThat(connectionDetails.getUser()).isEqualTo("root");
42+
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
43+
}
44+
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.docker.compose.service.connection.activemq;
18+
19+
import java.util.Collections;
20+
import java.util.Map;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
26+
/**
27+
* Tests for {@link ActiveMQEnvironment}.
28+
*
29+
* @author Stephane Nicoll
30+
*/
31+
class ActiveMQEnvironmentTests {
32+
33+
@Test
34+
void getUserWhenHasNoActiveMqUser() {
35+
ActiveMQEnvironment environment = new ActiveMQEnvironment(Collections.emptyMap());
36+
assertThat(environment.getUser()).isNull();
37+
}
38+
39+
@Test
40+
void getUserWhenHasActiveMqUser() {
41+
ActiveMQEnvironment environment = new ActiveMQEnvironment(Map.of("ACTIVEMQ_USERNAME", "me"));
42+
assertThat(environment.getUser()).isEqualTo("me");
43+
}
44+
45+
@Test
46+
void getPasswordWhenHasNoActiveMqPassword() {
47+
ActiveMQEnvironment environment = new ActiveMQEnvironment(Collections.emptyMap());
48+
assertThat(environment.getPassword()).isNull();
49+
}
50+
51+
@Test
52+
void getPasswordWhenHasActiveMqPassword() {
53+
ActiveMQEnvironment environment = new ActiveMQEnvironment(Map.of("ACTIVEMQ_PASSWORD", "secret"));
54+
assertThat(environment.getPassword()).isEqualTo("secret");
55+
}
56+
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
services:
2+
activemq:
3+
image: 'symptoma/activemq:5.18.0'
4+
ports:
5+
- '61616'
6+
environment:
7+
ACTIVEMQ_USERNAME: 'root'
8+
ACTIVEMQ_PASSWORD: 'secret'

spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ The following service connections are currently supported:
5858
|===
5959
| Connection Details | Matched on
6060

61+
| `ActiveMQConnectionDetails`
62+
| Containers named "symptoma/activemq"
63+
6164
| `CassandraConnectionDetails`
6265
| Containers named "cassandra"
6366

spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/activemq/ActiveMQContainerConnectionDetailsFactory.java

+5-14
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
package org.springframework.boot.testcontainers.service.connection.activemq;
1818

19-
import java.util.Map;
20-
2119
import org.testcontainers.containers.Container;
2220
import org.testcontainers.containers.GenericContainer;
2321

@@ -34,7 +32,7 @@
3432
* @author Eddú Meléndez
3533
*/
3634
class ActiveMQContainerConnectionDetailsFactory
37-
extends ContainerConnectionDetailsFactory<ActiveMQConnectionDetails, Container<?>> {
35+
extends ContainerConnectionDetailsFactory<Container<?>, ActiveMQConnectionDetails> {
3836

3937
ActiveMQContainerConnectionDetailsFactory() {
4038
super("symptoma/activemq");
@@ -45,33 +43,26 @@ protected ActiveMQConnectionDetails getContainerConnectionDetails(ContainerConne
4543
return new ActiveMQContainerConnectionDetails(source);
4644
}
4745

48-
private static final class ActiveMQContainerConnectionDetails extends ContainerConnectionDetails
46+
private static final class ActiveMQContainerConnectionDetails extends ContainerConnectionDetails<Container<?>>
4947
implements ActiveMQConnectionDetails {
5048

51-
private final String brokerUrl;
52-
53-
private final Map<String, String> envVars;
54-
5549
private ActiveMQContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
5650
super(source);
57-
this.brokerUrl = "tcp://" + source.getContainer().getHost() + ":"
58-
+ source.getContainer().getFirstMappedPort();
59-
this.envVars = source.getContainer().getEnvMap();
6051
}
6152

6253
@Override
6354
public String getBrokerUrl() {
64-
return this.brokerUrl;
55+
return "tcp://" + getContainer().getHost() + ":" + getContainer().getFirstMappedPort();
6556
}
6657

6758
@Override
6859
public String getUser() {
69-
return this.envVars.get("ACTIVEMQ_USERNAME");
60+
return getContainer().getEnvMap().get("ACTIVEMQ_USERNAME");
7061
}
7162

7263
@Override
7364
public String getPassword() {
74-
return this.envVars.get("ACTIVEMQ_PASSWORD");
65+
return getContainer().getEnvMap().get("ACTIVEMQ_PASSWORD");
7566
}
7667

7768
}

spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-activemq/build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ dependencies {
99
implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-activemq"))
1010

1111
testImplementation("org.awaitility:awaitility")
12-
testImplementation("org.testcontainers:testcontainers")
1312
testImplementation("org.testcontainers:junit-jupiter")
1413
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
1514
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))

0 commit comments

Comments
 (0)