Skip to content

Commit

Permalink
added documentation to microservices module
Browse files Browse the repository at this point in the history
  • Loading branch information
marvec committed May 7, 2015
1 parent 3286806 commit c96088d
Show file tree
Hide file tree
Showing 18 changed files with 431 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Map;

/**
* Main class to boot the Microservices platforms.
*
* @author Martin Večeřa <[email protected]>
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "DM_EXIT", justification = "This class is allowed to terminate the JVM.")
Expand All @@ -41,6 +43,13 @@ public final class Boot {

private static final String PROPERTY_LETTER = "D";

/**
* Starts the Microservices platform.
*
* Uses Executor Microservice Provider as a boot hook.
*
* @param args Any additional properties can be specified at the command line via -Dprop=value.
*/
public static void main(final String... args) {
Thread.currentThread().setName("SilverWare-main");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,56 +38,127 @@
import java.util.stream.Collectors;

/**
* Microservices context carrying all necessary execution information.
* The intention is to separate all information shared between providers
* to be able to create multiple instances of the platform in the same JVM.
*
* @author Martin Večeřa <[email protected]>
*/
public class Context {

/**
* Logger.
*/
private static final Logger log = LogManager.getLogger(Context.class);

/**
* Property key where a registry with Microservice providers is.
*/
public static final String MICROSERVICE_PROVIDERS_REGISTRY = "silverware.providers.registry";

/**
* Name of the system property that lists the packages to be searched for provider deployments.
*/
public static final String DEPLOYMENT_PACKAGES = "silverware.deploy.packages";

/**
* Property key where a registry with local Microservices is.
*/
public static final String MICROSERVICES = "silverware.microservices";

/**
* Global properties.
*/
private final Map<String, Object> properties = new HashMap<>();

/**
* Providers registry.
*/
private final Map<String, MicroserviceProvider> providers = new HashMap<>();

/**
* Local Microservices registry.
*/
private final Set<MicroserviceMetaData> microservices = new HashSet<>();

/**
* Handles created for incoming service queries.
*/
private List<ServiceHandle> inboundHandles = new ArrayList<>();
private List<ServiceHandle> outboundHandles = new ArrayList<>();

/**
* Creates the context and binds the registries to global properties.
*/
public Context() {
properties.put(MICROSERVICE_PROVIDERS_REGISTRY, providers);
properties.put(MICROSERVICES, microservices);
}

/**
* Gets the global properties.
* @return The global properties.
*/
public Map<String, Object> getProperties() {
return properties;
}

/**
* Gets the registry of Microservices providers.
* @return
*/
@SuppressWarnings("unchecked")
public Map<String, MicroserviceProvider> getProvidersRegistry() {
return (Map<String, MicroserviceProvider>) properties.get(MICROSERVICE_PROVIDERS_REGISTRY);
}

/**
* Adds a Microservice to the registry.
* @param metaData
*/
public void registerMicroservice(final MicroserviceMetaData metaData) {
microservices.add(metaData);
}

/**
* Gets an unmodifiable copy of the current local Microservices registry.
* @return An unmodifiable copy of the current local Microservices registry.
*/
public Set<MicroserviceMetaData> getMicroservices() {
return Collections.unmodifiableSet(microservices);
}

/**
* Looks up Microservices based on the provided meta-data query.
* All providers are asked to look up all possible services including local and remote.
* @param metaData Meta-data query.
* @return A set of Microservices instances that meets the query.
*/
public Set<Object> lookupMicroservice(final MicroserviceMetaData metaData) {
return getAllProviders(ProvidingSilverService.class).stream()
.map(providingSilverService -> ((ProvidingSilverService) providingSilverService).lookupMicroservice(metaData))
.collect(Collectors.toSet());
}

/**
* Looks up Microservices based on the provided meta-data query.
* Only local Microservices are searched.
* @param metaData Meta-data query.
* @return A set of Microservices instances that meets the query.
*/
public Set<Object> lookupLocalMicroservice(final MicroserviceMetaData metaData) {
return getAllProviders(ProvidingSilverService.class).stream()
.map(providingSilverService -> ((ProvidingSilverService) providingSilverService).lookupLocalMicroservice(metaData))
.collect(Collectors.toSet());
}

/**
* Gets a provider based on the interface or class specification.
* Usually ancestors of {@link SilverService} are used for the query.
* The first class from the registry that meets the query is returned.
*
* @param clazz An interface or class the implementation of which we are looking for.
* @return The appropriate Microservice provider if it exists, null otherwise.
*/
public SilverService getProvider(final Class<? extends SilverService> clazz) {
for (Map.Entry<String, MicroserviceProvider> entry : providers.entrySet()) {
if (clazz.isAssignableFrom(entry.getValue().getClass())) {
Expand All @@ -98,10 +169,25 @@ public SilverService getProvider(final Class<? extends SilverService> clazz) {
return null;
}

/**
* Gets all providers based on the interface or class specification.
* Usually ancestors of {@link SilverService} are used for the query.
*
* @param clazz An interface or class the implementation of which we are looking for.
* @return A set of appropriate Microservice providers if they exists, an empty set otherwise.
*/
public Set<SilverService> getAllProviders(final Class<? extends SilverService> clazz) {
return providers.entrySet().stream().filter(entry -> clazz.isAssignableFrom(entry.getValue().getClass())).map(entry -> (SilverService) entry.getValue()).collect(Collectors.toSet());
}

/**
* Makes that there are handles created for all the local services that meet the given the query.
* Only local Microservices are searched as we cannot created inbound handles for remote Microservices
* (we do not want to just pass through calls).
*
* @param metaData The query for which to look up the service handles.
* @return A list of {@link ServiceHandle Service Handles} that meet the specified query.
*/
public List<ServiceHandle> assureHandles(final MicroserviceMetaData metaData) {
List<ServiceHandle> result = inboundHandles.stream().filter(serviceHandle -> serviceHandle.getQuery().equals(metaData)).collect(Collectors.toList());
Set<Object> microservices = lookupLocalMicroservice(metaData);
Expand All @@ -118,6 +204,11 @@ public List<ServiceHandle> assureHandles(final MicroserviceMetaData metaData) {
return result;
}

/**
* Gets the {@link ServiceHandle} for the given handle number.
* @param handle The handle number.
* @return The {@link ServiceHandle} with the given handle number.
*/
public ServiceHandle getInboundServiceHandle(final int handle) {
return inboundHandles.stream().filter(serviceHandle -> serviceHandle.getHandle() == handle).findFirst().get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,29 +37,77 @@
import java.util.concurrent.atomic.AtomicInteger;

/**
* The main Microservice provider that starts all other providers.
*
* @author Martin Večeřa <[email protected]>
*/
public class Executor implements MicroserviceProvider {

/**
* Logger.
*/
private static final Logger log = LogManager.getLogger(Executor.class);

/**
* Instances of all discovered Microservice providers.
*/
private final List<MicroserviceProvider> instances = new ArrayList<>();

/**
* Pool of threads - each of the providers runs the main code in its own thread.
*/
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(new DaemonThreadFactory());

/**
* Statistics about deployed providers.
*/
private final DeployStats stats = new DeployStats();

/**
* Context for this instance.
*/
private Context context = null;

/**
* A {@link ThreadFactory} to create daemon threads with a nice name and slightly higher priority.
*/
static class DaemonThreadFactory implements ThreadFactory {

/**
* Static counter of thread pools.
*/
private static final AtomicInteger poolNumber = new AtomicInteger(1);

/**
* Thread group of this factory.
*/
private final ThreadGroup group;

/**
* Counter of the threads in this pool.
*/
private final AtomicInteger threadNumber = new AtomicInteger(1);

/**
* Name prefix for the threads in this pool.
*/
private final String namePrefix;

/**
* Creates a new factory with a nice name perfix and group name.
*/
DaemonThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "SilverWare-" + poolNumber.getAndIncrement() + "-microservice-provider-";
}

/**
* Creates new daemon thread with higher priority.
*
* @param r Runnable for which the thread should be created-
* @return The new thread.
*/
public Thread newThread(final Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
t.setDaemon(true);
Expand All @@ -68,11 +116,24 @@ public Thread newThread(final Runnable r) {
}
}

/**
* The main entry point to the platform.
* This creates a default empty context.
*
* @throws InterruptedException If the main thread fails for any reason.
*/
public static void bootHook() throws InterruptedException {
final Context context = new Context();
bootHook(context);
}

/**
* The main entry point to the platform.
* Uses an already created context.
*
* @param initialContext The context associated with this platform instance.
* @throws InterruptedException If the main thread fails for any reason.
*/
public static void bootHook(final Context initialContext) throws InterruptedException {
final Executor executor = new Executor();
executor.initialize(initialContext);
Expand All @@ -83,6 +144,12 @@ public static void bootHook(final Context initialContext) throws InterruptedExce
bootThread.join();
}

/**
* Creates instances of the Microservice provider classes using reflection.
* Also counts statistics of the created instances.
*
* @param microserviceProviders A set of Microservice provider classes to create their instances.
*/
private void createInstances(final Set<Class<? extends MicroserviceProvider>> microserviceProviders) {
log.info(String.format("Found %d microservice providers. Starting...", microserviceProviders.size()));
stats.setFound(microserviceProviders.size());
Expand Down Expand Up @@ -112,6 +179,9 @@ private void createInstances(final Set<Class<? extends MicroserviceProvider>> mi
}
}

/**
* Starts the instances of prepared Microservice providers.
*/
private void startInstances() {
log.info("Running microservice providers...");

Expand All @@ -134,6 +204,11 @@ public void initialize(final Context context) {
context.getProvidersRegistry().put(this.getClass().getName(), this);
}

/**
* Searches for Microservice providers, creates their instances and starts them.
* Continues execution as long as there are any active providers.
*/
@Override
public void run() {
log.info("Looking up microservice providers...");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@
package org.silverware.microservices.silver;

/**
* Makes it possible to instantiate Camel routes automatically.
*
* @author Martin Večeřa <[email protected]>
*/
public interface CamelSilverService extends ProvidingSilverService {

/**
* Context property where the Camel context is stored.
*/
String CAMEL_CONTEXT = "silverware.camel.camelContext";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@
package org.silverware.microservices.silver;

/**
* CDI Microservices deployer.
*
* @author Martin Večeřa <[email protected]>
*/
public interface CdiSilverService extends ProvidingSilverService {

/**
* Context property where the bean manager is stored.
*/
String BEAN_MANAGER = "silverware.cdi.beanManager";

/**
* Context property where the CDI container is stored.
*/
String CDI_CONTAINER = "silverware.cdi.container";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,21 @@
package org.silverware.microservices.silver;

/**
* Makes it possible for the platforms to discover each other in a cluster.
* Can lookup services on other instances. Kepps handles to remote services.
*
* @author Martin Večeřa <[email protected]>
*/
public interface ClusterSilverService extends SilverService {

/**
* Property with the cluster group name.
*/
String CLUSTER_GROUP = "silverware.cluster.group";

/**
* Property with the cluster configuration name.
*/
String CLUSTER_CONFIGURATION = "silverware.cluster.configuration";

}
Loading

0 comments on commit c96088d

Please sign in to comment.