Skip to content

Commit 201765e

Browse files
author
Erlend Viddal
committed
Refactoring. Hk2 is my bitch.
1 parent 393397c commit 201765e

File tree

6 files changed

+120
-96
lines changed

6 files changed

+120
-96
lines changed

servicebuilder-mq-activemq/src/main/java/no/obos/util/servicebuilder/addon/ActiveMqAddon.java

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package no.obos.util.servicebuilder.addon;
22

3+
import com.google.common.collect.ImmutableMap;
34
import com.google.common.collect.ImmutableSet;
45
import lombok.AccessLevel;
56
import lombok.AllArgsConstructor;
@@ -12,21 +13,18 @@
1213
import no.obos.util.servicebuilder.model.Addon;
1314
import no.obos.util.servicebuilder.model.PropertyProvider;
1415
import no.obos.util.servicebuilder.model.ServiceDefinition;
15-
import no.obos.util.servicebuilder.mq.HandlerDescription;
16-
import no.obos.util.servicebuilder.mq.MessageHandler;
17-
import no.obos.util.servicebuilder.mq.MqHandlerImpl;
16+
import no.obos.util.servicebuilder.mq.MqListener;
17+
import no.obos.util.servicebuilder.mq.MqSender;
1818
import no.obos.util.servicebuilder.mq.MqSenderImpl;
1919
import no.obos.util.servicebuilder.mq.SenderDescription;
2020
import no.obos.util.servicebuilder.mq.activemq.ActiveMqConnectionProvider;
2121
import no.obos.util.servicebuilder.mq.activemq.ActiveMqListener;
2222
import no.obos.util.servicebuilder.mq.activemq.ActiveMqSender;
23-
import no.obos.util.servicebuilder.util.GuavaHelper;
24-
import org.glassfish.hk2.api.ServiceLocator;
23+
import org.glassfish.hk2.api.TypeLiteral;
2524

26-
import javax.inject.Inject;
27-
import javax.ws.rs.core.Feature;
28-
import javax.ws.rs.core.FeatureContext;
25+
import java.util.Map;
2926
import java.util.Set;
27+
import java.util.stream.Collectors;
3028

