forked from SilverThings/SilverWare
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use plug-in method handlers in microservice proxies
- Loading branch information
1 parent
b7164c2
commit 742640d
Showing
5 changed files
with
254 additions
and
113 deletions.
There are no files selected for viewing
96 changes: 96 additions & 0 deletions
96
...rc/main/java/io/silverware/microservices/providers/cdi/internal/DefaultMethodHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* -----------------------------------------------------------------------\ | ||
* SilverWare | ||
* | ||
* Copyright (C) 2016 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.providers.cdi.internal; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Method; | ||
import java.util.Set; | ||
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. | ||
*/ | ||
@Priority(Integer.MAX_VALUE) | ||
public class DefaultMethodHandler extends MicroserviceMethodHandler { | ||
|
||
private static final Logger log = LogManager.getLogger(DefaultMethodHandler.class); | ||
|
||
private final MicroserviceProxyBean proxyBean; | ||
|
||
private final LookupStrategy lookupStrategy; | ||
|
||
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()); | ||
|
||
this.lookupStrategy = LookupStrategyFactory.getStrategy(proxyBean.getContext(), metaData, proxyBean.getAnnotations()); | ||
} | ||
|
||
private synchronized Object getService() { | ||
final Object service = lookupStrategy.getService(); | ||
|
||
if (log.isDebugEnabled()) { | ||
log.debug(String.format("Proxy %s matched with service implementation %s.", this.toString(), service)); | ||
} | ||
|
||
return service; | ||
} | ||
|
||
@Override | ||
public Object invoke(final Method method, final Object[] args) throws Exception { | ||
if (method.getDeclaringClass() == Object.class) { | ||
final String methodName = method.getName(); | ||
final int paramCount = method.getParameterTypes().length; | ||
|
||
if ("toString".equals(methodName) && paramCount == 0) { | ||
return "Microservices proxy for " + proxyBean.getServiceInterface().getName(); | ||
} else if ("equals".equals(methodName) && paramCount == 1) { | ||
return this.equals(args[0]); | ||
} else if ("hashCode".equals(methodName) && paramCount == 0) { | ||
return this.hashCode(); | ||
} else if ("getClass".equals(methodName) && paramCount == 0) { | ||
return proxyBean.getServiceInterface(); | ||
} | ||
} | ||
|
||
if (log.isDebugEnabled()) { | ||
log.debug("Invocation of " + method); | ||
} | ||
|
||
Object service = getService(); | ||
return method.invoke(service, args); | ||
} | ||
|
||
@Override | ||
public MicroserviceProxyBean getProxyBean() { | ||
return proxyBean; | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...in/java/io/silverware/microservices/providers/cdi/internal/MicroserviceMethodHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* -----------------------------------------------------------------------\ | ||
* SilverWare | ||
* | ||
* Copyright (C) 2016 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.providers.cdi.internal; | ||
|
||
import java.lang.reflect.Method; | ||
|
||
import javassist.util.proxy.MethodHandler; | ||
|
||
/** | ||
* Method handler for invoking microservice methods. | ||
* | ||
* Descendants need to have a constructor with a single parameter of type MicroserviceMethodHandler (the next method handler). | ||
* The implementations of methods should call the same method on the next method handler but they can alter its behaviour by making some additional changes. | ||
* Descendants also need to specify the priority on their classes. The higher it is, the later they are invoked (closer to the actual service call). | ||
* | ||
* @see javax.annotation.Priority | ||
*/ | ||
public abstract class MicroserviceMethodHandler implements MethodHandler { | ||
|
||
public static final int DEFAULT_PRIORITY = 100; | ||
|
||
@Override | ||
public final Object invoke(final Object self, final Method thisMethod, final Method proceed, final Object[] args) throws Throwable { | ||
return invoke(thisMethod, args); | ||
} | ||
|
||
public abstract Object invoke(Method method, Object[] args) throws Exception; | ||
|
||
public abstract MicroserviceProxyBean getProxyBean(); | ||
|
||
} |
111 changes: 0 additions & 111 deletions
111
...r/src/main/java/io/silverware/microservices/providers/cdi/internal/MicroserviceProxy.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
...ain/java/io/silverware/microservices/providers/cdi/internal/MicroserviceProxyFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* -----------------------------------------------------------------------\ | ||
* SilverWare | ||
* | ||
* Copyright (C) 2016 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.providers.cdi.internal; | ||
|
||
import org.reflections.Reflections; | ||
import org.reflections.scanners.ResourcesScanner; | ||
import org.reflections.util.ConfigurationBuilder; | ||
|
||
import java.lang.reflect.Constructor; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import javax.annotation.Priority; | ||
|
||
import javassist.util.proxy.MethodHandler; | ||
import javassist.util.proxy.ProxyFactory; | ||
|
||
/** | ||
* Creates a proxy for invoking microservice methods. | ||
* | ||
* A classpath is searched for additional method handlers which are executed before DefaultMethodHandler ordered by their priority. | ||
* | ||
* @see io.silverware.microservices.providers.cdi.internal.MicroserviceMethodHandler | ||
* @see io.silverware.microservices.providers.cdi.internal.DefaultMethodHandler | ||
*/ | ||
public class MicroserviceProxyFactory { | ||
|
||
private static final List<Class<? extends MicroserviceMethodHandler>> HANDLER_CLASSES; | ||
|
||
static { | ||
ConfigurationBuilder builder = ConfigurationBuilder.build("").addScanners(new ResourcesScanner()); | ||
Reflections reflections = new Reflections(builder); | ||
|
||
HANDLER_CLASSES = reflections.getSubTypesOf(MicroserviceMethodHandler.class) | ||
.stream() | ||
.filter(handler -> handler != DefaultMethodHandler.class) | ||
.sorted(new MethodHandlerPrioritizer()) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private MicroserviceProxyFactory() { | ||
} | ||
|
||
/** | ||
* Creates a proxy for a given proxy bean. | ||
* | ||
* @param proxyBean | ||
* proxy bean for which a proxy is being created | ||
* @param <T> | ||
* provided service type | ||
* @return proxy | ||
*/ | ||
public static <T> T createProxy(final MicroserviceProxyBean proxyBean) { | ||
try { | ||
ProxyFactory factory = new ProxyFactory(); | ||
if (proxyBean.getServiceInterface().isInterface()) { | ||
factory.setInterfaces(new Class[] { proxyBean.getServiceInterface() }); | ||
} else { | ||
factory.setSuperclass(proxyBean.getServiceInterface()); | ||
} | ||
MethodHandler methodHandler = createMethodHandler(proxyBean); | ||
return (T) factory.create(new Class[0], new Object[0], methodHandler); | ||
} catch (Exception e) { | ||
throw new IllegalStateException("Cannot create proxy for class " + proxyBean.getServiceInterface().getName() + ": ", e); | ||
} | ||
} | ||
|
||
private static MethodHandler createMethodHandler(MicroserviceProxyBean parentBean) throws Exception { | ||
MicroserviceMethodHandler methodHandler = new DefaultMethodHandler(parentBean); | ||
for (Class<? extends MicroserviceMethodHandler> handlerClass : HANDLER_CLASSES) { | ||
final Constructor c = handlerClass.getConstructor(MicroserviceMethodHandler.class); | ||
methodHandler = (MicroserviceMethodHandler) c.newInstance(methodHandler); | ||
} | ||
return methodHandler; | ||
} | ||
|
||
private static class MethodHandlerPrioritizer implements Comparator<Class<? extends MicroserviceMethodHandler>> { | ||
|
||
@Override | ||
public int compare(final Class<? extends MicroserviceMethodHandler> class1, final Class<? extends MicroserviceMethodHandler> class2) { | ||
return getPriority(class2) - getPriority(class1); | ||
} | ||
|
||
private int getPriority(Class<? extends MicroserviceMethodHandler> methodHandlerClass) { | ||
Priority priority = methodHandlerClass.getAnnotation(Priority.class); | ||
return priority != null ? priority.value() : MicroserviceMethodHandler.DEFAULT_PRIORITY; | ||
} | ||
|
||
} | ||
|
||
} |