diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml index 4de29d40ece..c918ecdfe50 100644 --- a/hapi-fhir-base/pom.xml +++ b/hapi-fhir-base/pom.xml @@ -63,6 +63,10 @@ org.apache.commons commons-lang3 + + org.apache.commons + commons-text + commons-codec commons-codec diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index 96e7bcc8806..79b26314f3f 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -178,7 +178,7 @@ class ModelScanner { } /** - * There are two implementations of all of the annotations (e.g. {@link Child} and {@link org.hl7.fhir.instance.model.annotations.Child}) since the HL7.org ones will eventually replace the HAPI + * There are two implementations of all of the annotations (e.g. {@link Child} since the HL7.org ones will eventually replace the HAPI * ones. Annotations can't extend each other or implement interfaces or anything like that, so rather than duplicate all of the annotation processing code this method just creates an interface * Proxy to simulate the HAPI annotations if the HL7.org ones are found instead. */ @@ -482,9 +482,8 @@ class ModelScanner { static Set> scanVersionPropertyFile(Set> theDatatypes, Map> theResourceTypes, FhirVersionEnum theVersion, Map, BaseRuntimeElementDefinition> theExistingElementDefinitions) { Set> retVal = new HashSet>(); - InputStream str = theVersion.getVersionImplementation().getFhirVersionPropertiesFile(); - Properties prop = new Properties(); - try { + try (InputStream str = theVersion.getVersionImplementation().getFhirVersionPropertiesFile()) { + Properties prop = new Properties(); prop.load(str); for (Entry nextEntry : prop.entrySet()) { String nextKey = nextEntry.getKey().toString(); @@ -542,8 +541,6 @@ class ModelScanner { } } catch (IOException e) { throw new ConfigurationException("Failed to load model property file from classpath: " + "/ca/uhn/fhir/model/dstu/model.properties"); - } finally { - IOUtils.closeQuietly(str); } return retVal; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java index cd94bc5b4eb..a96f1283ce8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeChildUndeclaredExtensionDefinition.java @@ -27,7 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.text.WordUtils; import org.hl7.fhir.instance.model.api.IBase; import org.hl7.fhir.instance.model.api.IBaseResource; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index c0b28de9b74..4ed208ca9e1 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -38,7 +38,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; -import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.text.WordUtils; import org.hl7.fhir.instance.model.api.*; import java.io.IOException; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java index ed9d04a9c5d..5dcdab30b28 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java @@ -23,8 +23,6 @@ package ca.uhn.fhir.util; import java.io.InputStream; import java.util.Properties; -import org.apache.commons.io.IOUtils; - /** * Used internally by HAPI to log the version of the HAPI FHIR framework * once, when the framework is first loaded by the classloader. @@ -43,17 +41,13 @@ public class VersionUtil { } private static void initialize() { - InputStream is = null; - try { - is = VersionUtil.class.getResourceAsStream("/ca/uhn/fhir/hapi-version.properties"); + try (InputStream is = VersionUtil.class.getResourceAsStream("/ca/uhn/fhir/hapi-version.properties")) { Properties p = new Properties(); p.load(is); ourVersion = p.getProperty("version"); ourLog.info("HAPI FHIR version is: " + ourVersion); } catch (Exception e) { ourLog.warn("Unable to determine HAPI version information", e); - } finally { - IOUtils.closeQuietly(is); } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java index cb4aba958dd..6c166b1ecdf 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java @@ -27,7 +27,7 @@ import ca.uhn.fhir.util.jar.DependencyLogFactory; import ca.uhn.fhir.util.jar.IDependencyLog; import com.ctc.wstx.api.WstxInputProperties; import com.ctc.wstx.stax.WstxOutputFactory; -import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.text.StringEscapeUtils; import org.codehaus.stax2.XMLOutputFactory2; import org.codehaus.stax2.io.EscapingWriterFactory; @@ -54,7 +54,7 @@ public class XmlUtil { private static volatile XMLOutputFactory ourOutputFactory; static { - HashMap validEntityNames = new HashMap(1448); + HashMap validEntityNames = new HashMap<>(1448); validEntityNames.put("AElig", 0x000C6); validEntityNames.put("Aacute", 0x000C1); validEntityNames.put("Abreve", 0x00102); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java index b148db462d9..9e66792870f 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java @@ -212,7 +212,6 @@ public class SchemaBaseValidator implements IValidatorModule { InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase); if (baseIs == null) { - IOUtils.closeQuietly(baseIs); throw new InternalErrorException("Schema file not found: " + pathToBase); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronBaseValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronBaseValidator.java index f3076f98124..7539b9d4572 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronBaseValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronBaseValidator.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.validation.schematron; * 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. @@ -30,12 +30,14 @@ import com.helger.commons.error.list.IErrorList; import com.helger.schematron.ISchematronResource; import com.helger.schematron.SchematronHelper; import com.helger.schematron.xslt.SchematronResourceSCH; -import org.apache.commons.io.IOUtils; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.hl7.fhir.instance.model.api.IBaseResource; import org.oclc.purl.dsdl.svrl.SchematronOutputType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.xml.transform.stream.StreamSource; +import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.util.HashMap; @@ -49,9 +51,13 @@ import java.util.Map; */ public class SchematronBaseValidator implements IValidatorModule { - private Map, ISchematronResource> myClassToSchematron = new HashMap, ISchematronResource>(); + private static final Logger ourLog = LoggerFactory.getLogger(SchematronBaseValidator.class); + private final Map, ISchematronResource> myClassToSchematron = new HashMap<>(); private FhirContext myCtx; + /** + * Constructor + */ public SchematronBaseValidator(FhirContext theContext) { myCtx = theContext; } @@ -66,7 +72,7 @@ public class SchematronBaseValidator implements IValidatorModule { validateResource(ValidationContext.subContext(theCtx, nextSubResource)); } } - + ISchematronResource sch = getSchematron(theCtx); String resourceAsString; if (theCtx.getResourceAsStringEncoding() == EncodingEnum.XML) { @@ -127,15 +133,14 @@ public class SchematronBaseValidator implements IValidatorModule { } String pathToBase = myCtx.getVersion().getPathToSchemaDefinitions() + '/' + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName().toLowerCase() - + ".sch"; - InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase); - try { + + ".sch"; + try (InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase)) { if (baseIs == null) { throw new InternalErrorException("Failed to load schematron for resource '" + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName() + "'. " - + SchemaBaseValidator.RESOURCES_JAR_NOTE); + + SchemaBaseValidator.RESOURCES_JAR_NOTE); } - } finally { - IOUtils.closeQuietly(baseIs); + } catch (IOException e) { + ourLog.error("Failed to close stream", e); } retVal = SchematronResourceSCH.fromClassPath(pathToBase); @@ -143,5 +148,4 @@ public class SchematronBaseValidator implements IValidatorModule { return retVal; } } - } diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml index ef8a954304c..3b2d09abfa2 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml +++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml @@ -38,6 +38,11 @@ hapi-fhir-igpacks ${project.version} + + ca.uhn.hapi.fhir + hapi-fhir-jpaserver-migrate + ${project.version} + org.apache.commons diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java index 1eaf20a9e96..72275d45b16 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java @@ -27,7 +27,7 @@ import ch.qos.logback.core.joran.spi.JoranException; import com.helger.commons.io.file.FileHelper; import org.apache.commons.cli.*; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.text.WordUtils; +import org.apache.commons.text.WordUtils; import org.fusesource.jansi.Ansi; import org.fusesource.jansi.AnsiConsole; import org.slf4j.LoggerFactory; @@ -77,11 +77,6 @@ public abstract class BaseApp { } private void logCommandUsageNoHeader(BaseCommand theCommand) { - System.out.println("Usage:"); - System.out.println(" " + provideCommandName() + " " + theCommand.getCommandName() + " [options]"); - System.out.println(); - System.out.println("Options:"); - // This is passed in from the launch script String columnsString = System.getProperty("columns"); int columns; @@ -93,11 +88,34 @@ public abstract class BaseApp { columns = 80; } + // Usage + System.out.println("Usage:"); + System.out.println(" " + provideCommandName() + " " + theCommand.getCommandName() + " [options]"); + System.out.println(); + + // Description + String wrapped = WordUtils.wrap(theCommand.getCommandDescription(), columns); + System.out.println(wrapped); + System.out.println(); + + // Usage Notes + List usageNotes = theCommand.provideUsageNotes(); + for (String next : usageNotes) { + wrapped = WordUtils.wrap(next, columns); + System.out.println(wrapped); + System.out.println(); + } + + // Options + System.out.println("Options:"); HelpFormatter fmt = new HelpFormatter(); PrintWriter pw = new PrintWriter(System.out); fmt.printOptions(pw, columns, theCommand.getOptions(), 2, 2); pw.flush(); pw.close(); + + // That's it! + System.out.println(); } private void logUsage() { @@ -139,6 +157,7 @@ public abstract class BaseApp { commands.add(new IgPackUploader()); commands.add(new ExportConceptMapToCsvCommand()); commands.add(new ImportCsvToConceptMapCommand()); + commands.add(new BaseMigrateDatabaseCommand()); return commands; } diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseCommand.java index 1b49dce711a..fddefde8aab 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseCommand.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseCommand.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.cli; * 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. @@ -36,7 +36,6 @@ import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -import org.fusesource.jansi.Ansi; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,6 +51,7 @@ import static org.apache.commons.lang3.StringUtils.*; import static org.fusesource.jansi.Ansi.ansi; public abstract class BaseCommand implements Comparable { + public static final String PROMPT = "PROMPT"; protected static final String BASE_URL_PARAM = "t"; protected static final String BASE_URL_PARAM_LONGOPT = "target"; protected static final String BASE_URL_PARAM_NAME = "target"; @@ -72,7 +72,6 @@ public abstract class BaseCommand implements Comparable { protected static final String VERBOSE_LOGGING_PARAM_DESC = "If specified, verbose logging will be used."; // TODO: Don't use qualified names for loggers in HAPI CLI. private static final Logger ourLog = LoggerFactory.getLogger(BaseCommand.class); - public static final String PROMPT = "PROMPT"; protected FhirContext myFhirCtx; public BaseCommand() { @@ -99,7 +98,7 @@ public abstract class BaseCommand implements Comparable { try { retVal = reader.readLine(); } catch (IOException e) { - throw new ParseException("Failed to read input from user: "+ e.toString()); + throw new ParseException("Failed to read input from user: " + e.toString()); } System.out.print(ansi().boldOff().fgDefault()); @@ -117,7 +116,6 @@ public abstract class BaseCommand implements Comparable { } - private void addOption(Options theOptions, OptionGroup theOptionGroup, boolean theRequired, String theOpt, String theLongOpt, boolean theHasArgument, String theArgumentName, String theDescription) { Option option = createOption(theRequired, theOpt, theLongOpt, theHasArgument, theDescription); if (theHasArgument && isNotBlank(theArgumentName)) { @@ -329,7 +327,7 @@ public abstract class BaseCommand implements Comparable { File suppliedFile = new File(FilenameUtils.normalize(theFilepath)); if (suppliedFile.isDirectory()) { - inputFiles = FileUtils.listFiles(suppliedFile, new String[] {"zip"}, false); + inputFiles = FileUtils.listFiles(suppliedFile, new String[]{"zip"}, false); } else { inputFiles = Collections.singletonList(suppliedFile); } @@ -433,4 +431,8 @@ public abstract class BaseCommand implements Comparable { public abstract void run(CommandLine theCommandLine) throws ParseException, ExecutionException; + + public List provideUsageNotes() { + return Collections.emptyList(); + } } diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseMigrateDatabaseCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseMigrateDatabaseCommand.java new file mode 100644 index 00000000000..5de464229f5 --- /dev/null +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseMigrateDatabaseCommand.java @@ -0,0 +1,49 @@ +package ca.uhn.fhir.cli; + +import ca.uhn.fhir.util.VersionEnum; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +public class BaseMigrateDatabaseCommand extends BaseCommand { + @Override + public String getCommandDescription() { + return "This command migrates a HAPI FHIR JPA database from one version of HAPI FHIR to a newer version"; + } + + @Override + public String getCommandName() { + return "migrate-database"; + } + + @Override + public Options getOptions() { + Options retVal = new Options(); + + addRequiredOption(retVal,"u", "url", "URL", "The JDBC database URL"); + addRequiredOption(retVal,"n", "username", "Username", "The JDBC database username"); + addRequiredOption(retVal,"p", "password", "Password", "The JDBC database password"); + addRequiredOption(retVal,"f", "from", "Version", "The database schema version to migrate FROM"); + addRequiredOption(retVal,"t", "to", "Version", "The database schema version to migrate TO"); + + return retVal; + } + + @Override + public List provideUsageNotes() { + String versions = "The following versions are supported: " + + Arrays.stream(VersionEnum.values()).map(Enum::name).collect(Collectors.joining(", ")); + return Collections.singletonList(versions); + } + + @Override + public void run(CommandLine theCommandLine) throws ParseException, ExecutionException { + + } +} diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java index 2a5d0034f22..d97a5557b98 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java +++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/RunServerCommand.java @@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.demo.FhirServerConfig; import ca.uhn.fhir.jpa.demo.FhirServerConfigDstu3; import ca.uhn.fhir.jpa.demo.FhirServerConfigR4; import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.io.IOUtils; @@ -71,6 +72,8 @@ public class RunServerCommand extends BaseCommand { options.addOption(null, OPTION_ALLOW_EXTERNAL_REFS, false, "If this flag is set, the server will allow resources to be persisted contaning external resource references"); options.addOption(null, OPTION_DISABLE_REFERENTIAL_INTEGRITY, false, "If this flag is set, the server will not enforce referential integrity"); + addOptionalOption(options, "u", "url", "Url", "If this option is set, specifies the JDBC URL to use for the database connection"); + Long defaultReuseSearchResults = DaoConfig.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS; String defaultReuseSearchResultsStr = defaultReuseSearchResults == null ? "off" : String.valueOf(defaultReuseSearchResults); options.addOption(null, OPTION_REUSE_SEARCH_RESULTS_MILLIS, true, "The time in milliseconds within which the same results will be returned for multiple identical searches, or \"off\" (default is " + defaultReuseSearchResultsStr + ")"); @@ -106,6 +109,8 @@ public class RunServerCommand extends BaseCommand { ContextHolder.setDisableReferentialIntegrity(true); } + ContextHolder.setDatabaseUrl(theCommandLine.getOptionValue("u")); + String reuseSearchResults = theCommandLine.getOptionValue(OPTION_REUSE_SEARCH_RESULTS_MILLIS); if (reuseSearchResults != null) { if (reuseSearchResults.equals("off")) { diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java index 451ec6dd163..0f051150151 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/ContextHolder.java @@ -12,6 +12,7 @@ public class ContextHolder { private static boolean ourDisableReferentialIntegrity; private static String ourPath; private static Long ourReuseSearchResultsMillis; + private static String ourDatabaseUrl; static { ourReuseSearchResultsMillis = DaoConfig.DEFAULT_REUSE_CACHED_SEARCH_RESULTS_FOR_MILLIS; @@ -27,12 +28,15 @@ public class ContextHolder { case DSTU2: ourPath = "/baseDstu2/"; break; + case DSTU2_1: + break; case DSTU3: ourPath = "/baseDstu3/"; break; case R4: ourPath = "/baseR4/"; break; + case DSTU2_HL7ORG: default: throw new ParseException("FHIR version not supported by this command: " + theCtx.getVersion().getVersion()); } @@ -68,4 +72,12 @@ public class ContextHolder { public static void setDisableReferentialIntegrity(boolean theDisableReferentialIntegrity) { ourDisableReferentialIntegrity = theDisableReferentialIntegrity; } + + public static String getDatabaseUrl() { + return ourDatabaseUrl; + } + + public static void setDatabaseUrl(String theDatabaseUrl) { + ourDatabaseUrl = theDatabaseUrl; + } } diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirDbConfig.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirDbConfig.java index 42a147b98c7..19a7706e450 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirDbConfig.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirDbConfig.java @@ -4,14 +4,38 @@ import java.util.Properties; import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory; import ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect; +import org.apache.commons.dbcp2.BasicDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.sql.DataSource; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; + +@SuppressWarnings("Duplicates") @Configuration public class FhirDbConfig { - - private boolean ourLowMemMode; + /** + * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a + * directory called "jpaserver_derby_files". + * + * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. + */ + @Bean(destroyMethod = "close") + public DataSource dataSource() { + String url = "jdbc:derby:directory:target/jpaserver_derby_files;create=true"; + if (isNotBlank(ContextHolder.getDatabaseUrl())) { + url = ContextHolder.getDatabaseUrl(); + } + + BasicDataSource retVal = new BasicDataSource(); + retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); + retVal.setUrl(url); + retVal.setUsername(""); + retVal.setPassword(""); + return retVal; + } @Bean() public Properties jpaProperties() { diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java index 6001186a104..32270707137 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfig.java @@ -1,11 +1,11 @@ package ca.uhn.fhir.jpa.demo; -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - -import org.apache.commons.dbcp2.BasicDataSource; +import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; import org.apache.commons.lang3.time.DateUtils; import org.hibernate.jpa.HibernatePersistenceProvider; import org.springframework.beans.factory.annotation.Autowire; @@ -18,18 +18,21 @@ import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; -import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; -import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; @Configuration @EnableTransactionManagement() @Import(FhirDbConfig.class) public class FhirServerConfig extends BaseJavaConfigDstu2 { + @Autowired + private DataSource myDataSource; + @Autowired() + @Qualifier("jpaProperties") + private Properties myJpaProperties; + /** * Configure FHIR properties around the the JPA server via this bean */ @@ -43,32 +46,12 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 { return retVal; } - /** - * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a - * directory called "jpaserver_derby_files". - * - * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. - */ - @Bean(destroyMethod = "close") - public DataSource dataSource() { - BasicDataSource retVal = new BasicDataSource(); - retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); - retVal.setUrl("jdbc:derby:directory:target/jpaserver_derby_files;create=true"); - retVal.setUsername(""); - retVal.setPassword(""); - return retVal; - } - - @Autowired() - @Qualifier("jpaProperties") - private Properties myJpaProperties; - @Override @Bean() public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); retVal.setPersistenceUnitName("HAPI_PU"); - retVal.setDataSource(dataSource()); + retVal.setDataSource(myDataSource); retVal.setPackagesToScan("ca.uhn.fhir.jpa.entity"); retVal.setPersistenceProvider(new HibernatePersistenceProvider()); retVal.setJpaProperties(myJpaProperties); @@ -83,7 +66,7 @@ public class FhirServerConfig extends BaseJavaConfigDstu2 { LoggingInterceptor retVal = new LoggingInterceptor(); retVal.setLoggerName("fhirtest.access"); retVal.setMessageFormat( - "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); + "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); retVal.setLogExceptions(true); retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}"); return retVal; diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu3.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu3.java index 6ab41b41972..88053206124 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu3.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigDstu3.java @@ -1,13 +1,12 @@ package ca.uhn.fhir.jpa.demo; -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - -import org.apache.commons.dbcp2.BasicDataSource; +import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; import org.apache.commons.lang3.time.DateUtils; -import org.hibernate.jpa.HibernatePersistenceProvider; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -18,18 +17,15 @@ import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; -import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3; -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu3; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; -import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; /** - * This class isn't used by default by the example, but + * This class isn't used by default by the example, but * you can use it as a config if you want to support DSTU3 * instead of DSTU2 in your server. - * + *

* See https://github.com/jamesagnew/hapi-fhir/issues/278 */ @Configuration @@ -37,6 +33,12 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; @Import(FhirDbConfig.class) public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { + @Autowired + private DataSource myDataSource; + @Autowired() + @Qualifier("jpaProperties") + private Properties myJpaProperties; + /** * Configure FHIR properties around the the JPA server via this bean */ @@ -50,36 +52,16 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { return retVal; } - /** - * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a - * directory called "jpaserver_derby_files". - * - * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. - */ - @Bean(destroyMethod = "close") - public DataSource dataSource() { - BasicDataSource retVal = new BasicDataSource(); - retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); - retVal.setUrl("jdbc:derby:directory:target/jpaserver_derby_files;create=true"); - retVal.setUsername(""); - retVal.setPassword(""); - return retVal; - } - @Override @Bean() public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); retVal.setPersistenceUnitName("HAPI_PU"); - retVal.setDataSource(dataSource()); + retVal.setDataSource(myDataSource); retVal.setJpaProperties(myJpaProperties); return retVal; } - @Autowired() - @Qualifier("jpaProperties") - private Properties myJpaProperties; - /** * Do some fancy logging to create a nice access log that has details about each incoming request. */ @@ -87,7 +69,7 @@ public class FhirServerConfigDstu3 extends BaseJavaConfigDstu3 { LoggingInterceptor retVal = new LoggingInterceptor(); retVal.setLoggerName("fhirtest.access"); retVal.setMessageFormat( - "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); + "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); retVal.setLogExceptions(true); retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}"); return retVal; diff --git a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigR4.java b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigR4.java index 7454ea6b677..3012865d606 100644 --- a/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigR4.java +++ b/hapi-fhir-cli/hapi-fhir-cli-jpaserver/src/main/java/ca/uhn/fhir/jpa/demo/FhirServerConfigR4.java @@ -1,13 +1,12 @@ package ca.uhn.fhir.jpa.demo; -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - -import org.apache.commons.dbcp2.BasicDataSource; +import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; +import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorR4; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; +import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; import org.apache.commons.lang3.time.DateUtils; -import org.hibernate.jpa.HibernatePersistenceProvider; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -18,18 +17,15 @@ import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; -import ca.uhn.fhir.jpa.config.BaseJavaConfigR4; -import ca.uhn.fhir.jpa.dao.DaoConfig; -import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorR4; -import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; -import ca.uhn.fhir.rest.server.interceptor.LoggingInterceptor; -import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; /** - * This class isn't used by default by the example, but + * This class isn't used by default by the example, but * you can use it as a config if you want to support DSTU3 * instead of DSTU2 in your server. - * + *

* See https://github.com/jamesagnew/hapi-fhir/issues/278 */ @Configuration @@ -37,6 +33,12 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor; @Import(FhirDbConfig.class) public class FhirServerConfigR4 extends BaseJavaConfigR4 { + @Autowired + private DataSource myDataSource; + @Autowired() + @Qualifier("jpaProperties") + private Properties myJpaProperties; + /** * Configure FHIR properties around the the JPA server via this bean */ @@ -50,36 +52,16 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { return retVal; } - /** - * The following bean configures the database connection. The 'url' property value of "jdbc:derby:directory:jpaserver_derby_files;create=true" indicates that the server should save resources in a - * directory called "jpaserver_derby_files". - * - * A URL to a remote database could also be placed here, along with login credentials and other properties supported by BasicDataSource. - */ - @Bean(destroyMethod = "close") - public DataSource dataSource() { - BasicDataSource retVal = new BasicDataSource(); - retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver()); - retVal.setUrl("jdbc:derby:directory:target/jpaserver_derby_files;create=true"); - retVal.setUsername(""); - retVal.setPassword(""); - return retVal; - } - @Override @Bean() public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean retVal = super.entityManagerFactory(); retVal.setPersistenceUnitName("HAPI_PU"); - retVal.setDataSource(dataSource()); + retVal.setDataSource(myDataSource); retVal.setJpaProperties(myJpaProperties); return retVal; } - @Autowired() - @Qualifier("jpaProperties") - private Properties myJpaProperties; - /** * Do some fancy logging to create a nice access log that has details about each incoming request. */ @@ -87,7 +69,7 @@ public class FhirServerConfigR4 extends BaseJavaConfigR4 { LoggingInterceptor retVal = new LoggingInterceptor(); retVal.setLoggerName("fhirtest.access"); retVal.setMessageFormat( - "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); + "Path[${servletPath}] Source[${requestHeader.x-forwarded-for}] Operation[${operationType} ${operationName} ${idOrResourceName}] UA[${requestHeader.user-agent}] Params[${requestParameters}] ResponseEncoding[${responseEncodingNoDefault}]"); retVal.setLogExceptions(true); retVal.setErrorMessageFormat("ERROR - ${requestVerb} ${requestUrl}"); return retVal; diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml index cfe0b212030..4fda409f45b 100644 --- a/hapi-fhir-jpaserver-base/pom.xml +++ b/hapi-fhir-jpaserver-base/pom.xml @@ -343,6 +343,10 @@ org.jboss.spec.javax.transaction jboss-transaction-api_1.2_spec + + javax.activation + activation + @@ -399,10 +403,11 @@ - + - 5.3.1.Final + 5.3.6.Final 5.4.1.Final - 5.10.1.Final + 5.10.3.Final 4.4.6 4.5.3 5.5.5 @@ -527,7 +527,7 @@ 9.5.1-5_1 1.2_5 1.7.25 - 5.0.6.RELEASE + 5.0.8.RELEASE 2.0.7.RELEASE 1.5.6.RELEASE @@ -830,6 +830,11 @@ commons-lang3 ${commons_lang3_version} + + org.apache.commons + commons-text + 1.4 + org.apache.derby derby @@ -1446,7 +1451,7 @@ org.codehaus.mojo versions-maven-plugin - 2.6-SNAPSHOT + 2.6 false @@ -1468,7 +1473,7 @@ org.jacoco jacoco-maven-plugin - 0.8.1 + 0.8.2 org.apache.maven.plugins @@ -1644,7 +1649,7 @@ - 3.3.1 + 3.3.9 1.8 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f0f54a83f09..30af41181c7 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -17,16 +17,26 @@ latest versions (dependent HAPI modules listed in brackets): -

  • Spring Framework (JPA): 5.0.3.RELEASE -> 5.0.6.RELEASE
  • -
  • Hibernate OR (JPA): 5.2.16.Final -> 5.3.1.Final
  • -
  • Hibernate Search (JPA): 5.7.1.Final -> 5.10.1.Final
  • -
  • Jetty (CLI): 9.4.8.v20171121 -> 9.4.10.v20180503
  • +
  • Gson (JSON Parser): 2.8.1 -> 2.8.5
  • +
  • Spring Framework (JPA): 5.0.3.RELEASE -> 5.0.8.RELEASE
  • +
  • Hibernate ORM (JPA): 5.2.16.Final -> 5.3.6.Final
  • +
  • Hibernate Search (JPA): 5.7.1.Final -> 5.10.3.Final
  • +
  • Jetty (CLI): 9.4.8.v20171121 -> 9.4.12.v20180830
  • Commons-Codec (All): 1.10 -> 1.11
  • +
  • Commons-Lang (All): 3.7 -> 3.8
  • Commons-IO (All): 2.5 -> 2.6
  • Spring-Data (JPA): 1.11.6.RELEASE -> 2.0.7.RELEASE
  • ]]> + + A new mnandatory library depdendency has been added to hapi-fhir-base, meaning that all + applications using HAPI FHIR must import ti: commons-text. This library has been added as + a few utility methods used by HAPI FHIR that were formerly in the commons-lang3 + project have been moved into commons-text. This library has been added as a non-optional + dependency in the hapi-fhir-base POM, so Maven/Gradle users should not have to make + any changes. + The JPA server now has a configuration item in the DaoConfig to specify which bundle types may be stored as-is on the /Bundle endpoint. By default the following types