3129
/**
3230
* ActiveMQ backend for MqAddon
@@ -94,18 +92,19 @@ public void addToJerseyConfig(JerseyConfig serviceConfig) {
9492
ActiveMqSender activeMqSender = new ActiveMqSender(this.connectionProvider);
9593
serviceConfig.addBinder((binder) -> {
9694
binder.bind(this.connectionProvider).to(ActiveMqConnectionProvider.class);
97-
binder.bind(this.listener).to(ActiveMqListener.class);
98-
99-
mqAddon.senders.forEach(senderDescription -> {
100-
MqSenderImpl<?> mqSenderImpl = getMqSender(activeMqSender, senderDescription);
101-
binder.bind(mqSenderImpl).to(senderDescription.typeLiteral);
102-
});
95+
binder.bind(this.listener).to(MqListener.class);
96+
97+
ImmutableMap<String, MqSender> senderMap = ImmutableMap.copyOf(
98+
mqAddon.senders.stream()
99+
.collect(Collectors.toMap(
100+
sd -> sd.messageDescription.MessageType.getName(),
101+
sd -> getMqSender(activeMqSender, sd)
102+
))
103+
);
104+
binder.bind(senderMap).to(new TypeLiteral<Map<String, MqSender>>() {});
103105
});
104106

105-
// Feature is used to start the listeners immediately once dependencies are bound
106-
serviceConfig.addRegistations(registrator -> registrator
107-
.register(StartListenersFeature.class)
108-
);
107+
109108
}
110109

111110
private <T> MqSenderImpl<T> getMqSender(ActiveMqSender activeMqSender, SenderDescription<T> senderDescription) {
@@ -153,31 +152,7 @@ public Addon withProperties(PropertyProvider properties) {
153152
}
154153
}
155154

156-
private static class StartListenersFeature implements Feature {
157-
@Inject
158-
private ServiceLocator serviceLocator;
159-
160-
@Override
161-
public boolean configure(FeatureContext context) {
162-
// Iterates through all configurations, which contains the names of the listeners and handlers
163-
ActiveMqListener listener = serviceLocator.getService(ActiveMqListener.class);
164-
MqAddon mqAddon = serviceLocator.getService(MqAddon.class);
165-
ImmutableSet<MqHandlerImpl<?>> handlers = mqAddon.handlers.stream()
166-
.map(this::getHandlerImpl)
167-
.collect(GuavaHelper.setCollector());
168-
listener.startListener(handlers);
169-
return true;
170-
}
171155

172-
private <T> MqHandlerImpl<T> getHandlerImpl(HandlerDescription<T> handlerDescription) {
173-
MessageHandler<T> service = serviceLocator.getService(handlerDescription.messageHandlerClass);
174-
return MqHandlerImpl.<T>builder()
175-
.handlerDescription(handlerDescription)
176-
.messageHandler(service)
177-
.build();
178-
}
179-
180-
}
181156

182157
public ActiveMqAddon url(String url) {return withUrl(url);}
183158

servicebuilder-mq-activemq/src/main/java/no/obos/util/servicebuilder/mq/activemq/ActiveMqListener.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import no.obos.util.servicebuilder.mq.HandlerDescription;
88
import no.obos.util.servicebuilder.mq.MqHandlerForwarder;
99
import no.obos.util.servicebuilder.mq.MqHandlerImpl;
10+
import no.obos.util.servicebuilder.mq.MqListener;
1011

1112
import javax.jms.Connection;
1213
import javax.jms.JMSException;
@@ -17,7 +18,7 @@
1718
*/
1819
@Slf4j
1920
@Builder
20-
public class ActiveMqListener {
21+
public class ActiveMqListener implements MqListener {
2122
private final ActiveMqConnectionProvider activeMqConnectionProvider;
2223

2324
private final ImmutableSet<HandlerDescription<?>> handlerDescriptions;
@@ -31,7 +32,13 @@ public class ActiveMqListener {
3132
private Connection connection = null;
3233
private Session session = null;
3334

34-
public void startListener(ImmutableSet<MqHandlerImpl<?>> handlers) {
35+
ImmutableSet<MqHandlerImpl<?>> handlers;
36+
37+
public void setHandlers(Iterable<MqHandlerImpl<?>> handlers) {
38+
this.handlers = ImmutableSet.copyOf(handlers);
39+
}
40+
41+
public void startListener() {
3542
log.debug("Starting listener...");
3643
if (listenerActive) {
3744
throw new RuntimeException("Multiple active sessions in same listener. Check if starting connection threw exception and ActiveMQ ActiveMQConnection.setExceptionListener() failed at the same time.");
@@ -73,7 +80,7 @@ private void restartListener(ImmutableSet<MqHandlerImpl<?>> handlers) {
7380
abort = true;
7481
}
7582
if (! abort) {
76-
startListener(handlers);
83+
startListener();
7784
}
7885
}
7986

servicebuilder-mq-mockmq/src/main/java/no/obos/util/servicebuilder/addon/MqMockAddon.java

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package no.obos.util.servicebuilder.addon;
22

3+
import com.google.common.collect.ImmutableMap;
34
import com.google.common.collect.ImmutableSet;
45
import lombok.AccessLevel;
56
import lombok.AllArgsConstructor;
@@ -8,18 +9,14 @@
89
import no.obos.util.servicebuilder.JerseyConfig;
910
import no.obos.util.servicebuilder.ServiceConfig;
1011
import no.obos.util.servicebuilder.model.ServiceDefinition;
11-
import no.obos.util.servicebuilder.mq.HandlerDescription;
12-
import no.obos.util.servicebuilder.mq.MessageHandler;
13-
import no.obos.util.servicebuilder.mq.MqHandlerImpl;
12+
import no.obos.util.servicebuilder.mq.MqListener;
13+
import no.obos.util.servicebuilder.mq.MqSender;
1414
import no.obos.util.servicebuilder.mq.MqSenderImpl;
1515
import no.obos.util.servicebuilder.mq.SenderDescription;
1616
import no.obos.util.servicebuilder.mq.mock.MqMock;
17-
import no.obos.util.servicebuilder.util.GuavaHelper;
18-
import org.glassfish.hk2.api.ServiceLocator;
17+
import org.glassfish.hk2.api.TypeLiteral;
1918

20-
import javax.inject.Inject;
21-
import javax.ws.rs.core.Feature;
22-
import javax.ws.rs.core.FeatureContext;
19+
import java.util.Map;
2320
import java.util.Set;
2421
import java.util.stream.Collectors;
2522

@@ -67,19 +64,19 @@ public void cleanUp() {
6764
public void addToJerseyConfig(JerseyConfig serviceConfig) {
6865
serviceConfig.addBinder((binder) -> {
6966
binder.bind(this.mqMock).to(MqMock.class);
70-
71-
mqAddon.senders.forEach(senderDescription -> {
72-
MqSenderImpl<?> mqSenderImpl = getMqSender(senderDescription);
73-
binder.bind(mqSenderImpl).to(senderDescription.typeLiteral);
74-
});
67+
binder.bind(this.mqMock).to(MqListener.class);
68+
ImmutableMap<String, MqSender> senderMap = ImmutableMap.copyOf(
69+
mqAddon.senders.stream()
70+
.collect(Collectors.toMap(
71+
sd -> sd.messageDescription.MessageType.getName(),
72+
this::getMqSender
73+
))
74+
);
75+
binder.bind(senderMap).to(new TypeLiteral<Map<String, MqSender>>() {});
7576
});
76-
77-
// Feature is used to start the listeners immediately once dependencies are bound
78-
serviceConfig.addRegistations(registrator -> registrator
79-
.register(StartListenersFeature.class)
80-
);
8177
}
8278

79+
8380
private <T> MqSenderImpl<T> getMqSender(SenderDescription<T> senderDescription) {
8481
return MqSenderImpl.<T>builder()
8582
.messageDescription(senderDescription.messageDescription)
@@ -89,32 +86,6 @@ private <T> MqSenderImpl<T> getMqSender(SenderDescription<T> senderDescription)
8986
.build();
9087
}
9188

92-
private static class StartListenersFeature implements Feature {
93-
@Inject
94-
private ServiceLocator serviceLocator;
95-
96-
@Override
97-
public boolean configure(FeatureContext context) {
98-
MqMock mqMock = serviceLocator.getService(MqMock.class);
99-
MqAddon mqAddon = serviceLocator.getService(MqAddon.class);
100-
ImmutableSet<MqHandlerImpl<?>> handlers = mqAddon.handlers.stream()
101-
.map(this::getHandlerImpl)
102-
.collect(GuavaHelper.setCollector());
103-
mqMock.setHandlers(handlers);
104-
mqMock.launchListenerThread();
105-
return true;
106-
}
107-
108-
private <T> MqHandlerImpl<T> getHandlerImpl(HandlerDescription<T> handlerDescription) {
109-
MessageHandler<T> service = serviceLocator.getService(handlerDescription.messageHandlerClass);
110-
return MqHandlerImpl.<T>builder()
111-
.handlerDescription(handlerDescription)
112-
.messageHandler(service)
113-
.build();
114-
}
115-
116-
}
117-
11889
@Override
11990
public void beforeNextTest() {
12091
mqMock.finishWork();

servicebuilder-mq-mockmq/src/main/java/no/obos/util/servicebuilder/mq/mock/MqMock.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import no.obos.util.servicebuilder.model.MessageDescription;
1212
import no.obos.util.servicebuilder.mq.MqHandlerForwarder;
1313
import no.obos.util.servicebuilder.mq.MqHandlerImpl;
14+
import no.obos.util.servicebuilder.mq.MqListener;
1415
import no.obos.util.servicebuilder.mq.MqMessage;
1516
import no.obos.util.servicebuilder.mq.MqTextSender;
1617
import no.obos.util.servicebuilder.mq.SenderDescription;
@@ -31,7 +32,7 @@
3132
* Mock queue intended for unit testing. Not intended to be run as a listening thread.
3233
*/
3334
@Slf4j
34-
public class MqMock implements MqTextSender {
35+
public class MqMock implements MqTextSender, MqListener {
3536
final Map<String, SenderDescription<?>> senderDescriptions;
3637
final LinkedBlockingQueue<QueuedMessage> listeningQueue = Queues.newLinkedBlockingQueue();
3738
final ImmutableMap<String, CopyOnWriteArrayList<String>> sendingQueues;
@@ -68,11 +69,8 @@ public MqMock(
6869

6970
}
7071

71-
/**
72-
* Only do this once, and before starting listener threads. If not the dark gods of multithreading will bring horrible
73-
* agony on you and your children and your childrens children.
74-
*/
7572

73+
@Override
7674
public void setHandlers(Iterable<MqHandlerImpl<?>> handlers) {
7775
this.handlers = ImmutableMap.copyOf(
7876
stream(handlers)
@@ -96,7 +94,8 @@ public void queueMessage(String messageText, String queue) {
9694
}
9795
}
9896

99-
public void launchListenerThread() {
97+
@Override
98+
public void startListener() {
10099
if (! handlers.isEmpty()) {
101100
running = true;
102101
Runnable runnable = () -> {
@@ -184,7 +183,7 @@ public void stop() {
184183
*/
185184
public void finishWork() {
186185
stop();
187-
launchListenerThread();
186+
startListener();
188187
}
189188

190189

servicebuilder-mq/src/main/java/no/obos/util/servicebuilder/addon/MqAddon.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,21 @@
1212
import no.obos.util.servicebuilder.mq.HandlerDescription;
1313
import no.obos.util.servicebuilder.mq.MessageHandler;
1414
import no.obos.util.servicebuilder.mq.MqHandlerForwarder;
15+
import no.obos.util.servicebuilder.mq.MqHandlerImpl;
16+
import no.obos.util.servicebuilder.mq.MqListener;
1517
import no.obos.util.servicebuilder.mq.MqSender;
1618
import no.obos.util.servicebuilder.mq.SenderDescription;
1719
import no.obos.util.servicebuilder.util.GuavaHelper;
20+
import org.glassfish.hk2.api.Injectee;
21+
import org.glassfish.hk2.api.JustInTimeInjectionResolver;
22+
import org.glassfish.hk2.api.ServiceLocator;
1823
import org.glassfish.hk2.api.TypeLiteral;
24+
import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
25+
26+
import javax.inject.Inject;
27+
import javax.ws.rs.core.Feature;
28+
import javax.ws.rs.core.FeatureContext;
29+
import java.util.Map;
1930

2031
/**
2132
* Interface for queueing system.
@@ -45,7 +56,12 @@ public Addon initialize(ServiceConfig serviceConfig) {
4556

4657
@Override
4758
public void addToJerseyConfig(JerseyConfig serviceConfig) {
59+
// Feature is used to start the listeners immediately once dependencies are bound
60+
serviceConfig.addRegistations(registrator -> registrator
61+
.register(StartListenersFeature.class)
62+
);
4863
serviceConfig.addBinder((binder) -> {
64+
binder.bind(MqSenderResolver.class).to(JustInTimeInjectionResolver.class);
4965
handlers.forEach(handlerDescription ->
5066
binder.bind(handlerDescription.messageHandlerClass).to(handlerDescription.messageHandlerClass)
5167
);
@@ -76,5 +92,50 @@ public <T> MqAddon send(MessageDescription<T> messageDescription, TypeLiteral<Mq
7692
return this.withSenders(GuavaHelper.plus(senders, senderDescription));
7793
}
7894

95+
static class MqSenderResolver implements JustInTimeInjectionResolver {
96+
@Inject
97+
ServiceLocator serviceLocator;
98+
@Inject
99+
Map<String, MqSender> senderMap;
100+
101+
@Override
102+
public boolean justInTimeResolution(Injectee failedInjectionPoint) {
103+
String typeName = failedInjectionPoint.getRequiredType().getTypeName();
104+
if (typeName.startsWith("no.obos.util.servicebuilder.mq.MqSender") && typeName.contains(">") && typeName.contains("<")) {
105+
String messageName = typeName.substring(typeName.indexOf('<') + 1, typeName.indexOf('>'));
106+
ServiceLocatorUtilities.addOneConstant(serviceLocator, senderMap.get(messageName), "null", failedInjectionPoint.getRequiredType());
107+
return true;
108+
}
109+
return false;
110+
}
111+
}
112+
113+
114+
private static class StartListenersFeature implements Feature {
115+
@Inject
116+
private ServiceLocator serviceLocator;
117+
118+
@Override
119+
public boolean configure(FeatureContext context) {
120+
// Iterates through all configurations, which contains the names of the listeners and handlers
121+
MqListener listener = serviceLocator.getService(MqListener.class);
122+
MqAddon mqAddon = serviceLocator.getService(MqAddon.class);
123+
ImmutableSet<MqHandlerImpl<?>> handlers = mqAddon.handlers.stream()
124+
.map(this::getHandlerImpl)
125+
.collect(GuavaHelper.setCollector());
126+
listener.setHandlers(handlers);
127+
listener.startListener();
128+
return true;
129+
}
130+
131+
private <T> MqHandlerImpl<T> getHandlerImpl(HandlerDescription<T> handlerDescription) {
132+
MessageHandler<T> service = serviceLocator.getService(handlerDescription.messageHandlerClass);
133+
return MqHandlerImpl.<T>builder()
134+
.handlerDescription(handlerDescription)
135+
.messageHandler(service)
136+
.build();
137+
}
138+
139+
}
79140

80141
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package no.obos.util.servicebuilder.mq;
2+
3+
public interface MqListener {
4+
/**
5+
* Only do this once, and before starting listener threads. If not the dark gods of multithreading will bring horrible
6+
* agony on you and your children and your childrens children.
7+
*/
8+
void setHandlers(Iterable<MqHandlerImpl<?>> handlers);
9+
10+
void startListener();
11+
}

0 commit comments

Comments
 (0)