Skip to content

Commit

Permalink
Merge pull request #39363 from eddumelendez
Browse files Browse the repository at this point in the history
* pr/39363:
  Add service connection for Docker Compose and Testcontainers ActiveMQ

Closes gh-39363
  • Loading branch information
mhalbritter committed Feb 2, 2024
2 parents f936356 + f3e7325 commit 550651f
Show file tree
Hide file tree
Showing 14 changed files with 416 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.docker.compose.service.connection.activemq;

import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
import org.springframework.boot.docker.compose.core.RunningService;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;

/**
* {@link DockerComposeConnectionDetailsFactory} to create
* {@link ActiveMQConnectionDetails} for an {@code activemq} service.
*
* @author Stephane Nicoll
* @author Eddú Meléndez
*/
class ActiveMQClassicDockerComposeConnectionDetailsFactory
extends DockerComposeConnectionDetailsFactory<ActiveMQConnectionDetails> {

private static final int ACTIVEMQ_PORT = 61616;

protected ActiveMQClassicDockerComposeConnectionDetailsFactory() {
super("apache/activemq-classic");
}

@Override
protected ActiveMQConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) {
return new ActiveMQDockerComposeConnectionDetails(source.getRunningService());
}

/**
* {@link ActiveMQConnectionDetails} backed by a {@code activemq}
* {@link RunningService}.
*/
static class ActiveMQDockerComposeConnectionDetails extends DockerComposeConnectionDetails
implements ActiveMQConnectionDetails {

private final ActiveMQClassicEnvironment environment;

private final String brokerUrl;

protected ActiveMQDockerComposeConnectionDetails(RunningService service) {
super(service);
this.environment = new ActiveMQClassicEnvironment(service.env());
this.brokerUrl = "tcp://" + service.host() + ":" + service.ports().get(ACTIVEMQ_PORT);
}

@Override
public String getBrokerUrl() {
return this.brokerUrl;
}

@Override
public String getUser() {
return this.environment.getUser();
}

@Override
public String getPassword() {
return this.environment.getPassword();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.docker.compose.service.connection.activemq;

import java.util.Map;

/**
* ActiveMQ environment details.
*
* @author Stephane Nicoll
* @author Eddú Meléndez
*/
class ActiveMQClassicEnvironment {

private final String user;

private final String password;

ActiveMQClassicEnvironment(Map<String, String> env) {
this.user = env.get("ACTIVEMQ_CONNECTION_USER");
this.password = env.get("ACTIVEMQ_CONNECTION_PASSWORD");
}

String getUser() {
return this.user;
}

String getPassword() {
return this.password;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ org.springframework.boot.docker.compose.service.connection.DockerComposeServiceC

# Connection Details Factories
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
org.springframework.boot.docker.compose.service.connection.activemq.ActiveMQClassicDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.activemq.ActiveMQDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.activemq.ArtemisDockerComposeConnectionDetailsFactory,\
org.springframework.boot.docker.compose.service.connection.cassandra.CassandraDockerComposeConnectionDetailsFactory,\
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.docker.compose.service.connection.activemq;

import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests;
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Integration tests for {@link ActiveMQClassicDockerComposeConnectionDetailsFactory}.
*
* @author Stephane Nicoll
* @author Eddú Meléndez
*/
class ActiveMQClassicDockerComposeConnectionDetailsFactoryIntegrationTests
extends AbstractDockerComposeIntegrationTests {

ActiveMQClassicDockerComposeConnectionDetailsFactoryIntegrationTests() {
super("activemq-classic-compose.yaml", DockerImageNames.activeMqClassic());
}

@Test
void runCreatesConnectionDetails() {
ActiveMQConnectionDetails connectionDetails = run(ActiveMQConnectionDetails.class);
assertThat(connectionDetails.getBrokerUrl()).isNotNull().startsWith("tcp://");
assertThat(connectionDetails.getUser()).isEqualTo("root");
assertThat(connectionDetails.getPassword()).isEqualTo("secret");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.docker.compose.service.connection.activemq;

import java.util.Collections;
import java.util.Map;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link ActiveMQClassicEnvironment}.
*
* @author Stephane Nicoll
* @author Eddú Meléndez
*/
class ActiveMQClassicEnvironmentTests {

@Test
void getUserWhenHasNoActiveMqUser() {
ActiveMQClassicEnvironment environment = new ActiveMQClassicEnvironment(Collections.emptyMap());
assertThat(environment.getUser()).isNull();
}

@Test
void getUserWhenHasActiveMqUser() {
ActiveMQClassicEnvironment environment = new ActiveMQClassicEnvironment(
Map.of("ACTIVEMQ_CONNECTION_USER", "me"));
assertThat(environment.getUser()).isEqualTo("me");
}

@Test
void getPasswordWhenHasNoActiveMqPassword() {
ActiveMQClassicEnvironment environment = new ActiveMQClassicEnvironment(Collections.emptyMap());
assertThat(environment.getPassword()).isNull();
}

@Test
void getPasswordWhenHasActiveMqPassword() {
ActiveMQClassicEnvironment environment = new ActiveMQClassicEnvironment(
Map.of("ACTIVEMQ_CONNECTION_PASSWORD", "secret"));
assertThat(environment.getPassword()).isEqualTo("secret");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
services:
activemq:
image: '{imageName}'
ports:
- '61616'
environment:
ACTIVEMQ_CONNECTION_USER: 'root'
ACTIVEMQ_CONNECTION_PASSWORD: 'secret'
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ The following service connections are currently supported:
| Connection Details | Matched on

| `ActiveMQConnectionDetails`
| Containers named "symptoma/activemq"
| Containers named "symptoma/activemq", "apache/activemq-classic"

| `ArtemisConnectionDetails`
| Containers named "apache/activemq-artemis"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,7 @@ The following service connection factories are provided in the `spring-boot-test
| Connection Details | Matched on

| `ActiveMQConnectionDetails`
| Containers named "symptoma/activemq"
| Containers named "symptoma/activemq" or `ActiveMQContainer`

| `ArtemisConnectionDetails`
| Containers of type `ArtemisContainer`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import org.testcontainers.activemq.ActiveMQContainer;

import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;

/**
* {@link ContainerConnectionDetailsFactory} to create {@link ActiveMQConnectionDetails} *
* from a {@link ServiceConnection @ServiceConnection}-annotated
* {@link ActiveMQContainer}.
*
* @author Eddú Meléndez
*/
class ActiveMQClassicContainerConnectionDetailsFactory
extends ContainerConnectionDetailsFactory<ActiveMQContainer, ActiveMQConnectionDetails> {

@Override
protected ActiveMQConnectionDetails getContainerConnectionDetails(
ContainerConnectionSource<ActiveMQContainer> source) {
return new ActiveMQContainerConnectionDetails(source);
}

private static final class ActiveMQContainerConnectionDetails extends ContainerConnectionDetails<ActiveMQContainer>
implements ActiveMQConnectionDetails {

private ActiveMQContainerConnectionDetails(ContainerConnectionSource<ActiveMQContainer> source) {
super(source);
}

@Override
public String getBrokerUrl() {
return getContainer().getBrokerUrl();
}

@Override
public String getUser() {
return getContainer().getUser();
}

@Override
public String getPassword() {
return getContainer().getPassword();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ org.springframework.boot.testcontainers.service.connection.ServiceConnectionCont

# Connection Details Factories
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
org.springframework.boot.testcontainers.service.connection.activemq.ActiveMQClassicContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.activemq.ActiveMQContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.activemq.ArtemisContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.amqp.RabbitContainerConnectionDetailsFactory,\
Expand Down
Loading

0 comments on commit 550651f

Please sign in to comment.