Skip to content

Commit d2a1792

Browse files
authored
split BeanRegistry interface (#2488)
* split BeanRegistry interface * fixes * fixed thread-safety
1 parent 255e460 commit d2a1792

27 files changed

Lines changed: 368 additions & 291 deletions

annot/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
<artifactId>json-schema-validator</artifactId>
5757
<version>2.0.0</version>
5858
</dependency>
59+
<dependency>
60+
<groupId>com.github.spotbugs</groupId>
61+
<artifactId>spotbugs-annotations</artifactId>
62+
<version>4.9.8</version>
63+
</dependency>
5964

6065
<!-- Test dependencies -->
6166
<dependency>

annot/src/main/java/com/predic8/membrane/annot/bean/BeanFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
package com.predic8.membrane.annot.bean;
1616

1717
import com.fasterxml.jackson.databind.*;
18+
import com.predic8.membrane.annot.beanregistry.BeanRegistry;
1819
import com.predic8.membrane.annot.util.*;
19-
import com.predic8.membrane.annot.yaml.*;
2020
import org.jetbrains.annotations.*;
2121

2222
import java.lang.reflect.*;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.predic8.membrane.annot.beanregistry;
2+
3+
import javax.annotation.concurrent.GuardedBy;
4+
import java.util.concurrent.BlockingQueue;
5+
import java.util.concurrent.LinkedBlockingDeque;
6+
7+
/**
8+
* Thread-safe, asynchronous wrapper for {@link BeanCollector}.
9+
*/
10+
public class AsyncBeanCollector implements BeanCollector {
11+
12+
private final BlockingQueue<ChangeEvent> changeEvents = new LinkedBlockingDeque<>();
13+
private final BeanCollector delegate;
14+
15+
@GuardedBy("this")
16+
Thread t;
17+
18+
public AsyncBeanCollector(BeanCollector delegate) {
19+
this.delegate = delegate;
20+
}
21+
22+
@Override
23+
public void handle(ChangeEvent changeEvent, boolean isLast) {
24+
changeEvents.add(changeEvent);
25+
}
26+
27+
@Override
28+
public synchronized void start() {
29+
if (t != null)
30+
return;
31+
t = Thread.ofVirtual().start(() -> {
32+
while (true) {
33+
try {
34+
ChangeEvent changeEvent = changeEvents.take();
35+
delegate.handle(changeEvent, changeEvents.isEmpty());
36+
} catch (InterruptedException e) {
37+
break;
38+
}
39+
}
40+
});
41+
}
42+
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.predic8.membrane.annot.beanregistry;
2+
3+
import com.predic8.membrane.annot.Grammar;
4+
import com.predic8.membrane.annot.yaml.GenericYamlParser;
5+
import com.predic8.membrane.annot.yaml.WatchAction;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.util.List;
10+
11+
/**
12+
* This is the definition side of a {@link BeanRegistryImplementation}. You can start the bean registry
13+
* and send it a series of change events.
14+
*/
15+
public interface BeanCollector {
16+
/**
17+
* Utility method to ingest a stream of YAML objects as a static configuration and then
18+
* start the bean registry.
19+
* @param yamls stream of YAML objects
20+
* @param grammar the grammar to use for parsing
21+
*/
22+
default void parseYamls(InputStream yamls, Grammar grammar) throws IOException {
23+
List<BeanDefinition> bds = GenericYamlParser.parseMembraneResources(yamls, grammar);
24+
for (int i = 0; i < bds.size(); i++) {
25+
handle(new BeanDefinitionChanged(WatchAction.ADDED, bds.get(i)), i == bds.size() - 1);
26+
}
27+
handle(new StaticConfigurationLoaded(), true);
28+
start();
29+
}
30+
31+
/**
32+
* @param changeEvent the change event
33+
* @param isLast indicates whether this is the last change event for this batch of changes
34+
*/
35+
void handle(ChangeEvent changeEvent, boolean isLast);
36+
37+
/**
38+
* Starts the bean registry.
39+
*/
40+
void start();
41+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.predic8.membrane.annot.beanregistry;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
5+
public class BeanContainer {
6+
private final BeanDefinition definition;
7+
/**
8+
* Constructed bean after initialization.
9+
*/
10+
private volatile Object singleton;
11+
12+
public BeanContainer(BeanDefinition definition) {
13+
this.definition = definition;
14+
}
15+
16+
17+
public Object getSingleton() {
18+
return singleton;
19+
}
20+
21+
public void setSingleton(Object singleton) {
22+
this.singleton = singleton;
23+
}
24+
25+
public BeanDefinition getDefinition() {
26+
return definition;
27+
}
28+
}

annot/src/main/java/com/predic8/membrane/annot/yaml/BeanDefinition.java renamed to annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
14-
package com.predic8.membrane.annot.yaml;
14+
package com.predic8.membrane.annot.beanregistry;
1515

1616
import com.fasterxml.jackson.databind.JsonNode;
17-
import com.predic8.membrane.annot.*;
18-
import com.predic8.membrane.annot.bean.*;
19-
20-
import java.util.*;
17+
import com.predic8.membrane.annot.yaml.WatchAction;
2118

2219
import static com.predic8.membrane.annot.yaml.WatchAction.*;
2320

@@ -29,19 +26,12 @@ public class BeanDefinition {
2926
private final String namespace;
3027
private final String uid;
3128
private final JsonNode node;
32-
private final WatchAction action;
3329
private final String kind;
3430

35-
/**
36-
* Constructed bean after initialization.
37-
*/
38-
private Object bean;
39-
4031
/**
4132
* Only called from K8S.
4233
*/
43-
private BeanDefinition(WatchAction action, JsonNode node) {
44-
this.action = action;
34+
private BeanDefinition(JsonNode node) {
4535
this.node = node;
4636
JsonNode metadata = node.get("metadata");
4737
var kind2 = node.get("kind").asText();
@@ -55,8 +45,8 @@ private BeanDefinition(WatchAction action, JsonNode node) {
5545
uid = metadata.get("uid").asText();
5646
}
5747

58-
public static BeanDefinition create4Kubernetes(WatchAction action, JsonNode node) {
59-
return new BeanDefinition(action, node);
48+
public static BeanDefinitionChanged create4Kubernetes(WatchAction action, JsonNode node) {
49+
return new BeanDefinitionChanged(action, new BeanDefinition(node));
6050
}
6151

6252
public BeanDefinition(String kind, String name, String namespace, String uid, JsonNode node) {
@@ -65,17 +55,12 @@ public BeanDefinition(String kind, String name, String namespace, String uid, Js
6555
this.namespace = namespace;
6656
this.uid = uid;
6757
this.node = node;
68-
this.action = ADDED;
6958
}
7059

7160
public JsonNode getNode() {
7261
return node;
7362
}
7463

75-
public WatchAction getAction() {
76-
return action;
77-
}
78-
7964
public String getNamespace() {
8065
return namespace;
8166
}
@@ -92,15 +77,6 @@ public String getKind() {
9277
return kind;
9378
}
9479

95-
public Object getBean() {
96-
return bean;
97-
}
98-
99-
// TODO: Rest is immutable - can we make this also?
100-
public void setBean(Object bean) {
101-
this.bean = bean;
102-
}
103-
10480
public String getScope() {
10581
JsonNode meta = node.get("metadata");
10682
if (meta == null)
@@ -124,15 +100,4 @@ public boolean isPrototype() {
124100
return PROTOTYPE.equals(getScope());
125101
}
126102

127-
public boolean isDeleted() {
128-
return action == DELETED;
129-
}
130-
131-
public boolean isModified() {
132-
return action == MODIFIED;
133-
}
134-
135-
public boolean isAdded() {
136-
return action == ADDED;
137-
}
138103
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.predic8.membrane.annot.beanregistry;
2+
3+
import com.predic8.membrane.annot.yaml.WatchAction;
4+
5+
/**
6+
* Signals that a BeanDefinition has changed (=was added, modified, or deleted).
7+
*/
8+
public record BeanDefinitionChanged(
9+
WatchAction action,
10+
BeanDefinition bd) implements ChangeEvent {
11+
}

annot/src/main/java/com/predic8/membrane/annot/yaml/BeanRegistry.java renamed to annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistry.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License. */
14-
package com.predic8.membrane.annot.yaml;
14+
package com.predic8.membrane.annot.beanregistry;
1515

1616
import com.predic8.membrane.annot.*;
1717

@@ -23,10 +23,6 @@ public interface BeanRegistry {
2323

2424
List<Object> getBeans();
2525

26-
void registerBeanDefinitions(List<BeanDefinition> beanDefinitions);
27-
28-
void start();
29-
3026
Grammar getGrammar();
3127

3228
}

0 commit comments

Comments
 (0)