-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/constructor level injection #126
Conversation
core/classpath.txt
Outdated
@@ -0,0 +1 @@ | |||
/Applications/activator-dist-1.3.7/repository/com.google.guava/guava/18.0/bundles/guava.jar:/Users/afrieze/.ivy2/cache/com.fasterxml.jackson.core/jackson-databind/bundles/jackson-databind-2.7.3.jar:/Users/afrieze/.ivy2/cache/com.fasterxml.jackson.core/jackson-annotations/bundles/jackson-annotations-2.7.0.jar:/Users/afrieze/.ivy2/cache/com.fasterxml.jackson.core/jackson-core/bundles/jackson-core-2.7.3.jar:/Users/afrieze/.ivy2/cache/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/bundles/jackson-datatype-jsr310-2.7.3.jar:/Users/afrieze/.ivy2/cache/ch.qos.logback/logback-classic/jars/logback-classic-1.0.13.jar:/Users/afrieze/.ivy2/cache/ch.qos.logback/logback-core/jars/logback-core-1.0.13.jar:/Users/afrieze/.ivy2/cache/org.slf4j/slf4j-api/jars/slf4j-api-1.7.5.jar:/Users/afrieze/.ivy2/cache/org.reflections/reflections/jars/reflections-0.9.10.jar:/Applications/activator-dist-1.3.7/repository/org.javassist/javassist/3.18.2-GA/bundles/javassist.jar:/Users/afrieze/.ivy2/cache/com.google.code.findbugs/annotations/jars/annotations-2.0.1.jar:/Applications/activator-dist-1.3.7/repository/javax.inject/javax.inject/1/jars/javax.inject.jar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be ignored or deleted, right?
public void jsonConstructorInjection() throws Exception { | ||
ConsumerService service = new ConsumerService(ServiceBeanResolver.class); | ||
Consumer test = new Consumer(ConstructorJsonConsumer.class, forklift, this.getClass().getClassLoader()); | ||
test.setServices(Arrays.asList(service)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a little cleaner as addServices
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Also, maybe it'd be nice to test service-based injection separately from forklift-based injection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth considering a refactor where the injection code is removed from the consumer entirely(this is what I started to do initially).
The setServices method was already in place and I tried to stick with adding the new functionality and not go down a refactoring rabbit hole.
@@ -1,15 +1,18 @@ | |||
package forklift; | |||
package forklift.consumer.injection; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, it's not all injection tests!
@@ -213,7 +222,7 @@ else if (queue != null) | |||
log.info("Creating thread pool of {}", multiThreaded.value()); | |||
blockQueue = new ArrayBlockingQueue<>(multiThreaded.value() * 100 + 100); | |||
threadPool = new ThreadPoolExecutor( | |||
multiThreaded.value(), multiThreaded.value(), 5L, TimeUnit.MINUTES, blockQueue); | |||
multiThreaded.value(), multiThreaded.value(), 5L, TimeUnit.MINUTES, blockQueue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That indentation seems a bit excessive.
Constructor<?>[] constructors = msgHandler.getDeclaredConstructors(); | ||
for (Constructor<?> constructor : constructors) { | ||
if (constructor.isAnnotationPresent(Inject.class)) { | ||
this.constructor = constructor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth it to log an error or warning (realistically, logging an error is more immediately useful) when there are multiple constructors annotated with @Inject
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Object[] parameters = new Object[constructorAnnotations.length]; | ||
int index = 0; | ||
for (Annotation[] parameterAnnotations : constructorAnnotations) { | ||
//there must be at least one annotation that indicates what we should inject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except not, right? If there's no annotation you still handle it fine by treating it like it has Inject
// Try to resolve the class from any available BeanResolvers. | ||
for (ConsumerService s : this.services) { | ||
try { | ||
final Object o = s.resolve(mappedClass, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we don't want name-based resolution? I guess it's worked so far, but isn't it a bit limiting to be unable to distinguish objects of the same type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm avoiding making changes to the existing functionality.
break; | ||
} | ||
} catch (Exception e) { | ||
log.debug("", e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this was existing code, but aren't errors like "failed to autowire dependency" pretty useful?
public Class<?> getMsgHandler() { | ||
return msgHandler; | ||
} | ||
|
||
/** | ||
* Creates an instance of hte MessageHandler class utilized by this constructor. Constructor and Field level injection is performed using both the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"hte"
@@ -242,11 +251,12 @@ public void messageLoop(ForkliftConsumerI consumer) { | |||
ForkliftMessage consumerMsg; | |||
while ((consumerMsg = consumer.receive(2500)) != null && running.get()) { | |||
try { | |||
final Object handler = msgHandler.newInstance(); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really a fan of newlines at the start of a block
|
||
/** | ||
* Inject the data from a forklift message into an instance of the msgHandler class. | ||
* @param msg containing data | ||
* | ||
* @param msg containing data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't really improve the vague documentation to add some spaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the space is to align with the param below that isn't shown :(
return parameters; | ||
} | ||
|
||
private Object getInjectableValue(Annotation decorator, String mappedName, Class<?> mappedClass, ForkliftMessage msg) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought for later: maybe this could be separated out better with a map of handlers or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -362,112 +384,12 @@ public void setOutOfMessages(java.util.function.Consumer<Consumer> outOfMessages | |||
fields.get(clazz).forEach(f -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we take this opportunity to not call this variable f
?
* | ||
* @param msg | ||
*/ | ||
public Object getMsgHandlerInstance(ForkliftMessage msg) throws InvocationTargetException, IOException, InstantiationException, IllegalAccessException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this method just public for internal testing, or what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Copying how the inject method and testing works.
* | ||
* @param msg | ||
*/ | ||
public Object getMsgHandlerInstance(ForkliftMessage msg) throws InvocationTargetException, IOException, InstantiationException, IllegalAccessException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't imagine most callers to these methods having a meaningful way of handling all of these exceptions differently. Maybe just wrap them in one exception?
Probably even let it be unchecked; 'cause fail-fast
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. The "Inject" method throws a runtime exception so I'l do the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly just some minor nits; with a few changes should be good to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
P.S. But there's still an indentation problem, please fix it
Fix Tests on Travis and Circle CI
cee304d
to
1ad6e4f
Compare
Added constructor injection for consumers.
Note: I thought about pulling this functionality out into its own set of classes, or even incorporating an existing DI framework. I decided that was a bit more than I wanted to take on right now and kept code changes to a minimum. Could be considerations for the future though.