Skip to content

Commit

Permalink
[SilverThings#34] Added semantic version resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
SlavoKrupa committed Nov 5, 2016
1 parent 9beef8e commit 1d85099
Show file tree
Hide file tree
Showing 29 changed files with 920 additions and 283 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* -----------------------------------------------------------------------\
* SilverWare
*
* Copyright (C) 2010 - 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* -----------------------------------------------------------------------/
*/
package io.silverware.microservices.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* This annotation can be used in two different scenarios:
* <ul>
* <li><strong>Microservice:</strong> can specify version of Microservice Implementation and API. </li>
* <li><strong>Injection point:</strong> can specify supported version of a Microservice API. </li>
* </ul>
* These versions are used in the lookup of the Microservices in the cluster.
* See @{@link io.silverware.microservices.providers.cdi.util.VersionResolver}
*
* @author Slavomír Krupa ([email protected])
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Target({ ElementType.TYPE })
public @interface MicroserviceVersion {

/**
* Gets the API version of the Microservice.
*/
String api() default "";

/**
* Gets the implementation version of the Microservice.
*/
String implementation() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.silverware.microservices.MicroserviceMetaData;
import io.silverware.microservices.annotations.Microservice;
import io.silverware.microservices.annotations.MicroserviceReference;
import io.silverware.microservices.annotations.MicroserviceVersion;
import io.silverware.microservices.providers.MicroserviceProvider;
import io.silverware.microservices.providers.cdi.builtin.Configuration;
import io.silverware.microservices.providers.cdi.builtin.CurrentContext;
Expand All @@ -33,12 +34,19 @@
import io.silverware.microservices.providers.cdi.internal.RestInterface;
import io.silverware.microservices.silver.CdiSilverService;
import io.silverware.microservices.util.Utils;
import io.silverware.microservices.util.VersionComparator;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Priority;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
Expand All @@ -50,13 +58,6 @@
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* @author <a href="mailto:[email protected]">Martin Večeřa</a>
*/
Expand Down Expand Up @@ -140,15 +141,18 @@ public void run() {

@SuppressWarnings("checkstyle:JavadocMethod")
public Set<Object> lookupMicroservice(final MicroserviceMetaData microserviceMetaData) {
// name can not be null - contract of MicroserviceMetaData
final String name = microserviceMetaData.getName();
final Class<?> type = microserviceMetaData.getType();
final Set<Annotation> qualifiers = microserviceMetaData.getQualifiers();
final String apiVersion = microserviceMetaData.getApiVersion();
final Set<Object> matchingBeansByName = new HashSet<>();
final Set<Object> matchingBeansByType = new HashSet<>();
boolean wasAlternative = false;

/*
We are in search for a CDI bean that meets the provided meta-data.
If there is a MicroserviceVersion annotation and it is not matching the version in metadata we skip that bean automatically.
Input and corresponding output is as follows:
* name specified in MicroserviceReference or derived from data type (both class or interface)
* beans having the same name in Microservice annotation
Expand All @@ -163,33 +167,39 @@ public Set<Object> lookupMicroservice(final MicroserviceMetaData microserviceMet
for (Bean<?> bean : beans) {
if (bean.getBeanClass().isAnnotationPresent(Microservice.class) && !(bean instanceof MicroserviceProxyBean)) {
final Bean<?> theBean = beanManager.resolve(Collections.singleton(bean));

if (theBean.getBeanClass().isAnnotationPresent(MicroserviceVersion.class)) {
final MicroserviceVersion versionAnnotation = theBean.getBeanClass().getAnnotation(MicroserviceVersion.class);
String implementationVersion = versionAnnotation.implementation();
if (!VersionComparator.forVersion(implementationVersion).satisfies(apiVersion)) {
continue;
}
}
final Microservice microserviceAnnotation = theBean.getBeanClass().getAnnotation(Microservice.class);

if (name != null) {
if ((!microserviceAnnotation.value().isEmpty() && name.equals(microserviceAnnotation.value())) ||
(microserviceAnnotation.value().isEmpty() && name.equals(theBean.getName()))) {
matchingBeansByName.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
} else if (type.isAssignableFrom(theBean.getBeanClass())) {
final Set<Annotation> qualifiersToCompare = new HashSet<>(theBean.getQualifiers());
qualifiers.stream().forEach(qualifiersToCompare::remove);

if (qualifiersToCompare.size() == 0) {

if (bean.isAlternative()) {
if (!wasAlternative) {
matchingBeansByType.clear();
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
wasAlternative = true;
} else {
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
throw new IllegalStateException(String.format("There are more than alternate beans matching the query: %s. The beans are: %s.", microserviceMetaData.toString(), matchingBeansByType.toString()));
}
if ((!microserviceAnnotation.value().isEmpty() && name.equals(microserviceAnnotation.value())) ||
(microserviceAnnotation.value().isEmpty() && name.equals(theBean.getName()))) {
matchingBeansByName.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
} else if (type.isAssignableFrom(theBean.getBeanClass())) {
final Set<Annotation> qualifiersToCompare = new HashSet<>(theBean.getQualifiers());
qualifiers.stream().forEach(qualifiersToCompare::remove);

if (qualifiersToCompare.size() == 0) {

if (bean.isAlternative()) {
if (!wasAlternative) {
matchingBeansByType.clear();
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
wasAlternative = true;
} else {
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
throw new IllegalStateException(String.format("There are more than alternate beans matching the query: %s. The beans are: %s.", microserviceMetaData.toString(), matchingBeansByType.toString()));
}
} else {
if (!wasAlternative) {
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
} else {
if (!wasAlternative) {
matchingBeansByType.add(beanManager.getReference(theBean, type, beanManager.createCreationalContext(theBean)));
} else {
// ignore this bean
}
// ignore this bean
}
}
}
Expand Down Expand Up @@ -229,7 +239,7 @@ public <T> T lookupBean(final Class<T> type) {
@Override
public <T> T findByType(Class<T> type) {
BeanManager beanManager = (BeanManager) context.getProperties().get(BEAN_MANAGER);
Set<T> beans = new HashSet<T>();
Set<T> beans = new HashSet<>();
Set<Bean<?>> definitions = beanManager.getBeans(type);
Bean<?> bean = beanManager.resolve(definitions);
CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean);
Expand Down Expand Up @@ -265,7 +275,7 @@ public Object log(final InvocationContext ic) throws Exception {
}
}

@SuppressWarnings({"unused", "checkstyle:JavadocType"})
@SuppressWarnings({ "unused", "checkstyle:JavadocType" })
@Microservice
public static class SilverWareConfiguration implements Configuration {

Expand All @@ -281,7 +291,7 @@ public void eventObserver(@Observes MicroservicesInitEvent event) {
}
}

@SuppressWarnings({"unused", "unchecked", "checkstyle:JavadocType"})
@SuppressWarnings({ "unused", "unchecked", "checkstyle:JavadocType" })
@Microservice
public static class SilverWareStorage implements Storage {

Expand Down Expand Up @@ -311,7 +321,7 @@ public void eventObserver(@Observes MicroservicesInitEvent event) {
}
}

@SuppressWarnings({"unused", "checkstyle:JavadocMethod"})
@SuppressWarnings({ "unused", "checkstyle:JavadocMethod" })
@Microservice
public static class SilverWareCurrentContext implements CurrentContext {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
*/
package io.silverware.microservices.providers.cdi.internal;

import io.silverware.microservices.MicroserviceMetaData;
import io.silverware.microservices.annotations.MicroserviceReference;
import io.silverware.microservices.providers.cdi.util.VersionResolver;
import io.silverware.microservices.silver.services.LookupStrategy;
import io.silverware.microservices.silver.services.LookupStrategyFactory;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand All @@ -28,11 +34,6 @@
import java.util.stream.Collectors;
import javax.annotation.Priority;

import io.silverware.microservices.MicroserviceMetaData;
import io.silverware.microservices.annotations.MicroserviceReference;
import io.silverware.microservices.silver.services.LookupStrategy;
import io.silverware.microservices.silver.services.LookupStrategyFactory;

/**
* Default microservice method handler which is invoked as the last one and makes an actual call on the service instance.
*/
Expand All @@ -47,9 +48,8 @@ public class DefaultMethodHandler extends MicroserviceMethodHandler {

protected DefaultMethodHandler(final MicroserviceProxyBean proxyBean) throws Exception {
this.proxyBean = proxyBean;

final Set<Annotation> qualifiers = proxyBean.getQualifiers().stream().filter(qualifier -> !qualifier.annotationType().getName().equals(MicroserviceReference.class.getName())).collect(Collectors.toSet());
final MicroserviceMetaData metaData = new MicroserviceMetaData(proxyBean.getMicroserviceName(), proxyBean.getServiceInterface(), qualifiers, proxyBean.getAnnotations());
final MicroserviceMetaData metaData = VersionResolver.createMicroserviceMetadata(proxyBean.getMicroserviceName(), proxyBean.getServiceInterface(), qualifiers, proxyBean.getAnnotations());

this.lookupStrategy = LookupStrategyFactory.getStrategy(proxyBean.getContext(), metaData, proxyBean.getAnnotations());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.silverware.microservices.annotations.Microservice;
import io.silverware.microservices.annotations.MicroserviceReference;
import io.silverware.microservices.providers.cdi.MicroserviceContext;
import io.silverware.microservices.providers.cdi.util.VersionResolver;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -93,10 +94,8 @@ public MicroservicesCDIExtension(final Context context, final RestInterface rest
/**
* {@link javax.enterprise.inject.spi.BeforeBeanDiscovery} CDI event observer.
*
* @param beforeEvent
* CDI Event instance.
* @param beanManager
* CDI Bean Manager instance.
* @param beforeEvent CDI Event instance.
* @param beanManager CDI Bean Manager instance.
*/
public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery beforeEvent, BeanManager beanManager) {
if (log.isDebugEnabled()) {
Expand All @@ -107,10 +106,8 @@ public void beforeBeanDiscovery(@Observes BeforeBeanDiscovery beforeEvent, BeanM
/**
* {@link javax.enterprise.inject.spi.ProcessBean} CDI event observer.
*
* @param processBean
* CDI Event instance.
* @param beanManager
* CDI Bean Manager instance.
* @param processBean CDI Event instance.
* @param beanManager CDI Bean Manager instance.
*/
public void processBean(@Observes final ProcessBean processBean, final BeanManager beanManager) {
final Bean<?> bean = processBean.getBean();
Expand Down Expand Up @@ -167,8 +164,7 @@ private Set<Annotation> preProcessQualifiers(final Set<Annotation> qualifiers) {
/**
* {@link javax.enterprise.inject.spi.ProcessBean} CDI event observer.
*
* @param afterEvent
* CDI Event instance.
* @param afterEvent CDI Event instance.
*/
public void afterBeanDiscovery(@Observes final AfterBeanDiscovery afterEvent) {
afterEvent.addContext(new MicroserviceContext());
Expand Down Expand Up @@ -227,6 +223,7 @@ private void addClientProxyBean(final String microserviceName, final Class<?> be

/**
* Gets the number of discovered injection points.
*
* @return The number of discovered injection points.
*/
public long getInjectionPointsCount() {
Expand All @@ -235,13 +232,14 @@ public long getInjectionPointsCount() {

/**
* Gets a new {@link MicroserviceMetaData} descriptor based on the provided CDI bean.
*
* @param microserviceName The Microservice name.
* @param bean The CDI Bean.
* @param bean The CDI Bean.
* @return Microservice meta-data.
*/
private MicroserviceMetaData getMicroserviceMetaData(final String microserviceName, final Bean<?> bean) {
return new MicroserviceMetaData(microserviceName, bean.getBeanClass(), bean.getQualifiers(), new HashSet<>(
Arrays.asList(bean.getBeanClass().getAnnotations())));
return VersionResolver.createMicroserviceMetadata(microserviceName, bean.getBeanClass(), bean.getQualifiers(), new HashSet<>(
Arrays.asList(bean.getBeanClass().getAnnotations())));
}

/**
Expand Down
Loading

0 comments on commit 1d85099

Please sign in to comment.