Skip to content

Commit

Permalink
MetaModule: support ResourceRegistry changes at runtime #81
Browse files Browse the repository at this point in the history
- introduced listener for ResourceRegistryPart
- MetaModule reinitializes MetaLookup holding all MetaElements upon ResourceRegistry change
- MetaModule caches MetaLookup instance during lifetime of request for consistent responses regardless of concurrent modifications
  • Loading branch information
remmeier committed Aug 9, 2017
1 parent 9113ae0 commit 679fea0
Show file tree
Hide file tree
Showing 31 changed files with 712 additions and 155 deletions.
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,19 @@ gradle.beforeProject { Project project ->
} else {
apply plugin: 'maven-publish'

task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java

artifact sourcesJar {
classifier "sources"
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,64 +1,71 @@
package io.crnk.core.engine.information;

import java.lang.reflect.Type;

import io.crnk.core.engine.information.repository.RelationshipRepositoryInformation;
import io.crnk.core.engine.information.repository.ResourceRepositoryInformation;
import io.crnk.core.engine.information.resource.*;
import io.crnk.core.engine.information.resource.ResourceField;
import io.crnk.core.engine.information.resource.ResourceFieldAccess;
import io.crnk.core.engine.information.resource.ResourceFieldAccessor;
import io.crnk.core.engine.information.resource.ResourceFieldType;
import io.crnk.core.engine.information.resource.ResourceInformation;
import io.crnk.core.resource.annotations.LookupIncludeBehavior;

import java.lang.reflect.Type;

public interface InformationBuilder {

interface RelationshipRepository {

RelationshipRepositoryInformation build();

}

interface ResourceRepository {

ResourceRepositoryInformation build();

}

interface Resource {

InformationBuilder.Field addField(String name, ResourceFieldType id1, Class<?> clazz);

void resourceClass(Class<?> resourceClass);
Resource resourceClass(Class<?> resourceClass);

void resourceType(String resourceType);
Resource resourceType(String resourceType);

void superResourceType(String superResourceType);
Resource superResourceType(String superResourceType);

ResourceInformation build();

}

interface Field {

ResourceField build();

void jsonName(String jsonName);
Field jsonName(String jsonName);

void underlyingName(String underlyingName);
Field underlyingName(String underlyingName);

void type(Class<?> type);
Field type(Class<?> type);

void genericType(Type genericType);
Field genericType(Type genericType);

void lazy(boolean lazy);
Field lazy(boolean lazy);

void oppositeResourceType(String oppositeResourceType);
Field oppositeResourceType(String oppositeResourceType);

void lookupIncludeBehavior(LookupIncludeBehavior lookupIncludeBehavior);
Field lookupIncludeBehavior(LookupIncludeBehavior lookupIncludeBehavior);

void includeByDefault(boolean includeByDefault);
Field includeByDefault(boolean includeByDefault);

void fieldType(ResourceFieldType fieldType);
Field fieldType(ResourceFieldType fieldType);

void setOppositeName(String oppositeName);
Field setOppositeName(String oppositeName);

void setAccessor(ResourceFieldAccessor accessor);
Field setAccessor(ResourceFieldAccessor accessor);

void setAccess(ResourceFieldAccess access);
Field setAccess(ResourceFieldAccess access);

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package io.crnk.core.engine.internal.information;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.crnk.core.engine.information.InformationBuilder;
import io.crnk.core.engine.information.repository.RelationshipRepositoryInformation;
import io.crnk.core.engine.information.repository.RepositoryAction;
import io.crnk.core.engine.information.repository.ResourceRepositoryInformation;
import io.crnk.core.engine.information.resource.*;
import io.crnk.core.engine.information.resource.ResourceField;
import io.crnk.core.engine.information.resource.ResourceFieldAccess;
import io.crnk.core.engine.information.resource.ResourceFieldAccessor;
import io.crnk.core.engine.information.resource.ResourceFieldType;
import io.crnk.core.engine.information.resource.ResourceInformation;
import io.crnk.core.engine.internal.information.repository.RelationshipRepositoryInformationImpl;
import io.crnk.core.engine.internal.information.repository.ResourceRepositoryInformationImpl;
import io.crnk.core.engine.internal.information.resource.ResourceFieldImpl;
import io.crnk.core.engine.parser.TypeParser;
import io.crnk.core.resource.annotations.LookupIncludeBehavior;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DefaultInformationBuilder implements InformationBuilder {

private final TypeParser typeParser;
Expand Down Expand Up @@ -109,16 +113,19 @@ public DefaultField addField(String name, ResourceFieldType type, Class<?> clazz
return field;
}

public void resourceClass(Class<?> resourceClass) {
public DefaultResource resourceClass(Class<?> resourceClass) {
this.resourceClass = resourceClass;
return this;
}

public void resourceType(String resourceType) {
public DefaultResource resourceType(String resourceType) {
this.resourceType = resourceType;
return this;
}

public void superResourceType(String superResourceType) {
public DefaultResource superResourceType(String superResourceType) {
this.superResourceType = superResourceType;
return this;
}

public ResourceInformation build() {
Expand All @@ -136,8 +143,11 @@ public ResourceInformation build() {
public class DefaultField implements InformationBuilder.Field {

private String jsonName;

private String underlyingName;

private Class<?> type;

private Type genericType;

private boolean lazy = true;
Expand Down Expand Up @@ -167,53 +177,65 @@ public ResourceField build() {
return impl;
}

public void jsonName(String jsonName) {
public DefaultField jsonName(String jsonName) {
this.jsonName = jsonName;
return this;
}

public void underlyingName(String underlyingName) {
public DefaultField underlyingName(String underlyingName) {
this.underlyingName = underlyingName;
return this;
}


public void type(Class<?> type) {
public DefaultField type(Class<?> type) {
this.type = type;
return this;
}

public void genericType(Type genericType) {
public DefaultField genericType(Type genericType) {
this.genericType = genericType;
return this;
}

public void lazy(boolean lazy) {
public DefaultField lazy(boolean lazy) {
this.lazy = lazy;
return this;
}

public void oppositeResourceType(String oppositeResourceType) {
public DefaultField oppositeResourceType(String oppositeResourceType) {
this.oppositeResourceType = oppositeResourceType;
return this;
}

public void lookupIncludeBehavior(LookupIncludeBehavior lookupIncludeBehavior) {
public DefaultField lookupIncludeBehavior(LookupIncludeBehavior lookupIncludeBehavior) {
this.lookupIncludeBehavior = lookupIncludeBehavior;
return this;
}

public void includeByDefault(boolean includeByDefault) {
public DefaultField includeByDefault(boolean includeByDefault) {
this.includeByDefault = includeByDefault;
return this;
}

public void fieldType(ResourceFieldType fieldType) {
public DefaultField fieldType(ResourceFieldType fieldType) {
this.fieldType = fieldType;
return this;
}

public void setOppositeName(String oppositeName) {
public DefaultField setOppositeName(String oppositeName) {
this.oppositeName = oppositeName;
return this;
}

public void setAccessor(ResourceFieldAccessor accessor) {
public DefaultField setAccessor(ResourceFieldAccessor accessor) {
this.accessor = accessor;
return this;
}

public void setAccess(ResourceFieldAccess access) {
public DefaultField setAccess(ResourceFieldAccess access) {
this.access = access;
return this;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package io.crnk.core.engine.internal.registry;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

import io.crnk.core.engine.information.resource.ResourceInformation;
import io.crnk.core.engine.internal.utils.PreconditionUtil;
import io.crnk.core.engine.internal.utils.UrlUtils;
import io.crnk.core.engine.registry.RegistryEntry;
import io.crnk.core.engine.registry.ResourceRegistry;
import io.crnk.core.engine.registry.ResourceRegistryPart;
import io.crnk.core.engine.registry.ResourceRegistryPartBase;
import io.crnk.core.engine.registry.ResourceRegistryPartEvent;
import io.crnk.core.engine.registry.ResourceRegistryPartListener;
import io.crnk.core.engine.url.ServiceUrlProvider;
import io.crnk.core.exception.RepositoryNotFoundException;
import io.crnk.core.module.ModuleRegistry;
import io.crnk.core.utils.Optional;

import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

public class ResourceRegistryImpl implements ResourceRegistry {
public class ResourceRegistryImpl extends ResourceRegistryPartBase implements ResourceRegistry {

private final ServiceUrlProvider serviceUrlProvider;

Expand All @@ -23,18 +27,28 @@ public class ResourceRegistryImpl implements ResourceRegistry {

private ResourceRegistryPart rootPart;

public ResourceRegistryImpl(ResourceRegistryPart rootPart, ModuleRegistry moduleRegistry, ServiceUrlProvider serviceUrlProvider) {
private ResourceRegistryPartListener rootListener = new ResourceRegistryPartListener() {
@Override
public void onChanged(ResourceRegistryPartEvent event) {
notifyChange();
}
};

public ResourceRegistryImpl(ResourceRegistryPart rootPart, ModuleRegistry moduleRegistry,
ServiceUrlProvider serviceUrlProvider) {
this.rootPart = rootPart;
this.moduleRegistry = moduleRegistry;
this.serviceUrlProvider = serviceUrlProvider;
this.moduleRegistry.setResourceRegistry(this);

rootPart.addListener(rootListener);
}


/**
* Adds a new resource definition to a registry.
*
* @param resource class of a resource
* @param resource class of a resource
* @param registryEntry resource information
*/
public RegistryEntry addEntry(Class<?> resource, RegistryEntry registryEntry) {
Expand All @@ -46,7 +60,8 @@ protected RegistryEntry findEntry(Class<?> clazz, boolean allowNull) {
Optional<Class<?>> resourceClazz = getResourceClass(clazz);
if (allowNull && !resourceClazz.isPresent()) {
return null;
} else if (!resourceClazz.isPresent()) {
}
else if (!resourceClazz.isPresent()) {
throw new RepositoryNotFoundException(clazz.getCanonicalName());
}
return rootPart.getEntry(resourceClazz.get());
Expand Down Expand Up @@ -110,7 +125,9 @@ public ResourceInformation getBaseResourceInformation(String resourceType) {
RegistryEntry entry = getEntry(resourceType);
baseInformation = entry.getResourceInformation();
while (baseInformation.getSuperResourceType() != null) {
entry = getEntry(baseInformation.getSuperResourceType());
String superResourceType = baseInformation.getSuperResourceType();
entry = getEntry(superResourceType);
PreconditionUtil.assertNotNull(superResourceType, entry);
baseInformation = entry.getResourceInformation();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
package io.crnk.core.engine.registry;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import io.crnk.core.engine.information.resource.ResourceInformation;
import io.crnk.core.engine.internal.registry.ResourceRegistryImpl;
import io.crnk.core.engine.internal.utils.PreconditionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;


/**
* Implements ResourceRegistryPart by maintaining a simple set of RegistryEntry in memory.
*/
public class DefaultResourceRegistryPart implements ResourceRegistryPart {
public class DefaultResourceRegistryPart extends ResourceRegistryPartBase {

private final Logger logger = LoggerFactory.getLogger(ResourceRegistryImpl.class);

private final Map<String, RegistryEntry> resourcesByType;

private final Map<Class, RegistryEntry> resourcesByClass;


public DefaultResourceRegistryPart() {
this.resourcesByType = new HashMap<>();
this.resourcesByClass = new HashMap<>();
Expand All @@ -34,6 +39,7 @@ public RegistryEntry addEntry(RegistryEntry entry) {
resourcesByClass.put(resourceClass, entry);
resourcesByType.put(resourceType, entry);
logger.debug("Added resource {} to ResourceRegistry", entry.getResourceInformation().getResourceType());
notifyChange();
return entry;
}

Expand Down

0 comments on commit 679fea0

Please sign in to comment.