Skip to content
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

Use inject for non singleton class #1617

Merged
merged 34 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
100b54e
comment to start branch
jorg3lopez Nov 4, 2024
b5ddf86
getFieldsAnnotatedWithInstance helper method
jorg3lopez Nov 25, 2024
c0bd221
todo comment deleted
jorg3lopez Nov 25, 2024
4ddefce
injectIntoField overloaded method
jorg3lopez Nov 25, 2024
ee807ea
injectIntoNonSingleton
jorg3lopez Nov 25, 2024
740f79d
access modifier protected to public
jorg3lopez Nov 25, 2024
006212e
revert access modifier change
jorg3lopez Nov 25, 2024
067eba4
changes:
jorg3lopez Nov 25, 2024
3d9c4f1
Added implementors unit test to ApplicationContextTest
jorg3lopez Nov 26, 2024
19102d8
Merge branch 'main' into use-inject-for-non-singleton-class
luis-pabon-tf Nov 26, 2024
be48aed
Merge remote-tracking branch 'refs/remotes/origin/use-inject-for-non-…
jorg3lopez Nov 26, 2024
875b86b
Minor refactoring on some AppContext injection methods
luis-pabon-tf Nov 26, 2024
4adaa27
Make the skip flag on TestApplicationContext switchable from the test…
luis-pabon-tf Nov 26, 2024
c46e4e1
Merge branch 'main' into use-inject-for-non-singleton-class
luis-pabon-tf Dec 2, 2024
ff4781a
Update ApplicationContext.java
luis-pabon-tf Dec 3, 2024
e5d184d
Update TestApplicationContext.groovy
luis-pabon-tf Dec 3, 2024
083ddb4
Update TestApplicationContext.groovy
luis-pabon-tf Dec 3, 2024
0ac729e
added unit tests to cover new code
jorg3lopez Dec 4, 2024
18c2f48
Update ApplicationContextTest.groovy
luis-pabon-tf Dec 5, 2024
a533d0d
Merge pull request #1639 from CDCgov/application_context_fix_unreacha…
luis-pabon-tf Dec 5, 2024
88d128e
Merge branch 'main' into use-inject-for-non-singleton-class
luis-pabon-tf Dec 5, 2024
2d1864c
Merge branch 'use-inject-for-non-singleton-class' of https://github.c…
luis-pabon-tf Dec 5, 2024
51af9ab
Update ApplicationContext.java
luis-pabon-tf Dec 9, 2024
8894b15
Merge branch 'main' into use-inject-for-non-singleton-class
luis-pabon-tf Dec 9, 2024
0f9bdb4
Merge branch 'main' into use-inject-for-non-singleton-class
jorg3lopez Dec 11, 2024
a1ab899
use return instead of System.err
jorg3lopez Dec 12, 2024
5672dcc
refactoring - dry
jorg3lopez Dec 12, 2024
e9f6e02
thown(NullPointerException) -> noExceptionThrown()
jorg3lopez Dec 12, 2024
ba81073
added comments to indicate changes that will be deleted
jorg3lopez Dec 12, 2024
c3cce16
deleted commented out code
jorg3lopez Dec 12, 2024
dde8378
Merge branch 'main' into use-inject-for-non-singleton-class
jorg3lopez Dec 12, 2024
2e81fd8
Merge branch 'main' into use-inject-for-non-singleton-class
jorg3lopez Dec 12, 2024
f8f6e5b
reinstated comments for test case
jorg3lopez Dec 12, 2024
37a57fa
deleted test changes:
jorg3lopez Dec 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ protected static void injectRegisteredImplementations(boolean skipMissingImpleme
fields.forEach(field -> injectIntoField(field, skipMissingImplementations));
}

public static void injectIntoNonSingleton(Object instance) {
var fields = Reflection.getFieldsAnnotatedWithInstance(instance.getClass(), Inject.class);

fields.forEach(field -> injectIntoField(field, instance, false));
}

private static void injectIntoField(
Field field, Object instance, boolean skipMissingImplementations) {
var fieldType = field.getType();

Object fieldImplementation = getFieldImplementation(fieldType, skipMissingImplementations);
if (fieldImplementation == null) {
return;
}

field.trySetAccessible();
try {
field.set(instance, fieldImplementation);
} catch (IllegalAccessException | IllegalArgumentException exception) {
throw new IllegalArgumentException(
jorg3lopez marked this conversation as resolved.
Show resolved Hide resolved
"unable to inject " + fieldType + " into " + instance.getClass(), exception);
}
}

private static void injectIntoField(Field field, boolean skipMissingImplementations) {
var fieldType = field.getType();
var declaringClass = field.getDeclaringClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import static org.reflections.scanners.Scanners.FieldsAnnotated;
import static org.reflections.scanners.Scanners.SubTypes;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.reflections.Reflections;

/**
Expand All @@ -27,4 +30,10 @@ public static <T> Set<Class<? extends T>> getImplementors(Class<T> interfaze) {
public static Set<Field> getFieldsAnnotatedWith(Class<?> annotation) {
return REFLECTIONS.get(FieldsAnnotated.with(annotation).as(Field.class));
}

public static Set<Field> getFieldsAnnotatedWithInstance(Class<?> clazz, Class<?> annotation) {
return Arrays.stream(clazz.getDeclaredFields())
.filter(field -> field.isAnnotationPresent(annotation.asSubclass(Annotation.class)))
.collect(Collectors.toSet());
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
package gov.hhs.cdc.trustedintermediary.external.hapi;

import gov.hhs.cdc.trustedintermediary.context.ApplicationContext;
import gov.hhs.cdc.trustedintermediary.wrappers.HealthData;
import gov.hhs.cdc.trustedintermediary.wrappers.Logger;
import javax.inject.Inject;
import org.hl7.fhir.instance.model.api.IBaseResource;

/** An implementation of {@link HealthData} to use as a wrapper around HAPI FHIR IBaseResource */
public class HapiFhirResource implements HealthData<IBaseResource> {

@Inject private Logger logger;
private final IBaseResource innerResource;

public HapiFhirResource(IBaseResource innerResource) {
ApplicationContext.injectIntoNonSingleton(this);
jorg3lopez marked this conversation as resolved.
Show resolved Hide resolved
this.innerResource = innerResource;
}

@Override
public IBaseResource getUnderlyingData() {
this.logger.logDebug("testing @Inject");
jorg3lopez marked this conversation as resolved.
Show resolved Hide resolved
return innerResource;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package gov.hhs.cdc.trustedintermediary.external.hapi

import gov.hhs.cdc.trustedintermediary.context.TestApplicationContext
import gov.hhs.cdc.trustedintermediary.wrappers.Logger
import org.hl7.fhir.r4.model.Bundle
import spock.lang.Specification

class HapiFhirResourceTest extends Specification {
jorg3lopez marked this conversation as resolved.
Show resolved Hide resolved

def mockLogger = Mock(Logger)
def setup() {
TestApplicationContext.reset()
TestApplicationContext.init()
TestApplicationContext.register(Logger, mockLogger)
}

def "sample test run to see if logger is injected"() {
given:
def expectedBundle = new Bundle()
when:
def resource = new HapiFhirResource(expectedBundle)
def actualBundle = resource.getUnderlyingData()
then:
expectedBundle == actualBundle
}
}