createTrieSearch(IndexConfig config) throws IndexCreationException {
final URI resolvedURI = FileUtil.getResolvedUri(config.getBaseUrl(), getFilePath());
log.trace("Resolved filter template reference url for search '{}': {}", this.getId(), resolvedURI);
diff --git a/backend/src/main/java/com/bakdata/conquery/commands/ManagerNode.java b/backend/src/main/java/com/bakdata/conquery/commands/ManagerNode.java
index d1c5686040..d48094fbad 100644
--- a/backend/src/main/java/com/bakdata/conquery/commands/ManagerNode.java
+++ b/backend/src/main/java/com/bakdata/conquery/commands/ManagerNode.java
@@ -85,7 +85,7 @@ public void run(Manager manager) throws InterruptedException {
this.manager = manager;
final ObjectMapper objectMapper = environment.getObjectMapper();
- customizeApiObjectMapper(objectMapper);
+ customizeApiObjectMapper(objectMapper, getDatasetRegistry(), getMetaStorage(), config, validator);
// FormScanner needs to be instantiated before plugins are initialized
@@ -182,7 +182,12 @@ protected void configure() {
*
* @param objectMapper to be configured (should be a JSON mapper)
*/
- public void customizeApiObjectMapper(ObjectMapper objectMapper) {
+ public static void customizeApiObjectMapper(
+ ObjectMapper objectMapper,
+ DatasetRegistry> datasetRegistry,
+ MetaStorage metaStorage,
+ ConqueryConfig config,
+ Validator validator) {
// Set serialization config
SerializationConfig serializationConfig = objectMapper.getSerializationConfig();
@@ -200,18 +205,18 @@ public void customizeApiObjectMapper(ObjectMapper objectMapper) {
final MutableInjectableValues injectableValues = new MutableInjectableValues();
objectMapper.setInjectableValues(injectableValues);
- injectableValues.add(Validator.class, getValidator());
+ injectableValues.add(Validator.class, validator);
- getDatasetRegistry().injectInto(objectMapper);
- getMetaStorage().injectInto(objectMapper);
- getConfig().injectInto(objectMapper);
+ datasetRegistry.injectInto(objectMapper);
+ metaStorage.injectInto(objectMapper);
+ config.injectInto(objectMapper);
}
/**
* Create a new internal object mapper for binary (de-)serialization that is equipped with {@link ManagerNode} related injectables.
*
* @return a preconfigured binary object mapper
- * @see ManagerNode#customizeApiObjectMapper(ObjectMapper)
+ * @see ManagerNode#customizeApiObjectMapper(ObjectMapper, DatasetRegistry, MetaStorage, ConqueryConfig, Validator)
*/
public ObjectMapper createInternalObjectMapper(Class extends View> viewClass) {
return getInternalObjectMapperCreator().createInternalObjectMapper(viewClass);
@@ -219,7 +224,7 @@ public ObjectMapper createInternalObjectMapper(Class extends View> viewClass)
private void loadMetaStorage() {
log.info("Opening MetaStorage");
- getMetaStorage().openStores(getInternalObjectMapperCreator().createInternalObjectMapper(View.Persistence.Manager.class));
+ getMetaStorage().openStores(createInternalObjectMapper(View.Persistence.Manager.class));
log.info("Loading MetaStorage");
getMetaStorage().loadData();
log.info("MetaStorage loaded {}", getMetaStorage());
diff --git a/backend/src/main/java/com/bakdata/conquery/io/jackson/Initializing.java b/backend/src/main/java/com/bakdata/conquery/io/jackson/Initializing.java
new file mode 100644
index 0000000000..e70ceda844
--- /dev/null
+++ b/backend/src/main/java/com/bakdata/conquery/io/jackson/Initializing.java
@@ -0,0 +1,29 @@
+package com.bakdata.conquery.io.jackson;
+
+import com.fasterxml.jackson.databind.util.StdConverter;
+
+/**
+ * Interface for class instances that need initialization after deserialization and value injection.
+ * Let the class implement this interface and annotate the class with:
+ *
+ * {@code
+ * @JsonDeserialize(converter = Initializing.Converter.class )
+ * }
+ *
+ * @param
+ * @implNote Every class that inherits from an initializing class needs to define its own Converter.
+ * Otherwise, the class is parsed as the super class, and its overrides are not called.
+ */
+public interface Initializing {
+
+ void init();
+
+ class Converter extends StdConverter {
+
+ @Override
+ public T convert(T value) {
+ value.init();
+ return value;
+ }
+ }
+}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
index 7de472e7b3..f22cc675e9 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespaceStorage.java
@@ -3,6 +3,8 @@
import java.util.Collection;
import java.util.Objects;
+import com.bakdata.conquery.io.jackson.Injectable;
+import com.bakdata.conquery.io.jackson.MutableInjectableValues;
import com.bakdata.conquery.io.storage.xodus.stores.CachedStore;
import com.bakdata.conquery.io.storage.xodus.stores.SingletonStore;
import com.bakdata.conquery.models.config.StoreFactory;
@@ -16,10 +18,12 @@
import com.bakdata.conquery.models.worker.WorkerToBucketsMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
+import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@Slf4j
-public class NamespaceStorage extends NamespacedStorage {
+@ToString
+public class NamespaceStorage extends NamespacedStorage implements Injectable {
protected IdentifiableStore internToExternMappers;
protected IdentifiableStore searchIndexes;
@@ -40,11 +44,6 @@ private void decorateIdMapping(SingletonStore idMapping) {
.onAdd(mapping -> mapping.setStorage(this));
}
- private void decorateInternToExternMappingStore(IdentifiableStore store) {
- // We don't call internToExternMapper::init this is done by the first select that needs the mapping
- }
-
-
@Override
public void openStores(ObjectMapper objectMapper) {
super.openStores(objectMapper);
@@ -57,7 +56,6 @@ public void openStores(ObjectMapper objectMapper) {
preview = getStorageFactory().createPreviewStore(super.getPathName(), getCentralRegistry(), objectMapper);
entity2Bucket = getStorageFactory().createEntity2BucketStore(super.getPathName(), objectMapper);
- decorateInternToExternMappingStore(internToExternMappers);
decorateIdMapping(idMapping);
}
@@ -169,4 +167,10 @@ public PreviewConfig getPreviewConfig() {
public void removePreviewConfig() {
preview.remove();
}
+
+
+ @Override
+ public MutableInjectableValues inject(MutableInjectableValues values) {
+ return super.inject(values).add(NamespaceStorage.class, this);
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
index a9a7378760..25baf5df05 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/NamespacedStorage.java
@@ -4,6 +4,8 @@
import java.util.Collection;
import java.util.List;
+import com.bakdata.conquery.io.jackson.Injectable;
+import com.bakdata.conquery.io.jackson.MutableInjectableValues;
import com.bakdata.conquery.io.storage.xodus.stores.SingletonStore;
import com.bakdata.conquery.models.config.StoreFactory;
import com.bakdata.conquery.models.datasets.Column;
@@ -35,7 +37,7 @@
*/
@Slf4j
@ToString(onlyExplicitlyIncluded = true)
-public abstract class NamespacedStorage extends ConqueryStorage {
+public abstract class NamespacedStorage extends ConqueryStorage implements Injectable {
@Getter
protected final CentralRegistry centralRegistry = new CentralRegistry();
@@ -59,6 +61,7 @@ public NamespacedStorage(StoreFactory storageFactory, String pathName) {
public void openStores(ObjectMapper objectMapper) {
// Before we start to parse the stores we need to replace the injected value for the IdResolveContext (from DatasetRegistry to this centralRegistry)
new SingletonNamespaceCollection(centralRegistry).injectInto(objectMapper);
+ this.injectInto(objectMapper);
dataset = storageFactory.createDatasetStore(pathName, objectMapper);
secondaryIds = storageFactory.createSecondaryIdDescriptionStore(centralRegistry, pathName, objectMapper);
@@ -67,9 +70,7 @@ public void openStores(ObjectMapper objectMapper) {
concepts = storageFactory.createConceptStore(centralRegistry, pathName, objectMapper);
decorateDatasetStore(dataset);
- decorateSecondaryIdDescriptionStore(secondaryIds);
decorateTableStore(tables);
- decorateImportStore(imports);
decorateConceptStore(concepts);
}
@@ -88,10 +89,6 @@ private void decorateDatasetStore(SingletonStore store) {
store.onAdd(centralRegistry::register).onRemove(centralRegistry::remove);
}
- private void decorateSecondaryIdDescriptionStore(IdentifiableStore store) {
- // Nothing to decorate
- }
-
private void decorateTableStore(IdentifiableStore store) {
store.onAdd(table -> {
for (Column column : table.getColumns()) {
@@ -109,13 +106,13 @@ private void decorateTableStore(IdentifiableStore store) {
private void decorateConceptStore(IdentifiableStore> store) {
store.onAdd(concept -> {
- if (concept.getDataset() != null && !concept.getDataset().equals(dataset.get())) {
- throw new IllegalStateException("Concept is not for this dataset.");
+ if (concept.getDataset() == null) {
+ throw new IllegalStateException("Concept had no dataset set");
}
- concept.setDataset(dataset.get());
-
- concept.initElements();
+ if (!concept.getDataset().equals(dataset.get())) {
+ throw new IllegalStateException("Concept is not for this dataset.");
+ }
concept.getSelects().forEach(centralRegistry::register);
for (Connector connector : concept.getConnectors()) {
@@ -145,11 +142,6 @@ private void decorateConceptStore(IdentifiableStore> store) {
});
}
- private void decorateImportStore(IdentifiableStore store) {
- // Intentionally left blank
- }
-
-
public void addImport(Import imp) {
imports.add(imp);
}
@@ -231,4 +223,9 @@ public Collection> getAllConcepts() {
return concepts.getAll();
}
+
+ @Override
+ public MutableInjectableValues inject(MutableInjectableValues values) {
+ return values.add(NamespacedStorage.class, this);
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/io/storage/WorkerStorage.java b/backend/src/main/java/com/bakdata/conquery/io/storage/WorkerStorage.java
index 84ff4e90d6..ac51d97c4b 100644
--- a/backend/src/main/java/com/bakdata/conquery/io/storage/WorkerStorage.java
+++ b/backend/src/main/java/com/bakdata/conquery/io/storage/WorkerStorage.java
@@ -2,6 +2,8 @@
import java.util.Collection;
+import com.bakdata.conquery.io.jackson.Injectable;
+import com.bakdata.conquery.io.jackson.MutableInjectableValues;
import com.bakdata.conquery.io.storage.xodus.stores.SingletonStore;
import com.bakdata.conquery.models.config.StoreFactory;
import com.bakdata.conquery.models.datasets.concepts.Concept;
@@ -13,19 +15,18 @@
import com.bakdata.conquery.models.worker.WorkerInformation;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
-import jakarta.validation.Validator;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@ToString(of = "worker")
-public class WorkerStorage extends NamespacedStorage {
+public class WorkerStorage extends NamespacedStorage implements Injectable {
private SingletonStore worker;
private IdentifiableStore buckets;
private IdentifiableStore cBlocks;
- public WorkerStorage(StoreFactory storageFactory, Validator validator, String pathName) {
+ public WorkerStorage(StoreFactory storageFactory, String pathName) {
super(storageFactory, pathName);
}
@@ -36,10 +37,6 @@ public void openStores(ObjectMapper objectMapper) {
worker = getStorageFactory().createWorkerInformationStore(getPathName(), objectMapper);
buckets = getStorageFactory().createBucketStore(centralRegistry, getPathName(), objectMapper);
cBlocks = getStorageFactory().createCBlockStore(centralRegistry, getPathName(), objectMapper);
-
- decorateWorkerStore(worker);
- decorateBucketStore(buckets);
- decorateCBlockStore(cBlocks);
}
@Override
@@ -58,19 +55,6 @@ public ImmutableList getStores() {
}
- private void decorateWorkerStore(SingletonStore store) {
- // Nothing to decorate
- }
-
- private void decorateBucketStore(IdentifiableStore store) {
- // Nothing to decorate
- }
-
- private void decorateCBlockStore(IdentifiableStore baseStoreCreator) {
- // Nothing to decorate
- }
-
-
public void addCBlock(CBlock cBlock) {
log.trace("Adding CBlock[{}]", cBlock.getId());
cBlocks.add(cBlock);
@@ -129,4 +113,9 @@ public void removeConcept(ConceptId id) {
log.debug("Removing Concept[{}]", id);
concepts.remove(id);
}
+
+ @Override
+ public MutableInjectableValues inject(MutableInjectableValues values) {
+ return super.inject(values).add(WorkerStorage.class, this);
+ }
}
diff --git a/backend/src/main/java/com/bakdata/conquery/mode/NamespaceHandler.java b/backend/src/main/java/com/bakdata/conquery/mode/NamespaceHandler.java
index fef5334580..af83f42f13 100644
--- a/backend/src/main/java/com/bakdata/conquery/mode/NamespaceHandler.java
+++ b/backend/src/main/java/com/bakdata/conquery/mode/NamespaceHandler.java
@@ -33,14 +33,17 @@ public interface NamespaceHandler {
static NamespaceSetupData createNamespaceSetup(NamespaceStorage storage, final ConqueryConfig config, final InternalObjectMapperCreator mapperCreator, IndexService indexService) {
List injectables = new ArrayList<>();
injectables.add(indexService);
+ injectables.add(storage);
ObjectMapper persistenceMapper = mapperCreator.createInternalObjectMapper(View.Persistence.Manager.class);
ObjectMapper communicationMapper = mapperCreator.createInternalObjectMapper(View.InternalCommunication.class);
ObjectMapper preprocessMapper = mapperCreator.createInternalObjectMapper(null);
- injectables.forEach(i -> i.injectInto(persistenceMapper));
- injectables.forEach(i -> i.injectInto(communicationMapper));
- injectables.forEach(i -> i.injectInto(preprocessMapper));
+ injectables.forEach(i -> {
+ i.injectInto(persistenceMapper);
+ i.injectInto(communicationMapper);
+ i.injectInto(preprocessMapper);
+ });
// Each store needs its own mapper because each injects its own registry
diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java b/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
index 7529e92934..797df2caab 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/config/XodusStoreFactory.java
@@ -16,8 +16,11 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
-
import javax.annotation.Nullable;
+import jakarta.validation.Valid;
+import jakarta.validation.Validator;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotNull;
import com.bakdata.conquery.io.cps.CPSType;
import com.bakdata.conquery.io.storage.IdentifiableStore;
@@ -63,10 +66,6 @@
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import io.dropwizard.util.Duration;
-import jakarta.validation.Valid;
-import jakarta.validation.Validator;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotNull;
import jetbrains.exodus.env.Environment;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -195,7 +194,7 @@ public Collection discoverNamespaceStorages() {
@Override
public Collection discoverWorkerStorages() {
- return loadNamespacedStores("worker_", (storePath) -> new WorkerStorage(this, validator, storePath), WORKER_STORES);
+ return loadNamespacedStores("worker_", (storePath) -> new WorkerStorage(this, storePath), WORKER_STORES);
}
diff --git a/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java b/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java
index b7f3d6a27d..f50f0b2375 100644
--- a/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java
+++ b/backend/src/main/java/com/bakdata/conquery/models/datasets/concepts/Concept.java
@@ -4,6 +4,7 @@
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
+import jakarta.validation.Valid;
import com.bakdata.conquery.io.cps.CPSBase;
import com.bakdata.conquery.io.jackson.serializer.NsIdRef;
@@ -15,8 +16,6 @@
import com.bakdata.conquery.models.datasets.Dataset;
import com.bakdata.conquery.models.datasets.concepts.select.Select;
import com.bakdata.conquery.models.datasets.concepts.tree.TreeConcept;
-import com.bakdata.conquery.models.exceptions.ConfigurationException;
-import com.bakdata.conquery.models.exceptions.JSONException;
import com.bakdata.conquery.models.identifiable.ids.specific.ConceptId;
import com.bakdata.conquery.models.query.PrintSettings;
import com.bakdata.conquery.models.query.QueryPlanContext;
@@ -29,7 +28,6 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import jakarta.validation.Valid;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@@ -74,11 +72,6 @@ public List