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

GraphQL Introspection Support #3348

Merged
merged 23 commits into from
Feb 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion hapi-fhir-base/src/main/java/ca/uhn/fhir/i18n/Msg.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public final class Msg {

/**
* IMPORTANT: Please update the following comment after you add a new code
* Last code value: 2034
* Last code value: 2036
*/

private Msg() {}
Expand Down
24 changes: 24 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/util/MessageSupplier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ca.uhn.fhir.util;

import java.util.function.Supplier;

/**
* This is used to allow lazy parameter initialization for SLF4j - Hopefully
* a future version will allow lambda params
*/
public class MessageSupplier {
private Supplier<?> supplier;

public MessageSupplier(Supplier<?> supplier) {
this.supplier = supplier;
}

@Override
public String toString() {
return supplier.get().toString();
}

public static MessageSupplier msg(Supplier<?> supplier) {
return new MessageSupplier(supplier);
}
}
10 changes: 10 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/util/StringUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* #L%
*/

import javax.annotation.Nonnull;
import java.io.CharArrayWriter;
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
Expand Down Expand Up @@ -105,4 +106,13 @@ public static String left(String theString, int theCodePointCount) {
return theString.substring(0, theString.offsetByCodePoints(0, theCodePointCount));
}

@Nonnull
public static String prependLineNumbers(@Nonnull String theInput) {
StringBuilder schemaOutput = new StringBuilder();
int index = 0;
for (String next : theInput.split("\\n")) {
schemaOutput.append(index++).append(": ").append(next.replace("\r", "")).append("\n");
}
return schemaOutput.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package ca.uhn.fhir.util;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static ca.uhn.fhir.util.MessageSupplier.msg;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class MessageSupplierTest {

private static final Logger ourLog = LoggerFactory.getLogger(MessageSupplierTest.class);
private Appender myMockAppender;
private ch.qos.logback.classic.Logger myLoggerRoot;

@AfterEach
public void after() {
myLoggerRoot.detachAppender(myMockAppender);
}

@SuppressWarnings("unchecked")
@BeforeEach
public void before() {

/*
* This is a bit funky, but it's useful for verifying that the headers actually get logged
*/
myMockAppender = mock(Appender.class);
when(myMockAppender.getName()).thenReturn("MOCK");

Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);

myLoggerRoot = (ch.qos.logback.classic.Logger) logger;
myLoggerRoot.addAppender(myMockAppender);
}


@Test
public void testLog() {

ourLog.info("Hello: {}", msg(() -> "Goodbye"));

verify(myMockAppender, times(1)).doAppend(argThat((ArgumentMatcher<ILoggingEvent>) argument -> {
String formattedMessage = argument.getFormattedMessage();
System.out.flush();
System.out.println("** Got Message: " + formattedMessage);
System.out.flush();
return formattedMessage.equals("Hello: Goodbye");
}));


}


}
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,9 @@ public void testChompCharacter() {
assertEquals("a/a", StringUtil.chompCharacter("a/a////", '/'));
}

@Test
public void testPrependLineNumbers() {
assertEquals("0: A\n1: B\n", StringUtil.prependLineNumbers("A\nB"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
type: add
issue: 3348
title: "The HAPI FHIR server GraphQL endpoints now support GraphQL introspection, making them
much easier to use with GraphQL-capable IDEs."
24 changes: 6 additions & 18 deletions hapi-fhir-jpaserver-base/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,6 @@
<name>HAPI FHIR JPA Server</name>

<dependencies>
<!--
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>${jackson.version}</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
-->

<dependency>
<groupId>com.fasterxml.woodstox</groupId>
Expand Down Expand Up @@ -174,6 +156,12 @@
<artifactId>javassist</artifactId>
</dependency>

<!-- GraphQL -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
</dependency>

<!-- SQL Builder -->
<dependency>
<groupId>com.healthmarketscience.sqlbuilder</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.IDaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.config.GeneratedDaoAndResourceProviderConfigDstu3;
import ca.uhn.fhir.jpa.config.JpaConfig;
import ca.uhn.fhir.jpa.config.SharedConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.ITransactionProcessorVersionAdapter;
import ca.uhn.fhir.jpa.dao.dstu3.TransactionProcessorVersionAdapterDstu3;
import ca.uhn.fhir.jpa.graphql.GraphQLProvider;
import ca.uhn.fhir.jpa.graphql.GraphQLProviderWithIntrospection;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcDstu3;
Expand All @@ -17,6 +19,7 @@
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcDstu3;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Meta;
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
Expand Down Expand Up @@ -62,8 +65,8 @@ public ITermVersionAdapterSvc terminologyVersionAdapterSvc() {

@Bean(name = JpaConfig.GRAPHQL_PROVIDER_NAME)
@Lazy
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport) {
return new GraphQLProvider(theFhirContext, theValidationSupport, theGraphqlStorageServices);
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry, IDaoRegistry theDaoRegistry) {
return new GraphQLProviderWithIntrospection(theFhirContext, theValidationSupport, theGraphqlStorageServices, theSearchParamRegistry, theDaoRegistry);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.IDaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.config.GeneratedDaoAndResourceProviderConfigR4;
import ca.uhn.fhir.jpa.config.JpaConfig;
import ca.uhn.fhir.jpa.config.SharedConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.ITransactionProcessorVersionAdapter;
import ca.uhn.fhir.jpa.dao.r4.TransactionProcessorVersionAdapterR4;
import ca.uhn.fhir.jpa.graphql.GraphQLProvider;
import ca.uhn.fhir.jpa.graphql.GraphQLProviderWithIntrospection;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcR4;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR4;
Expand All @@ -17,6 +19,7 @@
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR4;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Meta;
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
Expand All @@ -26,6 +29,26 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
* %%
* 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.
* #L%
*/

@Configuration
@EnableTransactionManagement
@Import({
Expand All @@ -48,8 +71,8 @@ public ITransactionProcessorVersionAdapter transactionProcessorVersionFacade() {

@Bean(name = JpaConfig.GRAPHQL_PROVIDER_NAME)
@Lazy
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport) {
return new GraphQLProvider(theFhirContext, theValidationSupport, theGraphqlStorageServices);
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry, IDaoRegistry theDaoRegistry) {
return new GraphQLProviderWithIntrospection(theFhirContext, theValidationSupport, theGraphqlStorageServices, theSearchParamRegistry, theDaoRegistry);
}

@Bean(name = "mySystemDaoR4")
Expand Down Expand Up @@ -77,23 +100,3 @@ public ITermReadSvcR4 terminologyService() {
}

}

/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
* %%
* 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.
* #L%
*/
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.jpa.api.IDaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.config.GeneratedDaoAndResourceProviderConfigR5;
import ca.uhn.fhir.jpa.config.JpaConfig;
import ca.uhn.fhir.jpa.config.SharedConfigDstu3Plus;
import ca.uhn.fhir.jpa.dao.ITransactionProcessorVersionAdapter;
import ca.uhn.fhir.jpa.dao.r5.TransactionProcessorVersionAdapterR5;
import ca.uhn.fhir.jpa.graphql.GraphQLProvider;
import ca.uhn.fhir.jpa.graphql.GraphQLProviderWithIntrospection;
import ca.uhn.fhir.jpa.term.TermLoaderSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcR5;
import ca.uhn.fhir.jpa.term.TermVersionAdapterSvcR5;
Expand All @@ -17,6 +19,7 @@
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
import ca.uhn.fhir.jpa.term.api.ITermReadSvcR5;
import ca.uhn.fhir.jpa.term.api.ITermVersionAdapterSvc;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.Meta;
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
Expand Down Expand Up @@ -68,8 +71,8 @@ public ITransactionProcessorVersionAdapter transactionProcessorVersionFacade() {

@Bean(name = JpaConfig.GRAPHQL_PROVIDER_NAME)
@Lazy
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport) {
return new GraphQLProvider(theFhirContext, theValidationSupport, theGraphqlStorageServices);
public GraphQLProvider graphQLProvider(FhirContext theFhirContext, IGraphQLStorageServices theGraphqlStorageServices, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry, IDaoRegistry theDaoRegistry) {
return new GraphQLProviderWithIntrospection(theFhirContext, theValidationSupport, theGraphqlStorageServices, theSearchParamRegistry, theDaoRegistry);
}

@Bean(name = "mySystemDaoR5")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ public IBaseResource fetchStructureDefinition(String theUrl) {
@Nullable
@Override
public <T extends IBaseResource> List<T> fetchAllStructureDefinitions() {
if (!myDaoRegistry.isResourceTypeSupported("StructureDefinition")) {
return null;
}
IBundleProvider search = myDaoRegistry.getResourceDao("StructureDefinition").search(new SearchParameterMap().setLoadSynchronousUpTo(1000));
return (List<T>) search.getResources(0, 1000);
}
Expand Down
Loading