Skip to content
This repository was archived by the owner on Dec 5, 2023. It is now read-only.

Commit 62fa431

Browse files
author
Carlos León
committed
Initial commit
0 parents  commit 62fa431

File tree

9 files changed

+298
-0
lines changed

9 files changed

+298
-0
lines changed

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM java:openjdk-8-alpine
2+
3+
WORKDIR /usr/src/app
4+
COPY ./target/*.jar ./app.jar
5+
6+
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/urandom","-jar","./app.jar", "--port=80"]

pom.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>works.weave.socks</groupId>
8+
<artifactId>queue-master</artifactId>
9+
<packaging>jar</packaging>
10+
11+
<name>queue-master</name>
12+
<description>Shipping queue master for socks eCommerce application
13+
</description>
14+
15+
<parent>
16+
<groupId>works.weave</groupId>
17+
<artifactId>socks</artifactId>
18+
<version>0.0.1-SNAPSHOT</version>
19+
</parent>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>org.springframework.boot</groupId>
24+
<artifactId>spring-boot-starter-amqp</artifactId>
25+
</dependency>
26+
<dependency>
27+
<groupId>com.github.docker-java</groupId>
28+
<artifactId>docker-java</artifactId>
29+
<version>3.0.0</version>
30+
</dependency>
31+
</dependencies>
32+
</project>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package works.weave.socks;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import com.github.dockerjava.api.DockerClient;
7+
import com.github.dockerjava.api.command.CreateContainerResponse;
8+
import com.github.dockerjava.api.model.Network;
9+
import com.github.dockerjava.core.DockerClientBuilder;
10+
import com.github.dockerjava.core.DockerClientConfig;
11+
import com.github.dockerjava.core.command.PullImageResultCallback;
12+
import com.github.dockerjava.core.command.ExecStartResultCallback;
13+
import com.github.dockerjava.api.exception.DockerException;
14+
import org.springframework.stereotype.Component;
15+
16+
import java.lang.Exception;
17+
import java.util.concurrent.ExecutorService;
18+
import java.util.concurrent.Executors;
19+
import java.util.List;
20+
21+
@Component
22+
public class DockerSpawner {
23+
private final Logger logger = LoggerFactory.getLogger(this.getClass());
24+
25+
private DockerClient dc;
26+
private ExecutorService dockerPool;
27+
28+
private String imageName = "weaveworksdemos/worker";
29+
private String imageVersion = "latest";
30+
private String networkId = "weavedemo_backoffice";
31+
private int poolSize = 50;
32+
33+
public void init() {
34+
if (dc == null) {
35+
DockerClientConfig.DockerClientConfigBuilder builder = DockerClientConfig.createDefaultConfigBuilder();
36+
37+
DockerClientConfig config = builder.build();
38+
dc = DockerClientBuilder.getInstance(config).build();
39+
40+
dc.pullImageCmd(imageName).withTag(imageVersion).exec(new PullImageResultCallback()).awaitSuccess();
41+
}
42+
if (dockerPool == null) {
43+
dockerPool = Executors.newFixedThreadPool(poolSize);
44+
}
45+
}
46+
47+
public void spawn() {
48+
dockerPool.execute(new Runnable() {
49+
public void run() {
50+
logger.info("Spawning new container");
51+
try {
52+
CreateContainerResponse container = dc.createContainerCmd(imageName + ":" + imageVersion).withNetworkMode(networkId).withCmd("ping", "rabbitmq").exec();
53+
String containerId = container.getId();
54+
dc.startContainerCmd(containerId).exec();
55+
logger.info("Spawned container with id: " + container.getId() + " on network: " + networkId);
56+
// TODO instead of just sleeping, call await on the container and remove once it's completed.
57+
Thread.sleep(40000);
58+
try {
59+
dc.stopContainerCmd(containerId).exec();
60+
}
61+
catch (DockerException e) {
62+
logger.info("Container already stopped. (This is expected).");
63+
}
64+
dc.removeContainerCmd(containerId).exec();
65+
logger.info("Removed Container:" + containerId);
66+
} catch (Exception e) {
67+
logger.error("Exception trying to launch/remove worker container. " + e);
68+
}
69+
}
70+
});
71+
}
72+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package works.weave.socks;
2+
3+
import org.springframework.amqp.core.Binding;
4+
import org.springframework.amqp.core.BindingBuilder;
5+
import org.springframework.amqp.core.Queue;
6+
import org.springframework.amqp.core.TopicExchange;
7+
import org.springframework.amqp.rabbit.core.RabbitTemplate;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.CommandLineRunner;
10+
import org.springframework.boot.SpringApplication;
11+
import org.springframework.boot.autoconfigure.SpringBootApplication;
12+
import org.springframework.context.annotation.Bean;
13+
14+
@SpringBootApplication
15+
public class QueueMasterApplication implements CommandLineRunner {
16+
17+
final static String queueName = "shipping-task";
18+
19+
@Autowired
20+
RabbitTemplate rabbitTemplate;
21+
22+
public static void main(String[] args) throws InterruptedException {
23+
SpringApplication.run(QueueMasterApplication.class, args);
24+
}
25+
26+
@Bean
27+
Queue queue() {
28+
return new Queue(queueName, false);
29+
}
30+
31+
@Bean
32+
TopicExchange exchange() {
33+
return new TopicExchange("shipping-task-exchange");
34+
}
35+
36+
@Bean
37+
Binding binding(Queue queue, TopicExchange exchange) {
38+
return BindingBuilder.bind(queue).to(exchange).with(queueName);
39+
}
40+
41+
@Override
42+
public void run(String... args) throws Exception {
43+
System.out.println("Starting QueueMasterApplication...");
44+
}
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package works.weave.socks;
2+
3+
import org.springframework.amqp.core.AmqpAdmin;
4+
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
5+
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
6+
import org.springframework.amqp.rabbit.core.RabbitAdmin;
7+
import org.springframework.amqp.support.converter.DefaultClassMapper;
8+
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
9+
import org.springframework.amqp.support.converter.MessageConverter;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
13+
@Configuration
14+
public class RabbitMqConfiguration
15+
{
16+
@Bean
17+
public ConnectionFactory connectionFactory()
18+
{
19+
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("rabbitmq");
20+
// CachingConnectionFactory connectionFactory = new CachingConnectionFactory("192.168.99.104");
21+
connectionFactory.setUsername("guest");
22+
connectionFactory.setPassword("guest");
23+
return connectionFactory;
24+
}
25+
26+
@Bean
27+
public AmqpAdmin amqpAdmin()
28+
{
29+
return new RabbitAdmin(connectionFactory());
30+
}
31+
32+
@Bean
33+
public MessageConverter jsonMessageConverter()
34+
{
35+
final Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
36+
converter.setClassMapper(classMapper());
37+
return converter;
38+
}
39+
40+
@Bean
41+
public DefaultClassMapper classMapper()
42+
{
43+
DefaultClassMapper typeMapper = new DefaultClassMapper();
44+
typeMapper.setDefaultType(Shipment.class);
45+
return typeMapper;
46+
}
47+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package works.weave.socks;
2+
3+
public class Shipment {
4+
private String id;
5+
private String name;
6+
7+
public String getId() {
8+
return id;
9+
}
10+
11+
public void setId(String id) {
12+
this.id = id;
13+
}
14+
15+
public String getName() {
16+
return name;
17+
}
18+
19+
public void setName(String name) {
20+
this.name = name;
21+
}
22+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package works.weave.socks;
2+
3+
import org.springframework.amqp.core.Queue;
4+
import org.springframework.amqp.rabbit.core.RabbitTemplate;
5+
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
6+
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.context.annotation.Bean;
9+
import org.springframework.context.annotation.Configuration;
10+
11+
@Configuration
12+
public class ShippingConsumerConfiguration extends RabbitMqConfiguration
13+
{
14+
protected final String queueName = "shipping-task";
15+
16+
@Autowired
17+
private ShippingTaskHandler shippingTaskHandler;
18+
19+
@Bean
20+
public RabbitTemplate rabbitTemplate() {
21+
RabbitTemplate template = new RabbitTemplate(connectionFactory());
22+
template.setQueue(this.queueName);
23+
template.setMessageConverter(jsonMessageConverter());
24+
return template;
25+
}
26+
27+
@Bean
28+
public Queue queueName() {
29+
return new Queue(this.queueName, false);
30+
}
31+
32+
@Bean
33+
public SimpleMessageListenerContainer listenerContainer() {
34+
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
35+
container.setConnectionFactory(connectionFactory());
36+
container.setQueueNames(this.queueName);
37+
container.setMessageListener(messageListenerAdapter());
38+
39+
return container;
40+
}
41+
42+
@Bean
43+
public MessageListenerAdapter messageListenerAdapter() {
44+
return new MessageListenerAdapter(shippingTaskHandler, jsonMessageConverter());
45+
}
46+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package works.weave.socks;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.stereotype.Component;
5+
6+
@Component
7+
public class ShippingTaskHandler {
8+
9+
@Autowired
10+
DockerSpawner docker;
11+
12+
public void handleMessage(Shipment shipment) {
13+
System.out.println("Received shipment task: " + shipment.getName());
14+
docker.init();
15+
docker.spawn();
16+
}
17+
}

src/main/resources/log4j.properties

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Set root logger level to DEBUG and its only appender to A1.
2+
log4j.rootLogger=WARN, A1
3+
4+
# A1 is set to be a ConsoleAppender.
5+
log4j.appender.A1=org.apache.log4j.ConsoleAppender
6+
7+
# A1 uses PatternLayout.
8+
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
9+
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
10+
11+
log4j.category.org.springframework=INFO

0 commit comments

Comments
 (0)